From 82c76b20ca49c7bfe6ca37bdb4f3c0a96c2a2e6e Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Sun, 29 Jan 2023 11:54:27 -0800 Subject: [PATCH 1/4] docs(README): `project.items.archive*()` --- README.md | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) diff --git a/README.md b/README.md index 8ce75ce1..4612c99a 100644 --- a/README.md +++ b/README.md @@ -686,6 +686,139 @@ Map of internal field names to their values. +### `project.items.archive()` + +```js +await project.items.archive(itemNodeId); +``` + +Archives a single item. Resolves with the archived item or with `undefined` if item was not found. + + + + + + + + + + + + + + + + +
+ name + + type + + description +
+ itemNodeId + + string + + +**Required**. The graphql node ID of the project item + +
+ +### `project.items.archiveByContentId()` + +```js +await project.items.archiveByContentId(contentId); +``` + +Archives a single item based on the Node ID of its linked issue or pull request. Resolves with the archived item or with `undefined` if item was not found. + + + + + + + + + + + + + + + + +
+ name + + type + + description +
+ contentId + + string + + +**Required**. The graphql node ID of the issue/pull request the item is linked to. + +
+ +### `project.items.archiveByContentRepositoryAndNumber()` + +```js +await project.items.archiveByContentRepositoryAndNumber( + repositoryName, + issueOrPullRequestNumber +); +``` + +Archives a single item based on the Node ID of its linked issue or pull request. Resolves with the archived item or with `undefined` if item was not found. + + + + + + + + + + + + + + + + + + + + + +
+ name + + type + + description +
+ repositoryName + + string + + +**Required**. The repository name, without the `owner/`. + +
+ issueOrPullRequestNumber + + number + + +**Required**. The number of the issue or pull request. + +
+ ### `project.items.remove()` ```js From 3d4b484866b7105dd90b718ccdb01a2fe46e9248 Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Sun, 29 Jan 2023 13:50:15 -0800 Subject: [PATCH 2/4] test: `project.items.archive()`, `project.items.archiveByContentId()`, `project.items.archiveByContentRepositoryAndNumber()` --- .../fixtures.json | 501 +++++++++++++++++ .../prepare.js | 34 ++ .../api.items.archive-by-content-id/test.js | 15 + .../fixtures.json | 518 ++++++++++++++++++ .../prepare.js | 33 ++ .../test.js | 29 + test/recorded/api.items.archive/fixtures.json | 479 ++++++++++++++++ test/recorded/api.items.archive/prepare.js | 34 ++ test/recorded/api.items.archive/test.js | 15 + .../api.items.get-by-content-id/prepare.js | 2 +- test/recorded/api.items.remove/fixtures.json | 135 ++++- test/recorded/api.items.remove/test.js | 2 +- test/snapshots/recorded.test.js.md | 214 +++++++- test/snapshots/recorded.test.js.snap | Bin 28173 -> 28583 bytes 14 files changed, 1996 insertions(+), 15 deletions(-) create mode 100644 test/recorded/api.items.archive-by-content-id/fixtures.json create mode 100644 test/recorded/api.items.archive-by-content-id/prepare.js create mode 100644 test/recorded/api.items.archive-by-content-id/test.js create mode 100644 test/recorded/api.items.archive-by-content-repository-and-number/fixtures.json create mode 100644 test/recorded/api.items.archive-by-content-repository-and-number/prepare.js create mode 100644 test/recorded/api.items.archive-by-content-repository-and-number/test.js create mode 100644 test/recorded/api.items.archive/fixtures.json create mode 100644 test/recorded/api.items.archive/prepare.js create mode 100644 test/recorded/api.items.archive/test.js diff --git a/test/recorded/api.items.archive-by-content-id/fixtures.json b/test/recorded/api.items.archive-by-content-id/fixtures.json new file mode 100644 index 00000000..22ec57c6 --- /dev/null +++ b/test/recorded/api.items.archive-by-content-id/fixtures.json @@ -0,0 +1,501 @@ +[ + { + "query": "\n query getProjectCoreData($owner: String!, $number: Int!) {\n userOrOrganization: repositoryOwner(login: $owner) {\n ... on ProjectV2Owner {\n projectV2(number: $number) {\n \n id\n title\n url\n fields(first: 50) {\n nodes {\n ... on ProjectV2FieldCommon {\n id\n dataType\n name\n }\n ... on ProjectV2SingleSelectField {\n options {\n id\n name\n }\n }\n ... on ProjectV2IterationField {\n configuration {\n iterations {\n title\n duration\n startDate\n }\n completedIterations {\n title\n duration\n startDate\n }\n duration\n startDay\n }\n }\n }\n }\n\n }\n }\n }\n }\n", + "variables": { + "owner": "github-project-fixtures", + "number": 2 + }, + "response": { + "status": 200, + "url": "https://api.github.com/graphql", + "headers": { + "access-control-allow-origin": "*", + "access-control-expose-headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", + "connection": "close", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'", + "content-type": "application/json; charset=utf-8", + "date": "Sun, 29 Jan 2023 21:48:14 GMT", + "referrer-policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "server": "GitHub.com", + "strict-transport-security": "max-age=31536000; includeSubdomains; preload", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding, Accept, X-Requested-With", + "x-content-type-options": "nosniff", + "x-frame-options": "deny", + "x-github-media-type": "github.v3; format=json", + "x-github-request-id": "EEE6:172E:2BF37:2E0AE:63D6E99E", + "x-ratelimit-limit": "5000", + "x-ratelimit-remaining": "4505", + "x-ratelimit-reset": "1675030730", + "x-ratelimit-resource": "graphql", + "x-ratelimit-used": "495", + "x-xss-protection": "0" + }, + "data": { + "data": { + "userOrOrganization": { + "projectV2": { + "id": "PVT_1", + "title": "@gr2m's Test Fixtures", + "url": "https://github.com/orgs/github-project-fixtures/projects/2", + "fields": { + "nodes": [ + { + "id": "PVTF_1", + "dataType": "TITLE", + "name": "Title" + }, + { + "id": "PVTF_2", + "dataType": "ASSIGNEES", + "name": "Assignees" + }, + { + "id": "PVTSSF_1", + "dataType": "SINGLE_SELECT", + "name": "Status", + "options": [ + { + "id": "f75ad846", + "name": "Todo" + }, + { + "id": "47fc9ee4", + "name": "In Progress" + }, + { + "id": "98236657", + "name": "Done" + } + ] + }, + { + "id": "PVTF_3", + "dataType": "LABELS", + "name": "Labels" + }, + { + "id": "PVTF_4", + "dataType": "LINKED_PULL_REQUESTS", + "name": "Linked pull requests" + }, + { + "id": "PVTF_5", + "dataType": "REVIEWERS", + "name": "Reviewers" + }, + { + "id": "PVTF_6", + "dataType": "REPOSITORY", + "name": "Repository" + }, + { + "id": "PVTF_7", + "dataType": "MILESTONE", + "name": "Milestone" + }, + { + "id": "PVTF_8", + "dataType": "TEXT", + "name": "Text" + }, + { + "id": "PVTF_9", + "dataType": "NUMBER", + "name": "Number" + }, + { + "id": "PVTF_10", + "dataType": "DATE", + "name": "Date" + }, + { + "id": "PVTSSF_2", + "dataType": "SINGLE_SELECT", + "name": "Single select", + "options": [ + { + "id": "b92ebdaa", + "name": "One" + }, + { + "id": "8a0f266e", + "name": "Two" + }, + { + "id": "7ec185b4", + "name": "Three" + } + ] + }, + { + "id": "PVTIF_1", + "dataType": "ITERATION", + "name": "Iteration", + "configuration": { + "iterations": [], + "completedIterations": [ + { + "title": "Iteration 3", + "duration": 14, + "startDate": "2022-08-05" + }, + { + "title": "Iteration 2", + "duration": 14, + "startDate": "2022-07-22" + }, + { + "title": "Iteration 1", + "duration": 14, + "startDate": "2022-07-08" + } + ], + "duration": 14, + "startDay": 5 + } + } + ] + } + } + } + } + } + } + }, + { + "query": "\n query getProjectItemByContentId($id: ID!) {\n node(id: $id) {\n \n ... on Issue {\n title\n url\n projectItems(first: 10) {\n nodes {\n project {\n number\n }\n \n id\n createdAt\n type\n isArchived\n \n content {\n ... on DraftIssue {\n id\n title\n createdAt\n updatedAt\n author: creator {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n }\n ... on Issue {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n }\n ... on PullRequest {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n merged\n }\n }\n\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldDateValue {\n date\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n iterationId\n startDate\n duration\n field {\n ... on ProjectV2IterationField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldSingleSelectValue {\n optionId\n field {\n ... on ProjectV2SingleSelectField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n }\n }\n\n }\n }\n }\n ... on PullRequest {\n title\n url\n projectItems(first: 10) {\n nodes {\n project {\n number\n }\n \n id\n createdAt\n type\n isArchived\n \n content {\n ... on DraftIssue {\n id\n title\n createdAt\n updatedAt\n author: creator {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n }\n ... on Issue {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n }\n ... on PullRequest {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n merged\n }\n }\n\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldDateValue {\n date\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n iterationId\n startDate\n duration\n field {\n ... on ProjectV2IterationField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldSingleSelectValue {\n optionId\n field {\n ... on ProjectV2SingleSelectField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n }\n }\n\n }\n }\n }\n\n }\n }\n", + "variables": { + "id": "I_1" + }, + "response": { + "status": 200, + "url": "https://api.github.com/graphql", + "headers": { + "access-control-allow-origin": "*", + "access-control-expose-headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", + "connection": "close", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'", + "content-type": "application/json; charset=utf-8", + "date": "Sun, 29 Jan 2023 21:48:15 GMT", + "referrer-policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "server": "GitHub.com", + "strict-transport-security": "max-age=31536000; includeSubdomains; preload", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding, Accept, X-Requested-With", + "x-content-type-options": "nosniff", + "x-frame-options": "deny", + "x-github-media-type": "github.v3; format=json", + "x-github-request-id": "EEE7:4F0E:5F3408:63158D:63D6E99F", + "x-ratelimit-limit": "5000", + "x-ratelimit-remaining": "4504", + "x-ratelimit-reset": "1675030730", + "x-ratelimit-resource": "graphql", + "x-ratelimit-used": "496", + "x-xss-protection": "0" + }, + "data": { + "data": { + "node": { + "title": "Issue", + "url": "https://github.com/github-project-fixtures/test-repository/issues/1", + "projectItems": { + "nodes": [ + { + "project": { + "number": 2 + }, + "id": "PVTI_1", + "createdAt": "2022-02-02T12:00:00Z", + "type": "ISSUE", + "isArchived": false, + "content": { + "id": "I_1", + "databaseId": 1001, + "number": 1, + "title": "Issue", + "url": "https://github.com/github-project-fixtures/test-repository/issues/1", + "createdAt": "2022-02-02T12:00:00Z", + "author": { + "login": "gh-project-fixtures" + }, + "assignees": { + "nodes": [] + }, + "labels": { + "nodes": [] + }, + "closed": false, + "milestone": null, + "repository": { + "name": "test-repository" + } + }, + "fieldValues": { + "nodes": [ + { + "__typename": "ProjectV2ItemFieldRepositoryValue" + }, + { + "__typename": "ProjectV2ItemFieldTextValue", + "text": "Issue", + "field": { + "id": "PVTF_1" + } + }, + { + "__typename": "ProjectV2ItemFieldTextValue", + "text": "text", + "field": { + "id": "PVTF_8" + } + }, + { + "__typename": "ProjectV2ItemFieldNumberValue", + "number": 1, + "field": { + "id": "PVTF_9" + } + }, + { + "__typename": "ProjectV2ItemFieldDateValue", + "date": "2020-02-02", + "field": { + "id": "PVTF_10" + } + }, + { + "__typename": "ProjectV2ItemFieldSingleSelectValue", + "optionId": "b92ebdaa", + "field": { + "id": "PVTSSF_2" + } + } + ] + } + } + ] + } + } + } + } + } + }, + { + "query": "\n mutation archiveItem($projectId: ID!, $itemId: ID!) {\n archiveProjectV2Item(input:{projectId: $projectId, itemId: $itemId }) {\n clientMutationId\n }\n }\n", + "variables": { + "projectId": "PVT_1", + "itemId": "PVTI_1" + }, + "response": { + "status": 200, + "url": "https://api.github.com/graphql", + "headers": { + "access-control-allow-origin": "*", + "access-control-expose-headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", + "connection": "close", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'", + "content-type": "application/json; charset=utf-8", + "date": "Sun, 29 Jan 2023 21:48:16 GMT", + "referrer-policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "server": "GitHub.com", + "strict-transport-security": "max-age=31536000; includeSubdomains; preload", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding, Accept, X-Requested-With", + "x-content-type-options": "nosniff", + "x-frame-options": "deny", + "x-github-media-type": "github.v3; format=json", + "x-github-request-id": "EEE8:89D2:649DED:688499:63D6E9A0", + "x-ratelimit-limit": "5000", + "x-ratelimit-remaining": "4503", + "x-ratelimit-reset": "1675030730", + "x-ratelimit-resource": "graphql", + "x-ratelimit-used": "497", + "x-xss-protection": "0" + }, + "data": { + "data": { + "archiveProjectV2Item": { + "clientMutationId": null + } + } + } + } + }, + { + "query": "\n query getProjectItemByContentId($id: ID!) {\n node(id: $id) {\n \n ... on Issue {\n title\n url\n projectItems(first: 10) {\n nodes {\n project {\n number\n }\n \n id\n createdAt\n type\n isArchived\n \n content {\n ... on DraftIssue {\n id\n title\n createdAt\n updatedAt\n author: creator {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n }\n ... on Issue {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n }\n ... on PullRequest {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n merged\n }\n }\n\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldDateValue {\n date\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n iterationId\n startDate\n duration\n field {\n ... on ProjectV2IterationField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldSingleSelectValue {\n optionId\n field {\n ... on ProjectV2SingleSelectField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n }\n }\n\n }\n }\n }\n ... on PullRequest {\n title\n url\n projectItems(first: 10) {\n nodes {\n project {\n number\n }\n \n id\n createdAt\n type\n isArchived\n \n content {\n ... on DraftIssue {\n id\n title\n createdAt\n updatedAt\n author: creator {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n }\n ... on Issue {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n }\n ... on PullRequest {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n merged\n }\n }\n\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldDateValue {\n date\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n iterationId\n startDate\n duration\n field {\n ... on ProjectV2IterationField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldSingleSelectValue {\n optionId\n field {\n ... on ProjectV2SingleSelectField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n }\n }\n\n }\n }\n }\n\n }\n }\n", + "variables": { + "id": "I_1" + }, + "response": { + "status": 200, + "url": "https://api.github.com/graphql", + "headers": { + "access-control-allow-origin": "*", + "access-control-expose-headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", + "connection": "close", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'", + "content-type": "application/json; charset=utf-8", + "date": "Sun, 29 Jan 2023 21:48:17 GMT", + "referrer-policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "server": "GitHub.com", + "strict-transport-security": "max-age=31536000; includeSubdomains; preload", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding, Accept, X-Requested-With", + "x-content-type-options": "nosniff", + "x-frame-options": "deny", + "x-github-media-type": "github.v3; format=json", + "x-github-request-id": "EEE9:5970:35A24:37BEA:63D6E9A1", + "x-ratelimit-limit": "5000", + "x-ratelimit-remaining": "4502", + "x-ratelimit-reset": "1675030730", + "x-ratelimit-resource": "graphql", + "x-ratelimit-used": "498", + "x-xss-protection": "0" + }, + "data": { + "data": { + "node": { + "title": "Issue", + "url": "https://github.com/github-project-fixtures/test-repository/issues/1", + "projectItems": { + "nodes": [ + { + "project": { + "number": 2 + }, + "id": "PVTI_1", + "createdAt": "2022-02-02T12:00:00Z", + "type": "ISSUE", + "isArchived": true, + "content": { + "id": "I_1", + "databaseId": 1001, + "number": 1, + "title": "Issue", + "url": "https://github.com/github-project-fixtures/test-repository/issues/1", + "createdAt": "2022-02-02T12:00:00Z", + "author": { + "login": "gh-project-fixtures" + }, + "assignees": { + "nodes": [] + }, + "labels": { + "nodes": [] + }, + "closed": false, + "milestone": null, + "repository": { + "name": "test-repository" + } + }, + "fieldValues": { + "nodes": [ + { + "__typename": "ProjectV2ItemFieldRepositoryValue" + }, + { + "__typename": "ProjectV2ItemFieldTextValue", + "text": "Issue", + "field": { + "id": "PVTF_1" + } + }, + { + "__typename": "ProjectV2ItemFieldTextValue", + "text": "text", + "field": { + "id": "PVTF_8" + } + }, + { + "__typename": "ProjectV2ItemFieldNumberValue", + "number": 1, + "field": { + "id": "PVTF_9" + } + }, + { + "__typename": "ProjectV2ItemFieldDateValue", + "date": "2020-02-02", + "field": { + "id": "PVTF_10" + } + }, + { + "__typename": "ProjectV2ItemFieldSingleSelectValue", + "optionId": "b92ebdaa", + "field": { + "id": "PVTSSF_2" + } + } + ] + } + } + ] + } + } + } + } + } + }, + { + "query": "\n query getProjectItemByContentId($id: ID!) {\n node(id: $id) {\n \n ... on Issue {\n title\n url\n projectItems(first: 10) {\n nodes {\n project {\n number\n }\n \n id\n createdAt\n type\n isArchived\n \n content {\n ... on DraftIssue {\n id\n title\n createdAt\n updatedAt\n author: creator {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n }\n ... on Issue {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n }\n ... on PullRequest {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n merged\n }\n }\n\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldDateValue {\n date\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n iterationId\n startDate\n duration\n field {\n ... on ProjectV2IterationField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldSingleSelectValue {\n optionId\n field {\n ... on ProjectV2SingleSelectField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n }\n }\n\n }\n }\n }\n ... on PullRequest {\n title\n url\n projectItems(first: 10) {\n nodes {\n project {\n number\n }\n \n id\n createdAt\n type\n isArchived\n \n content {\n ... on DraftIssue {\n id\n title\n createdAt\n updatedAt\n author: creator {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n }\n ... on Issue {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n }\n ... on PullRequest {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n merged\n }\n }\n\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldDateValue {\n date\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n iterationId\n startDate\n duration\n field {\n ... on ProjectV2IterationField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldSingleSelectValue {\n optionId\n field {\n ... on ProjectV2SingleSelectField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n }\n }\n\n }\n }\n }\n\n }\n }\n", + "variables": { + "id": "" + }, + "response": { + "status": 200, + "url": "https://api.github.com/graphql", + "headers": { + "access-control-allow-origin": "*", + "access-control-expose-headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", + "connection": "close", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'", + "content-type": "application/json; charset=utf-8", + "date": "Sun, 29 Jan 2023 21:48:18 GMT", + "referrer-policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "server": "GitHub.com", + "strict-transport-security": "max-age=31536000; includeSubdomains; preload", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding, Accept, X-Requested-With", + "x-content-type-options": "nosniff", + "x-frame-options": "deny", + "x-github-media-type": "github.v3; format=json", + "x-github-request-id": "EEEA:7412:522968:560A0A:63D6E9A2", + "x-ratelimit-limit": "5000", + "x-ratelimit-remaining": "4501", + "x-ratelimit-reset": "1675030730", + "x-ratelimit-resource": "graphql", + "x-ratelimit-used": "499", + "x-xss-protection": "0" + }, + "data": { + "data": { + "node": null + }, + "errors": [ + { + "type": "NOT_FOUND", + "path": [ + "node" + ], + "locations": [ + { + "line": 3, + "column": 5 + } + ], + "message": "Could not resolve to a node with the global id of ''" + } + ] + } + } + } +] \ No newline at end of file diff --git a/test/recorded/api.items.archive-by-content-id/prepare.js b/test/recorded/api.items.archive-by-content-id/prepare.js new file mode 100644 index 00000000..4f975031 --- /dev/null +++ b/test/recorded/api.items.archive-by-content-id/prepare.js @@ -0,0 +1,34 @@ +// @ts-check + +/** + * Prepare state in order to record fixtures for test.js. Returns array of arguments that will be passed + * passed as `test(project, ...arguments)`. + * + * @param {import("@octokit/openapi-types").components["schemas"]["repository"]} repository + * @param {import("@octokit/core").Octokit} octokit + * @param {import("../../..").default<{text: string, number: number, date: string, singleSelect: "One" | "Two" | "Three"}>} project + * + * @returns {Promise<[string]>} + */ +export async function prepare(repository, octokit, project) { + // create a test issue + const { data: issue } = await octokit.request( + "POST /repos/{owner}/{repo}/issues", + { + owner: repository.owner.login, + repo: repository.name, + title: "Issue", + body: "This is a test issue", + } + ); + + // add issue to project + await project.items.add(issue.node_id, { + text: "text", + number: "1", + date: new Date("2020-02-02").toISOString(), + singleSelect: "One", + }); + + return [issue.node_id]; +} diff --git a/test/recorded/api.items.archive-by-content-id/test.js b/test/recorded/api.items.archive-by-content-id/test.js new file mode 100644 index 00000000..17befee5 --- /dev/null +++ b/test/recorded/api.items.archive-by-content-id/test.js @@ -0,0 +1,15 @@ +// @ts-check + +/** + * @param {import("../../..").default} project + * @param {string} [contentId] + */ +export async function test(project, contentId = "I_1") { + const first = await project.items.archiveByContentId(contentId); + // 2nd time it won't send a mutation + const second = await project.items.archiveByContentId(contentId); + // resolves with undefined if not found + const third = await project.items.archiveByContentId(""); + + return [first, second, third]; +} diff --git a/test/recorded/api.items.archive-by-content-repository-and-number/fixtures.json b/test/recorded/api.items.archive-by-content-repository-and-number/fixtures.json new file mode 100644 index 00000000..ecc9c251 --- /dev/null +++ b/test/recorded/api.items.archive-by-content-repository-and-number/fixtures.json @@ -0,0 +1,518 @@ +[ + { + "query": "\n query getProjectCoreData($owner: String!, $number: Int!) {\n userOrOrganization: repositoryOwner(login: $owner) {\n ... on ProjectV2Owner {\n projectV2(number: $number) {\n \n id\n title\n url\n fields(first: 50) {\n nodes {\n ... on ProjectV2FieldCommon {\n id\n dataType\n name\n }\n ... on ProjectV2SingleSelectField {\n options {\n id\n name\n }\n }\n ... on ProjectV2IterationField {\n configuration {\n iterations {\n title\n duration\n startDate\n }\n completedIterations {\n title\n duration\n startDate\n }\n duration\n startDay\n }\n }\n }\n }\n\n }\n }\n }\n }\n", + "variables": { + "owner": "github-project-fixtures", + "number": 2 + }, + "response": { + "status": 200, + "url": "https://api.github.com/graphql", + "headers": { + "access-control-allow-origin": "*", + "access-control-expose-headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", + "connection": "close", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'", + "content-type": "application/json; charset=utf-8", + "date": "Sun, 29 Jan 2023 21:47:31 GMT", + "referrer-policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "server": "GitHub.com", + "strict-transport-security": "max-age=31536000; includeSubdomains; preload", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding, Accept, X-Requested-With", + "x-content-type-options": "nosniff", + "x-frame-options": "deny", + "x-github-media-type": "github.v3; format=json", + "x-github-request-id": "EEC2:8D65:25D6D:27CFE:63D6E973", + "x-ratelimit-limit": "5000", + "x-ratelimit-remaining": "4514", + "x-ratelimit-reset": "1675030730", + "x-ratelimit-resource": "graphql", + "x-ratelimit-used": "486", + "x-xss-protection": "0" + }, + "data": { + "data": { + "userOrOrganization": { + "projectV2": { + "id": "PVT_1", + "title": "@gr2m's Test Fixtures", + "url": "https://github.com/orgs/github-project-fixtures/projects/2", + "fields": { + "nodes": [ + { + "id": "PVTF_1", + "dataType": "TITLE", + "name": "Title" + }, + { + "id": "PVTF_2", + "dataType": "ASSIGNEES", + "name": "Assignees" + }, + { + "id": "PVTSSF_1", + "dataType": "SINGLE_SELECT", + "name": "Status", + "options": [ + { + "id": "f75ad846", + "name": "Todo" + }, + { + "id": "47fc9ee4", + "name": "In Progress" + }, + { + "id": "98236657", + "name": "Done" + } + ] + }, + { + "id": "PVTF_3", + "dataType": "LABELS", + "name": "Labels" + }, + { + "id": "PVTF_4", + "dataType": "LINKED_PULL_REQUESTS", + "name": "Linked pull requests" + }, + { + "id": "PVTF_5", + "dataType": "REVIEWERS", + "name": "Reviewers" + }, + { + "id": "PVTF_6", + "dataType": "REPOSITORY", + "name": "Repository" + }, + { + "id": "PVTF_7", + "dataType": "MILESTONE", + "name": "Milestone" + }, + { + "id": "PVTF_8", + "dataType": "TEXT", + "name": "Text" + }, + { + "id": "PVTF_9", + "dataType": "NUMBER", + "name": "Number" + }, + { + "id": "PVTF_10", + "dataType": "DATE", + "name": "Date" + }, + { + "id": "PVTSSF_2", + "dataType": "SINGLE_SELECT", + "name": "Single select", + "options": [ + { + "id": "b92ebdaa", + "name": "One" + }, + { + "id": "8a0f266e", + "name": "Two" + }, + { + "id": "7ec185b4", + "name": "Three" + } + ] + }, + { + "id": "PVTIF_1", + "dataType": "ITERATION", + "name": "Iteration", + "configuration": { + "iterations": [], + "completedIterations": [ + { + "title": "Iteration 3", + "duration": 14, + "startDate": "2022-08-05" + }, + { + "title": "Iteration 2", + "duration": 14, + "startDate": "2022-07-22" + }, + { + "title": "Iteration 1", + "duration": 14, + "startDate": "2022-07-08" + } + ], + "duration": 14, + "startDay": 5 + } + } + ] + } + } + } + } + } + } + }, + { + "query": "\n query getProjectItemByContentRepositoryAndNumber($owner: String!, $repositoryName: String!, $number: Int!) {\n repositoryOwner(login: $owner) {\n repository(name: $repositoryName) {\n issueOrPullRequest(number: $number) {\n \n ... on Issue {\n title\n url\n projectItems(first: 10) {\n nodes {\n project {\n number\n }\n \n id\n createdAt\n type\n isArchived\n \n content {\n ... on DraftIssue {\n id\n title\n createdAt\n updatedAt\n author: creator {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n }\n ... on Issue {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n }\n ... on PullRequest {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n merged\n }\n }\n\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldDateValue {\n date\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n iterationId\n startDate\n duration\n field {\n ... on ProjectV2IterationField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldSingleSelectValue {\n optionId\n field {\n ... on ProjectV2SingleSelectField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n }\n }\n\n }\n }\n }\n ... on PullRequest {\n title\n url\n projectItems(first: 10) {\n nodes {\n project {\n number\n }\n \n id\n createdAt\n type\n isArchived\n \n content {\n ... on DraftIssue {\n id\n title\n createdAt\n updatedAt\n author: creator {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n }\n ... on Issue {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n }\n ... on PullRequest {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n merged\n }\n }\n\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldDateValue {\n date\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n iterationId\n startDate\n duration\n field {\n ... on ProjectV2IterationField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldSingleSelectValue {\n optionId\n field {\n ... on ProjectV2SingleSelectField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n }\n }\n\n }\n }\n }\n\n }\n }\n }\n }\n", + "variables": { + "owner": "github-project-fixtures", + "repositoryName": "test-repository", + "number": 1 + }, + "response": { + "status": 200, + "url": "https://api.github.com/graphql", + "headers": { + "access-control-allow-origin": "*", + "access-control-expose-headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", + "connection": "close", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'", + "content-type": "application/json; charset=utf-8", + "date": "Sun, 29 Jan 2023 21:47:32 GMT", + "referrer-policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "server": "GitHub.com", + "strict-transport-security": "max-age=31536000; includeSubdomains; preload", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding, Accept, X-Requested-With", + "x-content-type-options": "nosniff", + "x-frame-options": "deny", + "x-github-media-type": "github.v3; format=json", + "x-github-request-id": "EEC3:54E3:662301:6A0443:63D6E974", + "x-ratelimit-limit": "5000", + "x-ratelimit-remaining": "4513", + "x-ratelimit-reset": "1675030730", + "x-ratelimit-resource": "graphql", + "x-ratelimit-used": "487", + "x-xss-protection": "0" + }, + "data": { + "data": { + "repositoryOwner": { + "repository": { + "issueOrPullRequest": { + "title": "Issue", + "url": "https://github.com/github-project-fixtures/test-repository/issues/1", + "projectItems": { + "nodes": [ + { + "project": { + "number": 2 + }, + "id": "PVTI_1", + "createdAt": "2022-02-02T12:00:00Z", + "type": "ISSUE", + "isArchived": false, + "content": { + "id": "I_1", + "databaseId": 1001, + "number": 1, + "title": "Issue", + "url": "https://github.com/github-project-fixtures/test-repository/issues/1", + "createdAt": "2022-02-02T12:00:00Z", + "author": { + "login": "gh-project-fixtures" + }, + "assignees": { + "nodes": [] + }, + "labels": { + "nodes": [] + }, + "closed": false, + "milestone": null, + "repository": { + "name": "test-repository" + } + }, + "fieldValues": { + "nodes": [ + { + "__typename": "ProjectV2ItemFieldRepositoryValue" + }, + { + "__typename": "ProjectV2ItemFieldTextValue", + "text": "Issue", + "field": { + "id": "PVTF_1" + } + }, + { + "__typename": "ProjectV2ItemFieldTextValue", + "text": "text", + "field": { + "id": "PVTF_8" + } + }, + { + "__typename": "ProjectV2ItemFieldNumberValue", + "number": 1, + "field": { + "id": "PVTF_9" + } + }, + { + "__typename": "ProjectV2ItemFieldDateValue", + "date": "2020-02-02", + "field": { + "id": "PVTF_10" + } + }, + { + "__typename": "ProjectV2ItemFieldSingleSelectValue", + "optionId": "b92ebdaa", + "field": { + "id": "PVTSSF_2" + } + } + ] + } + } + ] + } + } + } + } + } + } + } + }, + { + "query": "\n mutation archiveItem($projectId: ID!, $itemId: ID!) {\n archiveProjectV2Item(input:{projectId: $projectId, itemId: $itemId }) {\n clientMutationId\n }\n }\n", + "variables": { + "projectId": "PVT_1", + "itemId": "PVTI_1" + }, + "response": { + "status": 200, + "url": "https://api.github.com/graphql", + "headers": { + "access-control-allow-origin": "*", + "access-control-expose-headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", + "connection": "close", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'", + "content-type": "application/json; charset=utf-8", + "date": "Sun, 29 Jan 2023 21:47:33 GMT", + "referrer-policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "server": "GitHub.com", + "strict-transport-security": "max-age=31536000; includeSubdomains; preload", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding, Accept, X-Requested-With", + "x-content-type-options": "nosniff", + "x-frame-options": "deny", + "x-github-media-type": "github.v3; format=json", + "x-github-request-id": "EEC5:7EE3:28567:2A54D:63D6E975", + "x-ratelimit-limit": "5000", + "x-ratelimit-remaining": "4512", + "x-ratelimit-reset": "1675030730", + "x-ratelimit-resource": "graphql", + "x-ratelimit-used": "488", + "x-xss-protection": "0" + }, + "data": { + "data": { + "archiveProjectV2Item": { + "clientMutationId": null + } + } + } + } + }, + { + "query": "\n query getProjectItemByContentRepositoryAndNumber($owner: String!, $repositoryName: String!, $number: Int!) {\n repositoryOwner(login: $owner) {\n repository(name: $repositoryName) {\n issueOrPullRequest(number: $number) {\n \n ... on Issue {\n title\n url\n projectItems(first: 10) {\n nodes {\n project {\n number\n }\n \n id\n createdAt\n type\n isArchived\n \n content {\n ... on DraftIssue {\n id\n title\n createdAt\n updatedAt\n author: creator {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n }\n ... on Issue {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n }\n ... on PullRequest {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n merged\n }\n }\n\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldDateValue {\n date\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n iterationId\n startDate\n duration\n field {\n ... on ProjectV2IterationField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldSingleSelectValue {\n optionId\n field {\n ... on ProjectV2SingleSelectField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n }\n }\n\n }\n }\n }\n ... on PullRequest {\n title\n url\n projectItems(first: 10) {\n nodes {\n project {\n number\n }\n \n id\n createdAt\n type\n isArchived\n \n content {\n ... on DraftIssue {\n id\n title\n createdAt\n updatedAt\n author: creator {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n }\n ... on Issue {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n }\n ... on PullRequest {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n merged\n }\n }\n\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldDateValue {\n date\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n iterationId\n startDate\n duration\n field {\n ... on ProjectV2IterationField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldSingleSelectValue {\n optionId\n field {\n ... on ProjectV2SingleSelectField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n }\n }\n\n }\n }\n }\n\n }\n }\n }\n }\n", + "variables": { + "owner": "github-project-fixtures", + "repositoryName": "test-repository", + "number": 1 + }, + "response": { + "status": 200, + "url": "https://api.github.com/graphql", + "headers": { + "access-control-allow-origin": "*", + "access-control-expose-headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", + "connection": "close", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'", + "content-type": "application/json; charset=utf-8", + "date": "Sun, 29 Jan 2023 21:47:34 GMT", + "referrer-policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "server": "GitHub.com", + "strict-transport-security": "max-age=31536000; includeSubdomains; preload", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding, Accept, X-Requested-With", + "x-content-type-options": "nosniff", + "x-frame-options": "deny", + "x-github-media-type": "github.v3; format=json", + "x-github-request-id": "EEC6:89D2:646202:6846EA:63D6E976", + "x-ratelimit-limit": "5000", + "x-ratelimit-remaining": "4511", + "x-ratelimit-reset": "1675030730", + "x-ratelimit-resource": "graphql", + "x-ratelimit-used": "489", + "x-xss-protection": "0" + }, + "data": { + "data": { + "repositoryOwner": { + "repository": { + "issueOrPullRequest": { + "title": "Issue", + "url": "https://github.com/github-project-fixtures/test-repository/issues/1", + "projectItems": { + "nodes": [ + { + "project": { + "number": 2 + }, + "id": "PVTI_1", + "createdAt": "2022-02-02T12:00:00Z", + "type": "ISSUE", + "isArchived": true, + "content": { + "id": "I_1", + "databaseId": 1001, + "number": 1, + "title": "Issue", + "url": "https://github.com/github-project-fixtures/test-repository/issues/1", + "createdAt": "2022-02-02T12:00:00Z", + "author": { + "login": "gh-project-fixtures" + }, + "assignees": { + "nodes": [] + }, + "labels": { + "nodes": [] + }, + "closed": false, + "milestone": null, + "repository": { + "name": "test-repository" + } + }, + "fieldValues": { + "nodes": [ + { + "__typename": "ProjectV2ItemFieldRepositoryValue" + }, + { + "__typename": "ProjectV2ItemFieldTextValue", + "text": "Issue", + "field": { + "id": "PVTF_1" + } + }, + { + "__typename": "ProjectV2ItemFieldTextValue", + "text": "text", + "field": { + "id": "PVTF_8" + } + }, + { + "__typename": "ProjectV2ItemFieldNumberValue", + "number": 1, + "field": { + "id": "PVTF_9" + } + }, + { + "__typename": "ProjectV2ItemFieldDateValue", + "date": "2020-02-02", + "field": { + "id": "PVTF_10" + } + }, + { + "__typename": "ProjectV2ItemFieldSingleSelectValue", + "optionId": "b92ebdaa", + "field": { + "id": "PVTSSF_2" + } + } + ] + } + } + ] + } + } + } + } + } + } + } + }, + { + "query": "\n query getProjectItemByContentRepositoryAndNumber($owner: String!, $repositoryName: String!, $number: Int!) {\n repositoryOwner(login: $owner) {\n repository(name: $repositoryName) {\n issueOrPullRequest(number: $number) {\n \n ... on Issue {\n title\n url\n projectItems(first: 10) {\n nodes {\n project {\n number\n }\n \n id\n createdAt\n type\n isArchived\n \n content {\n ... on DraftIssue {\n id\n title\n createdAt\n updatedAt\n author: creator {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n }\n ... on Issue {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n }\n ... on PullRequest {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n merged\n }\n }\n\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldDateValue {\n date\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n iterationId\n startDate\n duration\n field {\n ... on ProjectV2IterationField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldSingleSelectValue {\n optionId\n field {\n ... on ProjectV2SingleSelectField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n }\n }\n\n }\n }\n }\n ... on PullRequest {\n title\n url\n projectItems(first: 10) {\n nodes {\n project {\n number\n }\n \n id\n createdAt\n type\n isArchived\n \n content {\n ... on DraftIssue {\n id\n title\n createdAt\n updatedAt\n author: creator {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n }\n ... on Issue {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n }\n ... on PullRequest {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n merged\n }\n }\n\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldDateValue {\n date\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n iterationId\n startDate\n duration\n field {\n ... on ProjectV2IterationField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldSingleSelectValue {\n optionId\n field {\n ... on ProjectV2SingleSelectField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n }\n }\n\n }\n }\n }\n\n }\n }\n }\n }\n", + "variables": { + "owner": "github-project-fixtures", + "repositoryName": "", + "number": 1 + }, + "response": { + "status": 200, + "url": "https://api.github.com/graphql", + "headers": { + "access-control-allow-origin": "*", + "access-control-expose-headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", + "connection": "close", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'", + "content-type": "application/json; charset=utf-8", + "date": "Sun, 29 Jan 2023 21:47:35 GMT", + "referrer-policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "server": "GitHub.com", + "strict-transport-security": "max-age=31536000; includeSubdomains; preload", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding, Accept, X-Requested-With", + "x-content-type-options": "nosniff", + "x-frame-options": "deny", + "x-github-media-type": "github.v3; format=json", + "x-github-request-id": "EEC7:6763:563C4A:5A1E4A:63D6E977", + "x-ratelimit-limit": "5000", + "x-ratelimit-remaining": "4510", + "x-ratelimit-reset": "1675030730", + "x-ratelimit-resource": "graphql", + "x-ratelimit-used": "490", + "x-xss-protection": "0" + }, + "data": { + "data": { + "repositoryOwner": { + "repository": null + } + }, + "errors": [ + { + "type": "NOT_FOUND", + "path": [ + "repositoryOwner", + "repository" + ], + "locations": [ + { + "line": 4, + "column": 7 + } + ], + "message": "Could not resolve to a Repository with the name 'github-project-fixtures/'." + } + ] + } + } + } +] \ No newline at end of file diff --git a/test/recorded/api.items.archive-by-content-repository-and-number/prepare.js b/test/recorded/api.items.archive-by-content-repository-and-number/prepare.js new file mode 100644 index 00000000..a2635673 --- /dev/null +++ b/test/recorded/api.items.archive-by-content-repository-and-number/prepare.js @@ -0,0 +1,33 @@ +// @ts-check + +/** + * Prepare state in order to record fixtures for test.js. Returns array of arguments that will be passed + * passed as `test(project, ...arguments)`. + * + * @param {import("@octokit/openapi-types").components["schemas"]["repository"]} repository + * @param {import("@octokit/core").Octokit} octokit + * @param {import("../../..").default<{text: string, number: number, date: string, singleSelect: "One" | "Two" | "Three"}>} project + * @returns {Promise<[string, number]>} + */ +export async function prepare(repository, octokit, project) { + // create a test issue + const { data: issue } = await octokit.request( + "POST /repos/{owner}/{repo}/issues", + { + owner: repository.owner.login, + repo: repository.name, + title: "Issue", + body: "This is a test issue", + } + ); + + // add issue to project + await project.items.add(issue.node_id, { + text: "text", + number: "1", + date: new Date("2020-02-02").toISOString(), + singleSelect: "One", + }); + + return [repository.name, issue.number]; +} diff --git a/test/recorded/api.items.archive-by-content-repository-and-number/test.js b/test/recorded/api.items.archive-by-content-repository-and-number/test.js new file mode 100644 index 00000000..97895e72 --- /dev/null +++ b/test/recorded/api.items.archive-by-content-repository-and-number/test.js @@ -0,0 +1,29 @@ +// @ts-check + +/** + * @param {import("../../../").default} project + * @param {string} [repositoryName] + * @param {number} [issueNumber] + */ +export async function test( + project, + repositoryName = "test-repository", + issueNumber = 1 +) { + const first = await project.items.archiveByContentRepositoryAndNumber( + repositoryName, + issueNumber + ); + // 2nd time it won't send a mutation + const second = await project.items.archiveByContentRepositoryAndNumber( + repositoryName, + issueNumber + ); + // resolves with undefined if not found + const third = await project.items.archiveByContentRepositoryAndNumber( + "", + 1 + ); + + return [first, second, third]; +} diff --git a/test/recorded/api.items.archive/fixtures.json b/test/recorded/api.items.archive/fixtures.json new file mode 100644 index 00000000..e4bc61d9 --- /dev/null +++ b/test/recorded/api.items.archive/fixtures.json @@ -0,0 +1,479 @@ +[ + { + "query": "\n query getProjectCoreData($owner: String!, $number: Int!) {\n userOrOrganization: repositoryOwner(login: $owner) {\n ... on ProjectV2Owner {\n projectV2(number: $number) {\n \n id\n title\n url\n fields(first: 50) {\n nodes {\n ... on ProjectV2FieldCommon {\n id\n dataType\n name\n }\n ... on ProjectV2SingleSelectField {\n options {\n id\n name\n }\n }\n ... on ProjectV2IterationField {\n configuration {\n iterations {\n title\n duration\n startDate\n }\n completedIterations {\n title\n duration\n startDate\n }\n duration\n startDay\n }\n }\n }\n }\n\n }\n }\n }\n }\n", + "variables": { + "owner": "github-project-fixtures", + "number": 2 + }, + "response": { + "status": 200, + "url": "https://api.github.com/graphql", + "headers": { + "access-control-allow-origin": "*", + "access-control-expose-headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", + "connection": "close", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'", + "content-type": "application/json; charset=utf-8", + "date": "Sun, 29 Jan 2023 21:49:17 GMT", + "referrer-policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "server": "GitHub.com", + "strict-transport-security": "max-age=31536000; includeSubdomains; preload", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding, Accept, X-Requested-With", + "x-content-type-options": "nosniff", + "x-frame-options": "deny", + "x-github-media-type": "github.v3; format=json", + "x-github-request-id": "EF0D:7F27:2A623:2CA51:63D6E9DD", + "x-ratelimit-limit": "5000", + "x-ratelimit-remaining": "4486", + "x-ratelimit-reset": "1675030730", + "x-ratelimit-resource": "graphql", + "x-ratelimit-used": "514", + "x-xss-protection": "0" + }, + "data": { + "data": { + "userOrOrganization": { + "projectV2": { + "id": "PVT_1", + "title": "@gr2m's Test Fixtures", + "url": "https://github.com/orgs/github-project-fixtures/projects/2", + "fields": { + "nodes": [ + { + "id": "PVTF_1", + "dataType": "TITLE", + "name": "Title" + }, + { + "id": "PVTF_2", + "dataType": "ASSIGNEES", + "name": "Assignees" + }, + { + "id": "PVTSSF_1", + "dataType": "SINGLE_SELECT", + "name": "Status", + "options": [ + { + "id": "f75ad846", + "name": "Todo" + }, + { + "id": "47fc9ee4", + "name": "In Progress" + }, + { + "id": "98236657", + "name": "Done" + } + ] + }, + { + "id": "PVTF_3", + "dataType": "LABELS", + "name": "Labels" + }, + { + "id": "PVTF_4", + "dataType": "LINKED_PULL_REQUESTS", + "name": "Linked pull requests" + }, + { + "id": "PVTF_5", + "dataType": "REVIEWERS", + "name": "Reviewers" + }, + { + "id": "PVTF_6", + "dataType": "REPOSITORY", + "name": "Repository" + }, + { + "id": "PVTF_7", + "dataType": "MILESTONE", + "name": "Milestone" + }, + { + "id": "PVTF_8", + "dataType": "TEXT", + "name": "Text" + }, + { + "id": "PVTF_9", + "dataType": "NUMBER", + "name": "Number" + }, + { + "id": "PVTF_10", + "dataType": "DATE", + "name": "Date" + }, + { + "id": "PVTSSF_2", + "dataType": "SINGLE_SELECT", + "name": "Single select", + "options": [ + { + "id": "b92ebdaa", + "name": "One" + }, + { + "id": "8a0f266e", + "name": "Two" + }, + { + "id": "7ec185b4", + "name": "Three" + } + ] + }, + { + "id": "PVTIF_1", + "dataType": "ITERATION", + "name": "Iteration", + "configuration": { + "iterations": [], + "completedIterations": [ + { + "title": "Iteration 3", + "duration": 14, + "startDate": "2022-08-05" + }, + { + "title": "Iteration 2", + "duration": 14, + "startDate": "2022-07-22" + }, + { + "title": "Iteration 1", + "duration": 14, + "startDate": "2022-07-08" + } + ], + "duration": 14, + "startDay": 5 + } + } + ] + } + } + } + } + } + } + }, + { + "query": "\n query getProjectItem($id:ID!) {\n node(id:$id){\n ... on ProjectV2Item {\n \n id\n createdAt\n type\n isArchived\n \n content {\n ... on DraftIssue {\n id\n title\n createdAt\n updatedAt\n author: creator {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n }\n ... on Issue {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n }\n ... on PullRequest {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n merged\n }\n }\n\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldDateValue {\n date\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n iterationId\n startDate\n duration\n field {\n ... on ProjectV2IterationField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldSingleSelectValue {\n optionId\n field {\n ... on ProjectV2SingleSelectField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n }\n }\n\n }\n }\n }\n", + "variables": { + "id": "PVTI_1" + }, + "response": { + "status": 200, + "url": "https://api.github.com/graphql", + "headers": { + "access-control-allow-origin": "*", + "access-control-expose-headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", + "connection": "close", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'", + "content-type": "application/json; charset=utf-8", + "date": "Sun, 29 Jan 2023 21:49:18 GMT", + "referrer-policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "server": "GitHub.com", + "strict-transport-security": "max-age=31536000; includeSubdomains; preload", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding, Accept, X-Requested-With", + "x-content-type-options": "nosniff", + "x-frame-options": "deny", + "x-github-media-type": "github.v3; format=json", + "x-github-request-id": "EF0E:425D:2A5E7:2CA81:63D6E9DE", + "x-ratelimit-limit": "5000", + "x-ratelimit-remaining": "4485", + "x-ratelimit-reset": "1675030730", + "x-ratelimit-resource": "graphql", + "x-ratelimit-used": "515", + "x-xss-protection": "0" + }, + "data": { + "data": { + "node": { + "id": "PVTI_1", + "createdAt": "2022-02-02T12:00:00Z", + "type": "ISSUE", + "isArchived": false, + "content": { + "id": "I_1", + "databaseId": 1001, + "number": 1, + "title": "Issue", + "url": "https://github.com/github-project-fixtures/test-repository/issues/1", + "createdAt": "2022-02-02T12:00:00Z", + "author": { + "login": "gh-project-fixtures" + }, + "assignees": { + "nodes": [] + }, + "labels": { + "nodes": [] + }, + "closed": false, + "milestone": null, + "repository": { + "name": "test-repository" + } + }, + "fieldValues": { + "nodes": [ + { + "__typename": "ProjectV2ItemFieldRepositoryValue" + }, + { + "__typename": "ProjectV2ItemFieldTextValue", + "text": "Issue", + "field": { + "id": "PVTF_1" + } + }, + { + "__typename": "ProjectV2ItemFieldTextValue", + "text": "text", + "field": { + "id": "PVTF_8" + } + }, + { + "__typename": "ProjectV2ItemFieldNumberValue", + "number": 1, + "field": { + "id": "PVTF_9" + } + }, + { + "__typename": "ProjectV2ItemFieldDateValue", + "date": "2020-02-02", + "field": { + "id": "PVTF_10" + } + }, + { + "__typename": "ProjectV2ItemFieldSingleSelectValue", + "optionId": "b92ebdaa", + "field": { + "id": "PVTSSF_2" + } + } + ] + } + } + } + } + } + }, + { + "query": "\n mutation archiveItem($projectId: ID!, $itemId: ID!) {\n archiveProjectV2Item(input:{projectId: $projectId, itemId: $itemId }) {\n clientMutationId\n }\n }\n", + "variables": { + "projectId": "PVT_1", + "itemId": "PVTI_1" + }, + "response": { + "status": 200, + "url": "https://api.github.com/graphql", + "headers": { + "access-control-allow-origin": "*", + "access-control-expose-headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", + "connection": "close", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'", + "content-type": "application/json; charset=utf-8", + "date": "Sun, 29 Jan 2023 21:49:19 GMT", + "referrer-policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "server": "GitHub.com", + "strict-transport-security": "max-age=31536000; includeSubdomains; preload", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding, Accept, X-Requested-With", + "x-content-type-options": "nosniff", + "x-frame-options": "deny", + "x-github-media-type": "github.v3; format=json", + "x-github-request-id": "EF0F:7C54:2334E:254CB:63D6E9DF", + "x-ratelimit-limit": "5000", + "x-ratelimit-remaining": "4484", + "x-ratelimit-reset": "1675030730", + "x-ratelimit-resource": "graphql", + "x-ratelimit-used": "516", + "x-xss-protection": "0" + }, + "data": { + "data": { + "archiveProjectV2Item": { + "clientMutationId": null + } + } + } + } + }, + { + "query": "\n query getProjectItem($id:ID!) {\n node(id:$id){\n ... on ProjectV2Item {\n \n id\n createdAt\n type\n isArchived\n \n content {\n ... on DraftIssue {\n id\n title\n createdAt\n updatedAt\n author: creator {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n }\n ... on Issue {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n }\n ... on PullRequest {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n merged\n }\n }\n\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldDateValue {\n date\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n iterationId\n startDate\n duration\n field {\n ... on ProjectV2IterationField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldSingleSelectValue {\n optionId\n field {\n ... on ProjectV2SingleSelectField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n }\n }\n\n }\n }\n }\n", + "variables": { + "id": "PVTI_1" + }, + "response": { + "status": 200, + "url": "https://api.github.com/graphql", + "headers": { + "access-control-allow-origin": "*", + "access-control-expose-headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", + "connection": "close", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'", + "content-type": "application/json; charset=utf-8", + "date": "Sun, 29 Jan 2023 21:49:20 GMT", + "referrer-policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "server": "GitHub.com", + "strict-transport-security": "max-age=31536000; includeSubdomains; preload", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding, Accept, X-Requested-With", + "x-content-type-options": "nosniff", + "x-frame-options": "deny", + "x-github-media-type": "github.v3; format=json", + "x-github-request-id": "EF11:37DF:2D96E:2FDE9:63D6E9E0", + "x-ratelimit-limit": "5000", + "x-ratelimit-remaining": "4483", + "x-ratelimit-reset": "1675030730", + "x-ratelimit-resource": "graphql", + "x-ratelimit-used": "517", + "x-xss-protection": "0" + }, + "data": { + "data": { + "node": { + "id": "PVTI_1", + "createdAt": "2022-02-02T12:00:00Z", + "type": "ISSUE", + "isArchived": true, + "content": { + "id": "I_1", + "databaseId": 1001, + "number": 1, + "title": "Issue", + "url": "https://github.com/github-project-fixtures/test-repository/issues/1", + "createdAt": "2022-02-02T12:00:00Z", + "author": { + "login": "gh-project-fixtures" + }, + "assignees": { + "nodes": [] + }, + "labels": { + "nodes": [] + }, + "closed": false, + "milestone": null, + "repository": { + "name": "test-repository" + } + }, + "fieldValues": { + "nodes": [ + { + "__typename": "ProjectV2ItemFieldRepositoryValue" + }, + { + "__typename": "ProjectV2ItemFieldTextValue", + "text": "Issue", + "field": { + "id": "PVTF_1" + } + }, + { + "__typename": "ProjectV2ItemFieldTextValue", + "text": "text", + "field": { + "id": "PVTF_8" + } + }, + { + "__typename": "ProjectV2ItemFieldNumberValue", + "number": 1, + "field": { + "id": "PVTF_9" + } + }, + { + "__typename": "ProjectV2ItemFieldDateValue", + "date": "2020-02-02", + "field": { + "id": "PVTF_10" + } + }, + { + "__typename": "ProjectV2ItemFieldSingleSelectValue", + "optionId": "b92ebdaa", + "field": { + "id": "PVTSSF_2" + } + } + ] + } + } + } + } + } + }, + { + "query": "\n query getProjectItem($id:ID!) {\n node(id:$id){\n ... on ProjectV2Item {\n \n id\n createdAt\n type\n isArchived\n \n content {\n ... on DraftIssue {\n id\n title\n createdAt\n updatedAt\n author: creator {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n }\n ... on Issue {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n }\n ... on PullRequest {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n merged\n }\n }\n\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldDateValue {\n date\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n iterationId\n startDate\n duration\n field {\n ... on ProjectV2IterationField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldSingleSelectValue {\n optionId\n field {\n ... on ProjectV2SingleSelectField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n }\n }\n\n }\n }\n }\n", + "variables": { + "id": "" + }, + "response": { + "status": 200, + "url": "https://api.github.com/graphql", + "headers": { + "access-control-allow-origin": "*", + "access-control-expose-headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", + "connection": "close", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'", + "content-type": "application/json; charset=utf-8", + "date": "Sun, 29 Jan 2023 21:49:21 GMT", + "referrer-policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "server": "GitHub.com", + "strict-transport-security": "max-age=31536000; includeSubdomains; preload", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding, Accept, X-Requested-With", + "x-content-type-options": "nosniff", + "x-frame-options": "deny", + "x-github-media-type": "github.v3; format=json", + "x-github-request-id": "EF13:5970:39CB6:3C112:63D6E9E1", + "x-ratelimit-limit": "5000", + "x-ratelimit-remaining": "4482", + "x-ratelimit-reset": "1675030730", + "x-ratelimit-resource": "graphql", + "x-ratelimit-used": "518", + "x-xss-protection": "0" + }, + "data": { + "data": { + "node": null + }, + "errors": [ + { + "type": "NOT_FOUND", + "path": [ + "node" + ], + "locations": [ + { + "line": 3, + "column": 5 + } + ], + "message": "Could not resolve to a node with the global id of ''" + } + ] + } + } + } +] \ No newline at end of file diff --git a/test/recorded/api.items.archive/prepare.js b/test/recorded/api.items.archive/prepare.js new file mode 100644 index 00000000..14269ef8 --- /dev/null +++ b/test/recorded/api.items.archive/prepare.js @@ -0,0 +1,34 @@ +// @ts-check + +/** + * Prepare state in order to record fixtures for test.js. Returns array of arguments that will be passed + * passed as `test(project, ...arguments)`. + * + * @param {import("@octokit/openapi-types").components["schemas"]["repository"]} repository + * @param {import("@octokit/core").Octokit} octokit + * @param {import("../../..").default<{text: string, number: number, date: string, singleSelect: "One" | "Two" | "Three"}>} project + * + * @returns {Promise<[string]>} + */ +export async function prepare(repository, octokit, project) { + // create a test issue + const { data: issue } = await octokit.request( + "POST /repos/{owner}/{repo}/issues", + { + owner: repository.owner.login, + repo: repository.name, + title: "Issue", + body: "This is a test issue", + } + ); + + // add issue to project + const item = await project.items.add(issue.node_id, { + text: "text", + number: "1", + date: new Date("2020-02-02").toISOString(), + singleSelect: "One", + }); + + return [item.id]; +} diff --git a/test/recorded/api.items.archive/test.js b/test/recorded/api.items.archive/test.js new file mode 100644 index 00000000..fd1d90e7 --- /dev/null +++ b/test/recorded/api.items.archive/test.js @@ -0,0 +1,15 @@ +// @ts-check + +/** + * @param {import("../../..").default} project + * @param {string} [itemId] + */ +export async function test(project, itemId = "PVTI_1") { + const first = await project.items.archive(itemId); + // 2nd time it won't send a mutation + const second = await project.items.archive(itemId); + // resolves with undefined if not found + const third = await project.items.archive(""); + + return [first, second, third]; +} diff --git a/test/recorded/api.items.get-by-content-id/prepare.js b/test/recorded/api.items.get-by-content-id/prepare.js index 6acccde5..4f975031 100644 --- a/test/recorded/api.items.get-by-content-id/prepare.js +++ b/test/recorded/api.items.get-by-content-id/prepare.js @@ -23,7 +23,7 @@ export async function prepare(repository, octokit, project) { ); // add issue to project - const item = await project.items.add(issue.node_id, { + await project.items.add(issue.node_id, { text: "text", number: "1", date: new Date("2020-02-02").toISOString(), diff --git a/test/recorded/api.items.remove/fixtures.json b/test/recorded/api.items.remove/fixtures.json index 7c09b5da..00478eed 100644 --- a/test/recorded/api.items.remove/fixtures.json +++ b/test/recorded/api.items.remove/fixtures.json @@ -15,7 +15,7 @@ "content-encoding": "gzip", "content-security-policy": "default-src 'none'", "content-type": "application/json; charset=utf-8", - "date": "Sun, 29 Jan 2023 18:51:52 GMT", + "date": "Sun, 29 Jan 2023 21:33:14 GMT", "referrer-policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "server": "GitHub.com", "strict-transport-security": "max-age=31536000; includeSubdomains; preload", @@ -24,12 +24,12 @@ "x-content-type-options": "nosniff", "x-frame-options": "deny", "x-github-media-type": "github.v3; format=json", - "x-github-request-id": "E2B4:0782:3C1A3E:3E5709:63D6C048", + "x-github-request-id": "ED7A:8AAB:2773:29CD:63D6E61A", "x-ratelimit-limit": "5000", - "x-ratelimit-remaining": "4727", - "x-ratelimit-reset": "1675021300", + "x-ratelimit-remaining": "4559", + "x-ratelimit-reset": "1675030730", "x-ratelimit-resource": "graphql", - "x-ratelimit-used": "273", + "x-ratelimit-used": "441", "x-xss-protection": "0" }, "data": { @@ -165,7 +165,7 @@ } }, { - "query": "\n query getProjectItemByContentId($id: ID!) {\n node(id: $id) {\n \n ... on Issue {\n title\n url\n projectItems(first: 10) {\n nodes {\n project {\n number\n }\n \n id\n createdAt\n type\n \n content {\n ... on DraftIssue {\n id\n title\n createdAt\n updatedAt\n author: creator {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n }\n ... on Issue {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n }\n ... on PullRequest {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n merged\n }\n }\n\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldDateValue {\n date\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n iterationId\n startDate\n duration\n field {\n ... on ProjectV2IterationField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldSingleSelectValue {\n optionId\n field {\n ... on ProjectV2SingleSelectField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n }\n }\n\n }\n }\n }\n ... on PullRequest {\n title\n url\n projectItems(first: 10) {\n nodes {\n project {\n number\n }\n \n id\n createdAt\n type\n \n content {\n ... on DraftIssue {\n id\n title\n createdAt\n updatedAt\n author: creator {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n }\n ... on Issue {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n }\n ... on PullRequest {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n merged\n }\n }\n\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldDateValue {\n date\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n iterationId\n startDate\n duration\n field {\n ... on ProjectV2IterationField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldSingleSelectValue {\n optionId\n field {\n ... on ProjectV2SingleSelectField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n }\n }\n\n }\n }\n }\n\n }\n }\n", + "query": "\n query getProjectItem($id:ID!) {\n node(id:$id){\n ... on ProjectV2Item {\n \n id\n createdAt\n type\n isArchived\n \n content {\n ... on DraftIssue {\n id\n title\n createdAt\n updatedAt\n author: creator {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n }\n ... on Issue {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n }\n ... on PullRequest {\n \n id\n databaseId\n number\n title\n url\n createdAt\n author {\n login\n }\n assignees(first: 10) {\n nodes {\n login\n }\n }\n labels(first: 10) {\n nodes {\n name\n }\n }\n closed\n milestone {\n number\n title\n state\n }\n repository {\n name\n }\n\n merged\n }\n }\n\n fieldValues(first: 20) {\n nodes {\n __typename\n ... on ProjectV2ItemFieldDateValue {\n date\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldIterationValue {\n title\n iterationId\n startDate\n duration\n field {\n ... on ProjectV2IterationField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldNumberValue {\n number\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldSingleSelectValue {\n optionId\n field {\n ... on ProjectV2SingleSelectField {\n id\n }\n }\n }\n ... on ProjectV2ItemFieldTextValue {\n text\n field {\n ... on ProjectV2Field {\n id\n }\n }\n }\n }\n }\n\n }\n }\n }\n", "variables": { "id": "PVTI_1" }, @@ -179,7 +179,7 @@ "content-encoding": "gzip", "content-security-policy": "default-src 'none'", "content-type": "application/json; charset=utf-8", - "date": "Sun, 29 Jan 2023 18:51:53 GMT", + "date": "Sun, 29 Jan 2023 21:33:15 GMT", "referrer-policy": "origin-when-cross-origin, strict-origin-when-cross-origin", "server": "GitHub.com", "strict-transport-security": "max-age=31536000; includeSubdomains; preload", @@ -188,17 +188,128 @@ "x-content-type-options": "nosniff", "x-frame-options": "deny", "x-github-media-type": "github.v3; format=json", - "x-github-request-id": "E2B6:54E3:39D1E6:3C0F34:63D6C049", + "x-github-request-id": "ED7B:7412:4E2480:51E028:63D6E61B", "x-ratelimit-limit": "5000", - "x-ratelimit-remaining": "4726", - "x-ratelimit-reset": "1675021300", + "x-ratelimit-remaining": "4558", + "x-ratelimit-reset": "1675030730", "x-ratelimit-resource": "graphql", - "x-ratelimit-used": "274", + "x-ratelimit-used": "442", "x-xss-protection": "0" }, "data": { "data": { - "node": {} + "node": { + "id": "PVTI_1", + "createdAt": "2022-02-02T12:00:00Z", + "type": "ISSUE", + "isArchived": false, + "content": { + "id": "I_1", + "databaseId": 1001, + "number": 1, + "title": "Issue", + "url": "https://github.com/github-project-fixtures/test-repository/issues/1", + "createdAt": "2022-02-02T12:00:00Z", + "author": { + "login": "gh-project-fixtures" + }, + "assignees": { + "nodes": [] + }, + "labels": { + "nodes": [] + }, + "closed": false, + "milestone": null, + "repository": { + "name": "test-repository" + } + }, + "fieldValues": { + "nodes": [ + { + "__typename": "ProjectV2ItemFieldRepositoryValue" + }, + { + "__typename": "ProjectV2ItemFieldTextValue", + "text": "Issue", + "field": { + "id": "PVTF_1" + } + }, + { + "__typename": "ProjectV2ItemFieldTextValue", + "text": "text", + "field": { + "id": "PVTF_8" + } + }, + { + "__typename": "ProjectV2ItemFieldNumberValue", + "number": 1, + "field": { + "id": "PVTF_9" + } + }, + { + "__typename": "ProjectV2ItemFieldDateValue", + "date": "2020-02-02", + "field": { + "id": "PVTF_10" + } + }, + { + "__typename": "ProjectV2ItemFieldSingleSelectValue", + "optionId": "b92ebdaa", + "field": { + "id": "PVTSSF_2" + } + } + ] + } + } + } + } + } + }, + { + "query": "\n mutation removeItemFromProject($projectId:ID!, $itemId:ID!) {\n deleteProjectV2Item(input:{\n projectId:$projectId,\n itemId:$itemId\n }) {\n clientMutationId\n }\n }\n", + "variables": { + "projectId": "PVT_1", + "itemId": "PVTI_1" + }, + "response": { + "status": 200, + "url": "https://api.github.com/graphql", + "headers": { + "access-control-allow-origin": "*", + "access-control-expose-headers": "ETag, Link, Location, Retry-After, X-GitHub-OTP, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Used, X-RateLimit-Resource, X-RateLimit-Reset, X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Poll-Interval, X-GitHub-Media-Type, X-GitHub-SSO, X-GitHub-Request-Id, Deprecation, Sunset", + "connection": "close", + "content-encoding": "gzip", + "content-security-policy": "default-src 'none'", + "content-type": "application/json; charset=utf-8", + "date": "Sun, 29 Jan 2023 21:33:16 GMT", + "referrer-policy": "origin-when-cross-origin, strict-origin-when-cross-origin", + "server": "GitHub.com", + "strict-transport-security": "max-age=31536000; includeSubdomains; preload", + "transfer-encoding": "chunked", + "vary": "Accept-Encoding, Accept, X-Requested-With", + "x-content-type-options": "nosniff", + "x-frame-options": "deny", + "x-github-media-type": "github.v3; format=json", + "x-github-request-id": "ED7C:6763:51769F:553583:63D6E61C", + "x-ratelimit-limit": "5000", + "x-ratelimit-remaining": "4557", + "x-ratelimit-reset": "1675030730", + "x-ratelimit-resource": "graphql", + "x-ratelimit-used": "443", + "x-xss-protection": "0" + }, + "data": { + "data": { + "deleteProjectV2Item": { + "clientMutationId": null + } } } } diff --git a/test/recorded/api.items.remove/test.js b/test/recorded/api.items.remove/test.js index c571020b..7a531418 100644 --- a/test/recorded/api.items.remove/test.js +++ b/test/recorded/api.items.remove/test.js @@ -5,5 +5,5 @@ * @param {string} [itemId] */ export function test(project, itemId = "PVTI_1") { - return project.items.removeByContentId(itemId); + return project.items.remove(itemId); } diff --git a/test/snapshots/recorded.test.js.md b/test/snapshots/recorded.test.js.md index f7eeb83a..0ee2c882 100644 --- a/test/snapshots/recorded.test.js.md +++ b/test/snapshots/recorded.test.js.md @@ -370,6 +370,192 @@ Generated by [AVA](https://avajs.dev). type: 'ISSUE', } +## api.items.archive + +> Snapshot 1 + + [ + { + content: { + assignees: [], + closed: false, + closedAt: undefined, + createdAt: '2022-02-02T12:00:00Z', + databaseId: 1001, + id: 'I_1', + labels: [], + milestone: null, + number: 1, + repository: 'test-repository', + title: 'Issue', + url: 'https://github.com/github-project-fixtures/test-repository/issues/1', + }, + fields: { + date: '2020-02-02', + number: '1', + singleSelect: 'One', + status: null, + text: 'text', + title: 'Issue', + }, + id: 'PVTI_1', + isArchived: true, + type: 'ISSUE', + }, + { + content: { + assignees: [], + closed: false, + closedAt: undefined, + createdAt: '2022-02-02T12:00:00Z', + databaseId: 1001, + id: 'I_1', + labels: [], + milestone: null, + number: 1, + repository: 'test-repository', + title: 'Issue', + url: 'https://github.com/github-project-fixtures/test-repository/issues/1', + }, + fields: { + date: '2020-02-02', + number: '1', + singleSelect: 'One', + status: null, + text: 'text', + title: 'Issue', + }, + id: 'PVTI_1', + isArchived: true, + type: 'ISSUE', + }, + undefined, + ] + +## api.items.archive-by-content-id + +> Snapshot 1 + + [ + { + content: { + assignees: [], + closed: false, + closedAt: undefined, + createdAt: '2022-02-02T12:00:00Z', + databaseId: 1001, + id: 'I_1', + labels: [], + milestone: null, + number: 1, + repository: 'test-repository', + title: 'Issue', + url: 'https://github.com/github-project-fixtures/test-repository/issues/1', + }, + fields: { + date: '2020-02-02', + number: '1', + singleSelect: 'One', + status: null, + text: 'text', + title: 'Issue', + }, + id: 'PVTI_1', + isArchived: true, + type: 'ISSUE', + }, + { + content: { + assignees: [], + closed: false, + closedAt: undefined, + createdAt: '2022-02-02T12:00:00Z', + databaseId: 1001, + id: 'I_1', + labels: [], + milestone: null, + number: 1, + repository: 'test-repository', + title: 'Issue', + url: 'https://github.com/github-project-fixtures/test-repository/issues/1', + }, + fields: { + date: '2020-02-02', + number: '1', + singleSelect: 'One', + status: null, + text: 'text', + title: 'Issue', + }, + id: 'PVTI_1', + isArchived: true, + type: 'ISSUE', + }, + undefined, + ] + +## api.items.archive-by-content-repository-and-number + +> Snapshot 1 + + [ + { + content: { + assignees: [], + closed: false, + closedAt: undefined, + createdAt: '2022-02-02T12:00:00Z', + databaseId: 1001, + id: 'I_1', + labels: [], + milestone: null, + number: 1, + repository: 'test-repository', + title: 'Issue', + url: 'https://github.com/github-project-fixtures/test-repository/issues/1', + }, + fields: { + date: '2020-02-02', + number: '1', + singleSelect: 'One', + status: null, + text: 'text', + title: 'Issue', + }, + id: 'PVTI_1', + isArchived: true, + type: 'ISSUE', + }, + { + content: { + assignees: [], + closed: false, + closedAt: undefined, + createdAt: '2022-02-02T12:00:00Z', + databaseId: 1001, + id: 'I_1', + labels: [], + milestone: null, + number: 1, + repository: 'test-repository', + title: 'Issue', + url: 'https://github.com/github-project-fixtures/test-repository/issues/1', + }, + fields: { + date: '2020-02-02', + number: '1', + singleSelect: 'One', + status: null, + text: 'text', + title: 'Issue', + }, + id: 'PVTI_1', + isArchived: true, + type: 'ISSUE', + }, + undefined, + ] + ## api.items.get > Snapshot 1 @@ -6373,7 +6559,33 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 - undefined + { + content: { + assignees: [], + closed: false, + closedAt: undefined, + createdAt: '2022-02-02T12:00:00Z', + databaseId: 1001, + id: 'I_1', + labels: [], + milestone: null, + number: 1, + repository: 'test-repository', + title: 'Issue', + url: 'https://github.com/github-project-fixtures/test-repository/issues/1', + }, + fields: { + date: '2020-02-02', + number: '1', + singleSelect: 'One', + status: null, + text: 'text', + title: 'Issue', + }, + id: 'PVTI_1', + isArchived: false, + type: 'ISSUE', + } ## api.items.remove-by-content-id diff --git a/test/snapshots/recorded.test.js.snap b/test/snapshots/recorded.test.js.snap index 7539f905027727aedc5b6b4299e429449753ca53..de2cf93b89f5ca91838d4de10637c37a565f4361 100644 GIT binary patch literal 28583 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 literal 28173 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 SKaIAc`E7*$Hh=%Rzy1#zC1fc8 From 4ce09fa83c1d45bc0670f08d04225a368fb7318f Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Sun, 29 Jan 2023 13:52:44 -0800 Subject: [PATCH 3/4] feat: `project.items.archive()`, `project.items.archiveByContentId()`, `project.items.archiveByContentRepositoryAndNumber()` --- api/items.archive-by-content-id.js | 24 +++++++++++++ ...rchive-by-content-repository-and-number.js | 35 +++++++++++++++++++ api/items.archive.js | 24 +++++++++++++ api/items.get-by-content-id.js | 4 --- ...ms.get-by-content-repository-and-number.js | 4 --- api/lib/archive-project-item.js | 26 ++++++++++++++ api/lib/queries.js | 8 +++++ index.d.ts | 10 ++++++ index.js | 7 ++++ 9 files changed, 134 insertions(+), 8 deletions(-) create mode 100644 api/items.archive-by-content-id.js create mode 100644 api/items.archive-by-content-repository-and-number.js create mode 100644 api/items.archive.js create mode 100644 api/lib/archive-project-item.js diff --git a/api/items.archive-by-content-id.js b/api/items.archive-by-content-id.js new file mode 100644 index 00000000..50db26d5 --- /dev/null +++ b/api/items.archive-by-content-id.js @@ -0,0 +1,24 @@ +// @ts-check + +import { getItemByContentId } from "./items.get-by-content-id.js"; +import { archiveProjectItem } from "./lib/archive-project-item.js"; + +/** + * Archives an item based on content ID. Resolves with the archived item + * or with `undefined` if item was not found. + * + * @param {import("..").default} project + * @param {import("..").GitHubProjectState} state + * @param {string} contentId + * + * @returns {Promise} + */ +export async function archiveItemByContentId(project, state, contentId) { + const item = await getItemByContentId(project, state, contentId); + if (!item) return; + + if (item.isArchived) return item; + + await archiveProjectItem(project, state, item.id); + return { ...item, isArchived: true }; +} diff --git a/api/items.archive-by-content-repository-and-number.js b/api/items.archive-by-content-repository-and-number.js new file mode 100644 index 00000000..928ccaaf --- /dev/null +++ b/api/items.archive-by-content-repository-and-number.js @@ -0,0 +1,35 @@ +// @ts-check + +import { getItemByContentRepositoryAndNumber } from "./items.get-by-content-repository-and-number.js"; +import { archiveProjectItem } from "./lib/archive-project-item.js"; + +/** + * Removes an item based on content repository name and number. + * Resolves with the archived item or with `undefined` if item was not found. + * + * @param {import("..").default} project + * @param {import("..").GitHubProjectState} state + * @param {string} repositoryName + * @param {number} issueOrPullRequestNumber + * + * @returns {Promise} + */ +export async function archiveItemByContentRepositoryAndNumber( + project, + state, + repositoryName, + issueOrPullRequestNumber +) { + const item = await getItemByContentRepositoryAndNumber( + project, + state, + repositoryName, + issueOrPullRequestNumber + ); + if (!item) return; + + if (item.isArchived) return item; + + await archiveProjectItem(project, state, item.id); + return { ...item, isArchived: true }; +} diff --git a/api/items.archive.js b/api/items.archive.js new file mode 100644 index 00000000..337ee922 --- /dev/null +++ b/api/items.archive.js @@ -0,0 +1,24 @@ +// @ts-check + +import { getItem } from "./items.get.js"; +import { archiveProjectItem } from "./lib/archive-project-item.js"; + +/** + * Archives an item if it exists. Resolves with the archived item + * or with `undefined` if item was not found. + * + * @param {import("..").default} project + * @param {import("..").GitHubProjectState} state + * @param {string} itemNodeId + * + * @returns {Promise} + */ +export async function archiveItem(project, state, itemNodeId) { + const item = await getItem(project, state, itemNodeId); + if (!item) return; + + if (item.isArchived) return item; + + await archiveProjectItem(project, state, item.id); + return { ...item, isArchived: true }; +} diff --git a/api/items.get-by-content-id.js b/api/items.get-by-content-id.js index 51e1ca91..b7d41942 100644 --- a/api/items.get-by-content-id.js +++ b/api/items.get-by-content-id.js @@ -18,10 +18,6 @@ import { handleNotFoundGraphqlError } from "./lib/handle-not-found-graphql-error export async function getItemByContentId(project, state, contentId) { const stateWithFields = await getStateWithProjectFields(project, state); - // TODO: ideally we would retrieve a project item directly based on a content id - // and the project number, but GitHub's GraphQL Schema does not support that - // as of 2022-08-14. As a workaround, we load all project items and filter - // them by project number afterwards. const result = await project.octokit .graphql(getItemByContentIdQuery, { id: contentId, diff --git a/api/items.get-by-content-repository-and-number.js b/api/items.get-by-content-repository-and-number.js index 28595912..5aecf37a 100644 --- a/api/items.get-by-content-repository-and-number.js +++ b/api/items.get-by-content-repository-and-number.js @@ -24,10 +24,6 @@ export async function getItemByContentRepositoryAndNumber( ) { const stateWithFields = await getStateWithProjectFields(project, state); - // TODO: ideally we would retrieve a project item directly based on a content id - // and the project number, but GitHub's GraphQL Schema does not support that - // as of 2022-08-14. As a workaround, we load all project items and filter - // them by project number afterwards. const result = await project.octokit .graphql(getItemByContentRepositoryAndNameQuery, { owner: project.owner, diff --git a/api/lib/archive-project-item.js b/api/lib/archive-project-item.js new file mode 100644 index 00000000..2c069d87 --- /dev/null +++ b/api/lib/archive-project-item.js @@ -0,0 +1,26 @@ +// @ts-check + +import { getStateWithProjectFields } from "./get-state-with-project-fields.js"; +import { handleNotFoundGraphqlError } from "./handle-not-found-graphql-error.js"; +import { archiveItemMutation } from "./queries.js"; + +/** + * Helper method to archive an item from a project which is used + * by all the `project.items.archive*` methods. + * + * @param {import("../..").default} project + * @param {import("../..").GitHubProjectState} state + * @param {string} itemNodeId + * + * @returns {Promise} + */ +export async function archiveProjectItem(project, state, itemNodeId) { + const stateWithFields = await getStateWithProjectFields(project, state); + + await project.octokit + .graphql(archiveItemMutation, { + projectId: stateWithFields.id, + itemId: itemNodeId, + }) + .catch(handleNotFoundGraphqlError); +} diff --git a/api/lib/queries.js b/api/lib/queries.js index acd3cac4..68d1c94c 100644 --- a/api/lib/queries.js +++ b/api/lib/queries.js @@ -292,3 +292,11 @@ export const removeItemFromProjectMutation = ` } } `; + +export const archiveItemMutation = ` + mutation archiveItem($projectId: ID!, $itemId: ID!) { + archiveProjectV2Item(input:{projectId: $projectId, itemId: $itemId }) { + clientMutationId + } + } +`; diff --git a/index.d.ts b/index.d.ts index a7069a30..460bbb14 100644 --- a/index.d.ts +++ b/index.d.ts @@ -77,6 +77,16 @@ export default class GitHubProject< issueOrPullRequestNumber: number, fields: Partial ): Promise | undefined>; + archive( + itemNodeId: string + ): Promise | undefined>; + archiveByContentId( + contentNodeId: string + ): Promise | undefined>; + archiveByContentRepositoryAndNumber( + repositoryName: string, + issueOrPullRequestNumber: number + ): Promise | undefined>; remove( itemNodeId: string ): Promise | undefined>; diff --git a/index.js b/index.js index 8004266c..04ad64eb 100644 --- a/index.js +++ b/index.js @@ -11,6 +11,9 @@ import { getItemByContentRepositoryAndNumber } from "./api/items.get-by-content- import { updateItem } from "./api/items.update.js"; import { updateItemByContentId } from "./api/items.update-by-content-id.js"; import { updateItemByContentRepositoryAndNumber } from "./api/items.update-by-content-repository-and-number.js"; +import { archiveItem } from "./api/items.archive.js"; +import { archiveItemByContentId } from "./api/items.archive-by-content-id.js"; +import { archiveItemByContentRepositoryAndNumber } from "./api/items.archive-by-content-repository-and-number.js"; import { removeItem } from "./api/items.remove.js"; import { removeItemByContentId } from "./api/items.remove-by-content-id.js"; import { removeItemByContentRepositoryAndNumber } from "./api/items.remove-by-content-repository-and-name.js"; @@ -60,6 +63,10 @@ export default class GitHubProject { updateByContentId: updateItemByContentId.bind(null, this, state), updateByContentRepositoryAndNumber: updateItemByContentRepositoryAndNumber.bind(null, this, state), + archive: archiveItem.bind(null, this, state), + archiveByContentId: archiveItemByContentId.bind(null, this, state), + archiveByContentRepositoryAndNumber: + archiveItemByContentRepositoryAndNumber.bind(null, this, state), remove: removeItem.bind(null, this, state), removeByContentId: removeItemByContentId.bind(null, this, state), removeByContentRepositoryAndNumber: From 0bb4737d637a6b7c8750d2cbff3e49f08917c84d Mon Sep 17 00:00:00 2001 From: Gregor Martynus <39992+gr2m@users.noreply.github.com> Date: Sun, 29 Jan 2023 13:54:40 -0800 Subject: [PATCH 4/4] test(types): archive methods --- index.test-d.ts | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/index.test-d.ts b/index.test-d.ts index 330f92d0..535c4f5e 100644 --- a/index.test-d.ts +++ b/index.test-d.ts @@ -495,6 +495,57 @@ export async function updateItemByContentRepositoryAndNumberTest() { } } +export async function archiveItemTest() { + const project = new GitHubProject({ + owner: "owner", + number: 1, + token: "gpg_secret123", + }); + const item = await project.items.archive("item node id"); + + if (typeof item === "undefined") { + expectType(item); + return; + } + + expectType(item.id); +} + +export async function archiveItemByContentIdTest() { + const project = new GitHubProject({ + owner: "owner", + number: 1, + token: "gpg_secret123", + }); + const item = await project.items.archiveByContentId("content node id"); + + if (typeof item === "undefined") { + expectType(item); + return; + } + + expectType(item.id); +} + +export async function archiveItemByContentRepositoryAndNameTest() { + const project = new GitHubProject({ + owner: "owner", + number: 1, + token: "gpg_secret123", + }); + const item = await project.items.archiveByContentRepositoryAndNumber( + "repository-name", + 1 + ); + + if (typeof item === "undefined") { + expectType(item); + return; + } + + expectType(item.id); +} + export async function removeItemTest() { const project = new GitHubProject({ owner: "owner",