{"id":20026294,"url":"https://github.com/ply-ct/ply","last_synced_at":"2025-08-24T22:16:40.697Z","repository":{"id":54875939,"uuid":"129549489","full_name":"ply-ct/ply","owner":"ply-ct","description":"API Automated Testing","archived":false,"fork":false,"pushed_at":"2024-11-10T00:08:52.000Z","size":32436,"stargazers_count":34,"open_issues_count":26,"forks_count":7,"subscribers_count":10,"default_branch":"main","last_synced_at":"2025-03-17T01:32:32.783Z","etag":null,"topics":["continuous-testing","graphql","nodejs","rest-api","test-automation","testing","typescript","workflow"],"latest_commit_sha":null,"homepage":"https://ply-ct.org","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ply-ct.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-04-14T19:49:05.000Z","updated_at":"2025-02-04T17:56:48.000Z","dependencies_parsed_at":"2022-08-14T05:21:05.577Z","dependency_job_id":"ba889f91-41d0-4217-bd43-9541c8b164f8","html_url":"https://github.com/ply-ct/ply","commit_stats":{"total_commits":617,"total_committers":7,"mean_commits":88.14285714285714,"dds":"0.28363047001620745","last_synced_commit":"7c749a7b30b818f346e7db74055ed421296316b8"},"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ply-ct%2Fply","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ply-ct%2Fply/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ply-ct%2Fply/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ply-ct%2Fply/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ply-ct","download_url":"https://codeload.github.com/ply-ct/ply/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247595335,"owners_count":20963943,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["continuous-testing","graphql","nodejs","rest-api","test-automation","testing","typescript","workflow"],"created_at":"2024-11-13T09:06:11.215Z","updated_at":"2025-04-07T05:16:15.074Z","avatar_url":"https://github.com/ply-ct.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ca href=\"https://ply-ct.org\"\u003e\n  \u003cimg alt=\"ply-logo\" src=\"https://raw.githubusercontent.com/ply-ct/ply/master/docs/img/ply.png\" width=\"128\"\u003e\n\u003c/a\u003e\n\u003cbr\u003e\u003cbr\u003e\n\u003ca href=\"https://github.com/ply-ct/ply/actions\"\u003e\n  \u003cimg src=\"https://github.com/ply-ct/ply/workflows/build/badge.svg\" /\u003e\n\u003c/a\u003e\n\u003ca href=\"https://github.com/ply-ct/ply/actions\"\u003e\n  \u003cimg src=\"https://ply-ct.org/badges/ply-ct/ply/workflows/build\" /\u003e\n\u003c/a\u003e\n\u003ca href=\"https://github.com/ply-ct/ply/actions\"\u003e\n  \u003cimg src=\"https://github.com/ply-ct/ply/workflows/CodeQL/badge.svg\" /\u003e\n\u003c/a\u003e\n\n\u003ch2\u003eAPI Automated Testing\n\u003cdiv\u003e\n\u003ca href=\"https://ply-ct.org\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/ply-ct/ply/master/docs/img/wares.png\" width=\"128\" alt=\"Ply your wares\" /\u003e\n\u003c/a\u003e\n\u003c/div\u003e\n\u003c/h2\u003e\n\n  - [Installation](#installation)\n  - [Usage](#usage)\n    - [Submit a request](#submit-a-request)\n    - [Verify response](#verify-response)\n    - [Expected results](#expected-results)\n  - [Documentation](#documentation)\n    - [Guide](https://ply-ct.org/ply/topics/requests)\n    - [CLI](https://ply-ct.org/ply/topics/cli)\n    - [API](https://ply-ct.org/ply/api)\n  - [Demo](https://github.com/ply-ct/ply-demo/)\n  - [VS Code Extension](https://marketplace.visualstudio.com/items?itemName=ply-ct.vscode-ply)\n\n## Installation\n```\nnpm install @ply-ct/ply --save-dev\n```\nOr, to run anywhere:\n```\nnpm install -g @ply-ct/ply\n```\n\n## Usage\nPly API testing starts with a YAML file containing requests. Here's a GET request to retrieve\ntopics for the [ply-demo](https://github.com/ply-ct/ply-demo) repository using\n[GitHub API](https://developer.github.com/v3/repos/#get-all-repository-topics) v3:\n```yaml\nrepositoryTopics:\n  url: 'https://api.github.com/repos/ply-ct/ply-demo/topics'\n  method: GET\n  headers:\n    Accept: application/vnd.github.mercy-preview+json\n```\n\n### Submit a request\nSuppose you save this in a file named \"github.ply.yaml\". Then you can submit the\n`repositoryTopics` request from a command line by typing:\n```\nply -s github.ply.yaml\n```\nThe `-s` argument tells Ply not to verify the response (`-s` is short for `--submit`, \nmeaning submit an *ad hoc* request and don't bother with verification).\n\n### Verify response\nIf you run without `-s` you'll get an error saying, \"Expected result file not found\". Ply verification\nworks by comparing expected vs actual. So a complete test requires an expected result file. Run again\nwith `--create`, and the expected result file will be created from the actual response.\n```shell\nply --create github.ply.yaml\n```\nOutput looks like this:\n```shell\nRequest 'repositoryTopics' submitted at 4/11/2022, 11:19:46:292\nCreating expected result: ./results/expected/github.yaml\nRequest 'repositoryTopics' PASSED in 332 ms\n\nOverall Results: {\"Passed\":1,\"Failed\":0,\"Errored\":0,\"Pending\":0,\"Submitted\":0}\nOverall Time: 373 ms\n```\nDuring execution Ply submits the request and writes **actual** result file \"./results/actual/github.yaml\"\nbased on the response. Because of `--create`, Ply then copies the actual result over **expected** result file \"./results/expected/github.yaml\"\nbefore comparing. This test naturally passes since the results are identical.\n\n### Expected results\nAuto-creating an expected result provides a good starting point. But if you run the request again (without creating), it'll fail:\n```shell\nply github.ply.yaml\nRequest 'repositoryTopics' submitted at 4/11/2022, 11:20:44:478\nRequest 'repositoryTopics' FAILED in 372 ms: Results differ from line 24\n24\n-       x-github-request-id: E8C2:3201:51B1B:D9917:62546332\n+       x-github-request-id: E8C3:7857:386D8:7DDEE:6254636C\n===\n26\n-       x-ratelimit-remaining: '56'\n+       x-ratelimit-remaining: '55'\n===\n29\n-       x-ratelimit-used: '4'\n+       x-ratelimit-used: '5'\n===\n```\n\nBut looking at \"./results/expected/github.yaml\",\nyou'll notice that it includes many response headers that are not of interest for testing purposes. Here's a\ncleaned-up version of similar expected results from [ply-demo](https://github.com/ply-ct/ply-demo/blob/master/test/requests/github-api.ply.yaml#L1):\n```yaml\nrepositoryTopics:\n  request:\n    url: https://api.github.com/repos/${github.organization}/${github.repository}/topics\n    method: GET\n    headers:\n      Accept: application/vnd.github.mercy-preview+json\n  response:\n    status:\n      code: 200\n      message: OK\n    headers:\n      content-type: application/json; charset=utf-8\n    body: |-\n      {\n        \"names\": [\n          \"rest-api\",\n          \"testing\",\n          \"ply\",\n          \"example-project\",\n          \"graphql\",\n          \"typescript\",\n          \"workflow\"\n        ]\n      }\n```\nThe subset of response headers included in expected results YAML are those we care about for comparison.\nIn this test, body content is our main concern.\n\n### Expressions\nSomething else about this example that may be noticed by sharp-eyed observers: our request URL contains\nplaceholders like `${github.organization}`. Ply supports JavaScript [template literal](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals)\nsyntax for substituting dynamic values in both requests and results. Values come from JSON files and/or environment variables,\nas described in the docs under [Values](https://ply-ct.github.io/ply/topics/values).\n\nEven more powerfully, your multi-request suites can embed expressions that reference runtime values from previous responses.\nFor instance, the URL or body of a subsequent request in our github.ply.yaml file could have something like this:\n```\n${@repositoryTopics.response.body.names[0]}\n```\nwhich uses the special `@` character to reference the first topic name from above (resolving to 'rest-api').\nThis enables you to string together sequential requests that each depend on response output from preceding ones.\nCheck out the [Results](https://ply-ct.github.io/ply/topics/results) topic for details and examples.\n\n### Flows\nIf you have [Visual Studio Code](https://code.visualstudio.com/) with the [Ply extension](https://marketplace.visualstudio.com/items?itemName=ply-ct.vscode-ply),\nyou can graphically chain multiple requests into a workflow. See the [Ply flows documentation](https://ply-ct.org/ply/topics/flows) for details.\n\nFlows can include [custom TypeScript steps](https://ply-ct.org/ply/topics/steps) to perform complex interactions and update runtime values.\n\nRunning a flow from the command line is similar to running a request suite:\n```\nply test/flows/movies-api.flow\n```\n\n### GraphQL\nBody content in request YAML can be any text payload (typically JSON). GraphQL syntax is also supported, as in this\nexample which queries the [GitHub GraphQL API](https://docs.github.com/en/graphql) for ply-demo repository topics: \n```yaml\nrepositoryTopicsQuery:\n  url: 'https://api.github.com/graphql'\n  method: POST\n  headers:\n    Authorization: Bearer ${githubToken}\n    Content-Type: application/json\n    User-Agent: ${github.organization}\n  body: |-\n    query {\n      repository(owner: \"${github.organization}\", name: \"${github.repository}\") {\n        repositoryTopics(first: 10) {\n          edges {\n            node {\n              topic {\n                name\n              }\n            }\n          }\n        }\n      }\n    }\n```\n\n\n## Documentation\n\n### Guide\n\u003chttps://ply-ct.org/ply/topics/requests\u003e\n\n### CLI\n\u003chttps://ply-ct.org/ply/topics/cli\u003e\n\n### API\n\u003chttps://ply-ct.org/ply/api\u003e\n\n## Demo Project\n\u003chttps://github.com/ply-ct/ply-demo/\u003e\n\n\n## VS Code Extension\n\u003chttps://marketplace.visualstudio.com/items?itemName=ply-ct.vscode-ply\u003e  \n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fply-ct%2Fply","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fply-ct%2Fply","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fply-ct%2Fply/lists"}