From 8cabc5a8e3186ba71151163fdc1ed0772bfbf1ba Mon Sep 17 00:00:00 2001 From: shadrach-tayo Date: Mon, 13 May 2024 12:01:48 +0200 Subject: [PATCH 1/9] chore: document orcid api service class, methods and utils --- desci-server/src/services/orcid.ts | 104 +++++++++++++++++++++++++++-- 1 file changed, 97 insertions(+), 7 deletions(-) diff --git a/desci-server/src/services/orcid.ts b/desci-server/src/services/orcid.ts index 286c6e3ff..dfa2271d4 100644 --- a/desci-server/src/services/orcid.ts +++ b/desci-server/src/services/orcid.ts @@ -15,6 +15,11 @@ const ORCID_DOMAIN = process.env.ORCID_API_DOMAIN || 'sandbox.orcid.org'; type Claim = Awaited>[number]; const logger = parentLogger.child({ module: 'ORCIDApiService' }); +/** + * Service class for interfacing with ORCID /works API + * Handles updating orcid work profile entries for users with orcid + * linked to their profiles + */ class OrcidApiService { baseUrl: string; @@ -25,6 +30,12 @@ class OrcidApiService { logger.info({ url: this.baseUrl }, 'Init ORCID Service'); } + /** + * Query user orcid access token from the database and refreshes + * tokens if needed and update database entry valid token + * @param userId unique user identifier + * @returns a valid access token string + */ private async getAccessToken(userId: number) { const authTokens = await prisma.authToken.findMany({ where: { @@ -88,6 +99,16 @@ class OrcidApiService { return authToken.accessToken; } + /** + * Remove an attestation from user's ORCID work profile + * If user has no verified protected attestations, remove research node + * work entry + * @param {Object} argument - The claim argument to process + * @param {number} argument.claimId - The ID of the node attestation to remove + * @param {string} argument.nodeUuid - The uuid of the research node + * @param {string} argument.orcid - The ORCID identifier of the user + * @returns + */ async removeClaimRecord({ claimId, nodeUuid, orcid }: { claimId: number; nodeUuid: string; orcid: string }) { const putCode = await prisma.orcidPutCodes.findFirst({ where: { @@ -132,6 +153,15 @@ class OrcidApiService { logger.info({ userId: user.id, CLAIMS: claims.length, nodeUuid }, '[ORCID::DELETE]:: FINISH'); } + /** + * Execute http request to remove ORCID work entry + * and remove the associated putCode from the database + * @param {Object} argument - The claim argument to process + * @param {string} argument.orcid - The ORCID identifier of the user + * @param {number} argument.putCode - The ORCID /work record putCode + * @param {string} argument.authToken - A valid user orcid access token + * @returns + */ async removeWorkRecord({ putCode, authToken, orcid }: { orcid: string; putCode: OrcidPutCodes; authToken: string }) { const code = putCode.putcode; const url = `${this.baseUrl}/${orcid}/work${code ? '/' + code : ''}`; @@ -172,6 +202,14 @@ class OrcidApiService { ); } + /** + * Update ORCID work summary of a user + * Retrieve a validated protected attestations and post each as a work entry + * Retrieve Research Node with uuid {nodeUuid} and post a work entry + * @param nodeUuid - Research node uuid + * @param orcid - ORCID identifier + * @returns + */ async postWorkRecord(nodeUuid: string, orcid: string) { try { const user = await prisma.user.findUnique({ where: { orcid } }); @@ -225,6 +263,18 @@ class OrcidApiService { } } + /** + * Execute http request to post/update ORCID work entry for a node + * and insert/update the associated putCode in the database + * @param {Object} argument - The Research Node details object + * @param {Object} argument.manifest - The node's manifest + * @param {string} argument.publicationDate - The last publish datetime string in rfc3339 format + * @param {string} argument.uuid - Unique uuid identifier of the node to update + * @param {number} argument.userId - ID of the user (node owner) + * @param {string} argument.authToken - A valid user orcid access token + * @param {string} argument.orcid - The ORCID identifier of the user + * @param {number} argument.nodeVersion - The latest version of the research node + */ async putNodeWorkRecord({ manifest, publicationDate, @@ -248,7 +298,7 @@ class OrcidApiService { }); const putCode = orcidPutCode?.putcode; - let data = generateRootWorkRecord({ manifest, publicationDate, nodeVersion, putCode }); + let data = generateNodeWorkRecord({ manifest, publicationDate, nodeVersion, putCode }); data = data.replace(/\\"/g, '"'); const url = `${this.baseUrl}/${orcid}/work${putCode ? '/' + putCode : ''}`; @@ -316,6 +366,19 @@ class OrcidApiService { } } + /** + * Execute http request to post/update ORCID work entry for an attestation + * and insert/update the associated putCode in the database + * @param {Object} argument - The Research Node details object + * @param {string} argument.authToken - A valid user orcid access token + * @param {Object} argument.claim - The claim object retrieved from the database + * @param {Object} argument.manifest - The node's manifest + * @param {number} argument.nodeVersion - The latest version of the research node + * @param {string} argument.orcid - The ORCID identifier of the user + * @param {string} argument.publicationDate - The last publish datetime string in rfc3339 format + * @param {string} argument.uuid - Unique uuid identifier of the node to update + * @param {number} argument.userId - ID of the user (node owner) + */ async putClaimWorkRecord({ manifest, publicationDate, @@ -421,9 +484,16 @@ class OrcidApiService { } } -const orcidApiService = new OrcidApiService(); -export default orcidApiService; - +/** + * Generate an ORCID work summary xml string based for an attestation/claim + * Model Reference https://github.com/ORCID/orcid-model/blob/master/src/main/resources/record_3.0/work-3.0.xsd + * @param {Object} argument - The Research Node details object + * @param {Object} argument.claim - The claim object retrieved from the database + * @param {Object} argument.manifest - The node's manifest + * @param {number} argument.nodeVersion - The latest version of the research node + * @param {string} argument.publicationDate - The last publish datetime string in rfc3339 format + * @param {number=} argument.putCode - The ORCID /work record putCode + */ const generateClaimWorkRecord = ({ manifest, putCode, @@ -483,9 +553,20 @@ const generateClaimWorkRecord = ({ ` ); }; + const zeropad = (data: string) => (data.length < 2 ? `0${data}` : data); -const generateRootWorkRecord = ({ +/** + * Generate an ORCID work summary xml string based for a research Node + * Model Reference https://github.com/ORCID/orcid-model/blob/master/src/main/resources/record_3.0/work-3.0.xsd + * @param {Object} argument - The Research Node details object + * @param {Object} argument.manifest - The node's manifest + * @param {number} argument.nodeVersion - The latest version of the research node + * @param {string} argument.publicationDate - The last publish datetime string in rfc3339 format + * @param {number=} argument.putCode - The ORCID /work record putCode + * @returns {string} xml string of the constructed work summary data + */ +const generateNodeWorkRecord = ({ manifest, nodeVersion, putCode, @@ -495,7 +576,7 @@ const generateRootWorkRecord = ({ nodeVersion: number; putCode?: string; publicationDate: string; -}) => { +}): string => { const codeAttr = putCode ? 'put-code="' + putCode + '"' : ''; const workType = 'preprint'; const [month, day, year] = publicationDate.split('-'); @@ -530,7 +611,13 @@ const generateRootWorkRecord = ({ ); }; -const generateContributors = (authors: ResearchObjectV1Author[]) => { +/** + * Generate an ORCID work contributors xml string + * Model Reference https://github.com/ORCID/orcid-model/blob/master/src/main/resources/record_3.0/work-3.0.xsd#L160 + * @param authors[] - A list of ResearchObjectV1Author entries + * @returns {string} xml string of the constructed contributor data + */ +const generateContributors = (authors: ResearchObjectV1Author[]): string => { const contributors = authors?.length > 0 ? ` @@ -558,3 +645,6 @@ const generateContributors = (authors: ResearchObjectV1Author[]) => { : ``; return contributors; }; + +const orcidApiService = new OrcidApiService(); +export default orcidApiService; From b4983b656aa59f9825c16073a77a558b8d07074d Mon Sep 17 00:00:00 2001 From: shadrach-tayo Date: Wed, 15 May 2024 01:57:49 +0200 Subject: [PATCH 2/9] orcid api intercept test --- desci-server/package.json | 1 + .../test/integration/Attestation.test.ts | 44 ++++++++++++++++++- desci-server/yarn.lock | 16 ++++++- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/desci-server/package.json b/desci-server/package.json index a10510f91..de7bf9847 100755 --- a/desci-server/package.json +++ b/desci-server/package.json @@ -144,6 +144,7 @@ "eslint-plugin-prettier": "^5.0.1", "lint-staged": "^11.1.2", "mocha": "^10.2.0", + "nock": "^13.5.4", "nodemon": "^2.0.22", "nyc": "^15.1.0", "prettier": "^3.1.1", diff --git a/desci-server/test/integration/Attestation.test.ts b/desci-server/test/integration/Attestation.test.ts index 9a908ff74..429f3de48 100644 --- a/desci-server/test/integration/Attestation.test.ts +++ b/desci-server/test/integration/Attestation.test.ts @@ -5,6 +5,7 @@ import { Annotation, Attestation, AttestationVersion, + AuthTokenSource, CommunityMember, CommunityMembershipRole, DesciCommunity, @@ -18,6 +19,7 @@ import { } from '@prisma/client'; import { assert, expect } from 'chai'; import jwt from 'jsonwebtoken'; +import nock from 'nock'; import request from 'supertest'; import { prisma } from '../../src/client.js'; @@ -133,7 +135,7 @@ const clearDatabase = async () => { await prisma.$queryRaw`TRUNCATE TABLE "Node" CASCADE;`; }; -describe('Attestations Service', async () => { +describe.only('Attestations Service', async () => { let baseManifest: ResearchObjectV1; let baseManifestCid: string; let users: User[]; @@ -2105,6 +2107,8 @@ describe('Attestations Service', async () => { MemberJwtToken2: string, memberAuthHeaderVal1: string, memberAuthHeaderVal2: string; + const mockPutCode = '1926486'; + const ORCID_ID = '0000-0000-1111-090X'; before(async () => { node = nodes[0]; @@ -2121,6 +2125,26 @@ describe('Attestations Service', async () => { claimerId: author.id, }); + // add oricd to user profile + await prisma.user.update({ + where: { + id: author.id, + }, + data: { + orcid: ORCID_ID, + }, + }); + + // insert mock orcid auth token + await prisma.authToken.create({ + data: { + source: AuthTokenSource.ORCID, + accessToken: 'mock-access-token', + userId: author.id, + refreshToken: 'refresh-token', + }, + }); + members = await communityService.getAllMembers(desciCommunity.id); MemberJwtToken1 = jwt.sign({ email: members[0].user.email }, process.env.JWT_SECRET!, { expiresIn: '1y', @@ -2146,6 +2170,22 @@ describe('Attestations Service', async () => { }); it('should allow only members verify a node attestation(claim)', async () => { + let scope = nock('https://api.sandbox.orcid.org/v3.0') + .post(`${ORCID_ID}/work`) + .once() + .reply(201, '', { location: `https://api.sandbox.orcid.org/v3.0/${ORCID_ID}/work/${mockPutCode}` }); + + nock(`https://sandbox.orcid.org/oauth/token`).post(`${ORCID_ID}/work`).twice().reply(200, { + access_token: 'access-token', + token_type: 'auth', + refresh_token: 'refresh-token', + expires_in: 3599, + scope: '', + name: '', + orcid: ORCID_ID, + }); + + console.log('VERIFICATION HTTPS MOCK', scope); let res = await request(app) .post(`/v1/attestations/verification`) .set('authorization', memberAuthHeaderVal1) @@ -2154,6 +2194,8 @@ describe('Attestations Service', async () => { }); expect(res.statusCode).to.equal(200); + scope = nock('https://api.sandbox.orcid.org/v3.0').put(`${ORCID_ID}/work/${mockPutCode}`).once().reply(200); + res = await request(app).post(`/v1/attestations/verification`).set('authorization', memberAuthHeaderVal2).send({ claimId: openCodeClaim.id, }); diff --git a/desci-server/yarn.lock b/desci-server/yarn.lock index 60f309f24..41ed29f43 100644 --- a/desci-server/yarn.lock +++ b/desci-server/yarn.lock @@ -10116,7 +10116,7 @@ json-stable-stringify-without-jsonify@^1.0.1: resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== -json-stringify-safe@~5.0.1: +json-stringify-safe@^5.0.1, json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA== @@ -10953,6 +10953,15 @@ next@14.1.0: "@next/swc-win32-ia32-msvc" "14.1.0" "@next/swc-win32-x64-msvc" "14.1.0" +nock@^13.5.4: + version "13.5.4" + resolved "https://registry.yarnpkg.com/nock/-/nock-13.5.4.tgz#8918f0addc70a63736170fef7106a9721e0dc479" + integrity sha512-yAyTfdeNJGGBFxWdzSKCBYxs5FxLbCg5X5Q4ets974hcQzG1+qCxvIyOo4j2Ry6MUlhWVMX4OoYDefAIIwupjw== + dependencies: + debug "^4.1.0" + json-stringify-safe "^5.0.1" + propagate "^2.0.0" + node-domexception@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5" @@ -11779,6 +11788,11 @@ progress@^2.0.0: resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== +propagate@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/propagate/-/propagate-2.0.1.tgz#40cdedab18085c792334e64f0ac17256d38f9a45" + integrity sha512-vGrhOavPSTz4QVNuBNdcNXePNdNMaO1xj9yBeH1ScQPjk/rhg9sSlCXPhMkFuaNNW/syTvYqsnbIJxMBfRbbag== + proto-list@~1.2.1: version "1.2.4" resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849" From 68fcf8e765a433f8b06341f988904db274b6b94b Mon Sep 17 00:00:00 2001 From: shadrach-tayo Date: Wed, 15 May 2024 02:29:21 +0200 Subject: [PATCH 3/9] enable all tests to run --- desci-server/test/integration/Attestation.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desci-server/test/integration/Attestation.test.ts b/desci-server/test/integration/Attestation.test.ts index 429f3de48..f47ea46b1 100644 --- a/desci-server/test/integration/Attestation.test.ts +++ b/desci-server/test/integration/Attestation.test.ts @@ -135,7 +135,7 @@ const clearDatabase = async () => { await prisma.$queryRaw`TRUNCATE TABLE "Node" CASCADE;`; }; -describe.only('Attestations Service', async () => { +describe('Attestations Service', async () => { let baseManifest: ResearchObjectV1; let baseManifestCid: string; let users: User[]; From 5975401cbe5d4fb6672c14798514dbd783dec2dc Mon Sep 17 00:00:00 2001 From: shadrach-tayo Date: Wed, 15 May 2024 02:30:03 +0200 Subject: [PATCH 4/9] add nock expectations --- .../test/integration/Attestation.test.ts | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/desci-server/test/integration/Attestation.test.ts b/desci-server/test/integration/Attestation.test.ts index f47ea46b1..b7577d025 100644 --- a/desci-server/test/integration/Attestation.test.ts +++ b/desci-server/test/integration/Attestation.test.ts @@ -2090,7 +2090,7 @@ describe('Attestations Service', async () => { }); }); - describe('Protected Attestation Verification', async () => { + describe.only('Protected Attestation Verification', async () => { let openCodeClaim: NodeAttestation; let openDataClaim: NodeAttestation; let node: Node; @@ -2167,10 +2167,12 @@ describe('Attestations Service', async () => { await prisma.$queryRaw`TRUNCATE TABLE "Annotation" CASCADE;`; await prisma.$queryRaw`TRUNCATE TABLE "NodeAttestationVerification" CASCADE;`; // await prisma.$queryRaw`TRUNCATE TABLE "CommunityMember" CASCADE;`; + + nock.restore(); }); it('should allow only members verify a node attestation(claim)', async () => { - let scope = nock('https://api.sandbox.orcid.org/v3.0') + const scope1 = nock('https://api.sandbox.orcid.org/v3.0') .post(`${ORCID_ID}/work`) .once() .reply(201, '', { location: `https://api.sandbox.orcid.org/v3.0/${ORCID_ID}/work/${mockPutCode}` }); @@ -2185,7 +2187,7 @@ describe('Attestations Service', async () => { orcid: ORCID_ID, }); - console.log('VERIFICATION HTTPS MOCK', scope); + console.log('VERIFICATION HTTPS MOCK', scope1); let res = await request(app) .post(`/v1/attestations/verification`) .set('authorization', memberAuthHeaderVal1) @@ -2194,12 +2196,22 @@ describe('Attestations Service', async () => { }); expect(res.statusCode).to.equal(200); - scope = nock('https://api.sandbox.orcid.org/v3.0').put(`${ORCID_ID}/work/${mockPutCode}`).once().reply(200); + setTimeout(() => { + scope1.isDone(); + }, 100); + + const scope2 = nock('https://api.sandbox.orcid.org/v3.0') + .put(`${ORCID_ID}/work/${mockPutCode}`) + .once() + .reply(200); res = await request(app).post(`/v1/attestations/verification`).set('authorization', memberAuthHeaderVal2).send({ claimId: openCodeClaim.id, }); expect(res.statusCode).to.equal(200); + setTimeout(() => { + scope2.isDone(); + }, 100); const verifications = await attestationService.getAllClaimVerfications(openCodeClaim.id); expect(verifications.length).to.equal(2); From 524318131d2948b3edeb6417764936a27f86de81 Mon Sep 17 00:00:00 2001 From: shadrach-tayo Date: Wed, 15 May 2024 02:37:27 +0200 Subject: [PATCH 5/9] remove nock scope from timeouts --- .../test/integration/Attestation.test.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/desci-server/test/integration/Attestation.test.ts b/desci-server/test/integration/Attestation.test.ts index b7577d025..912962587 100644 --- a/desci-server/test/integration/Attestation.test.ts +++ b/desci-server/test/integration/Attestation.test.ts @@ -2177,7 +2177,7 @@ describe('Attestations Service', async () => { .once() .reply(201, '', { location: `https://api.sandbox.orcid.org/v3.0/${ORCID_ID}/work/${mockPutCode}` }); - nock(`https://sandbox.orcid.org/oauth/token`).post(`${ORCID_ID}/work`).twice().reply(200, { + const scope2 = nock(`https://sandbox.orcid.org/oauth/token`).post(`${ORCID_ID}/work`).twice().reply(200, { access_token: 'access-token', token_type: 'auth', refresh_token: 'refresh-token', @@ -2196,11 +2196,12 @@ describe('Attestations Service', async () => { }); expect(res.statusCode).to.equal(200); - setTimeout(() => { - scope1.isDone(); - }, 100); + scope1.isDone(); + scope2.isDone(); + // setTimeout(() => { + // }, 100); - const scope2 = nock('https://api.sandbox.orcid.org/v3.0') + const scope3 = nock('https://api.sandbox.orcid.org/v3.0') .put(`${ORCID_ID}/work/${mockPutCode}`) .once() .reply(200); @@ -2209,9 +2210,9 @@ describe('Attestations Service', async () => { claimId: openCodeClaim.id, }); expect(res.statusCode).to.equal(200); - setTimeout(() => { - scope2.isDone(); - }, 100); + scope2.isDone(); + // setTimeout(() => { + // }, 100); const verifications = await attestationService.getAllClaimVerfications(openCodeClaim.id); expect(verifications.length).to.equal(2); From 28d5772236c5ffa67b270d26f878eaba8a9dfce8 Mon Sep 17 00:00:00 2001 From: shadrach-tayo Date: Wed, 15 May 2024 02:44:42 +0200 Subject: [PATCH 6/9] log interceptor scopes --- desci-server/test/integration/Attestation.test.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/desci-server/test/integration/Attestation.test.ts b/desci-server/test/integration/Attestation.test.ts index 912962587..638c06522 100644 --- a/desci-server/test/integration/Attestation.test.ts +++ b/desci-server/test/integration/Attestation.test.ts @@ -2187,7 +2187,6 @@ describe('Attestations Service', async () => { orcid: ORCID_ID, }); - console.log('VERIFICATION HTTPS MOCK', scope1); let res = await request(app) .post(`/v1/attestations/verification`) .set('authorization', memberAuthHeaderVal1) @@ -2210,7 +2209,7 @@ describe('Attestations Service', async () => { claimId: openCodeClaim.id, }); expect(res.statusCode).to.equal(200); - scope2.isDone(); + scope3.isDone(); // setTimeout(() => { // }, 100); @@ -2218,6 +2217,10 @@ describe('Attestations Service', async () => { expect(verifications.length).to.equal(2); expect(verifications.some((v) => v.userId === members[0].userId)).to.equal(true); expect(verifications.some((v) => v.userId === members[1].userId)).to.equal(true); + + console.log('INTERCEPTOR SCOPE', scope1); + console.log('INTERCEPTOR SCOPE', scope2); + console.log('INTERCEPTOR SCOPE', scope3); }); it('should prevent non-authorized users from verifying a protected attestation(claim)', async () => { From 42bfbe2f324dc9a64e1c174f76f094b7b7887e8c Mon Sep 17 00:00:00 2001 From: shadrach-tayo Date: Wed, 15 May 2024 03:12:11 +0200 Subject: [PATCH 7/9] update nock scope options --- desci-server/package.json | 2 +- desci-server/test/integration/Attestation.test.ts | 12 +++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/desci-server/package.json b/desci-server/package.json index de7bf9847..c08be75f4 100755 --- a/desci-server/package.json +++ b/desci-server/package.json @@ -35,7 +35,7 @@ "lint-staged-husky": "lint-staged", "lint-prettier": "prettier --config .prettierrc --list-different '{src,test}/**/*.{ts,js,css,scss}'", "prettier": "prettier --config .prettierrc --write './**/*.{ts,js,css,scss,json,md}'", - "test:destructive": "NODE_OPTIONS=\"--experimental-specifier-resolution=node --loader=ts-node/esm\" mocha --colors --require ts-node/register 'test/integration/**/*.test.ts' --timeout 20000 --exit", + "test:destructive": "NODE_OPTIONS=\"--experimental-specifier-resolution=node --loader=ts-node/esm\" DEBUG=nock.desci-server mocha --colors --require ts-node/register 'test/integration/**/*.test.ts' --timeout 20000 --exit", "test:destructive:debug": "yarn test:destructive --inspect=0.0.0.0:9227", "test": "yarn docker:test; export EXIT=$(echo $?); docker-compose --file ../docker-compose.test.yml --compatibility down; exit $EXIT", "coverage:destructive": "nyc --all --parser-plugins='[\"importAssertions\"]' -r lcov -e .ts -x \"*.test.ts\" npm run test:destructive", diff --git a/desci-server/test/integration/Attestation.test.ts b/desci-server/test/integration/Attestation.test.ts index 638c06522..6f71ed323 100644 --- a/desci-server/test/integration/Attestation.test.ts +++ b/desci-server/test/integration/Attestation.test.ts @@ -2109,6 +2109,7 @@ describe('Attestations Service', async () => { memberAuthHeaderVal2: string; const mockPutCode = '1926486'; const ORCID_ID = '0000-0000-1111-090X'; + const NOCK_URL = new URL('https://api.sandbox.orcid.org'); before(async () => { node = nodes[0]; @@ -2172,12 +2173,12 @@ describe('Attestations Service', async () => { }); it('should allow only members verify a node attestation(claim)', async () => { - const scope1 = nock('https://api.sandbox.orcid.org/v3.0') - .post(`${ORCID_ID}/work`) + const scope1 = nock(NOCK_URL) + .post(`/v3.0/${ORCID_ID}/work`) .once() .reply(201, '', { location: `https://api.sandbox.orcid.org/v3.0/${ORCID_ID}/work/${mockPutCode}` }); - const scope2 = nock(`https://sandbox.orcid.org/oauth/token`).post(`${ORCID_ID}/work`).twice().reply(200, { + const scope2 = nock(new URL('https://sandbox.orcid.org')).post(`/oauth/token`).twice().reply(200, { access_token: 'access-token', token_type: 'auth', refresh_token: 'refresh-token', @@ -2200,10 +2201,7 @@ describe('Attestations Service', async () => { // setTimeout(() => { // }, 100); - const scope3 = nock('https://api.sandbox.orcid.org/v3.0') - .put(`${ORCID_ID}/work/${mockPutCode}`) - .once() - .reply(200); + const scope3 = nock(NOCK_URL).put(`/v3.0/${ORCID_ID}/work/${mockPutCode}`).once().reply(200); res = await request(app).post(`/v1/attestations/verification`).set('authorization', memberAuthHeaderVal2).send({ claimId: openCodeClaim.id, From 2c8a9d9a65bf779de8baf0af38b8eb6b378a0af5 Mon Sep 17 00:00:00 2001 From: shadrach-tayo Date: Wed, 15 May 2024 04:15:16 +0200 Subject: [PATCH 8/9] debug nock interceptors --- .env.test | 3 ++- desci-server/package.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.env.test b/.env.test index a20e598d1..b13c5ffc5 100644 --- a/.env.test +++ b/.env.test @@ -72,4 +72,5 @@ VSCODE_ACCESS_TOKEN= NODES_MEDIA_SERVER_URL=http://host.docker.internal:5454 REPO_SERVICE_SECRET_KEY="m8sIy5BPygBcX3+ZmMVuAA10k6w59BSCZd+Z5+VLYm4=" -REPO_SERVER_URL=http://host.docker.internal:5485 \ No newline at end of file +REPO_SERVER_URL=http://host.docker.internal:5485 +DEBUG=nock.desci-server \ No newline at end of file diff --git a/desci-server/package.json b/desci-server/package.json index c08be75f4..de7bf9847 100755 --- a/desci-server/package.json +++ b/desci-server/package.json @@ -35,7 +35,7 @@ "lint-staged-husky": "lint-staged", "lint-prettier": "prettier --config .prettierrc --list-different '{src,test}/**/*.{ts,js,css,scss}'", "prettier": "prettier --config .prettierrc --write './**/*.{ts,js,css,scss,json,md}'", - "test:destructive": "NODE_OPTIONS=\"--experimental-specifier-resolution=node --loader=ts-node/esm\" DEBUG=nock.desci-server mocha --colors --require ts-node/register 'test/integration/**/*.test.ts' --timeout 20000 --exit", + "test:destructive": "NODE_OPTIONS=\"--experimental-specifier-resolution=node --loader=ts-node/esm\" mocha --colors --require ts-node/register 'test/integration/**/*.test.ts' --timeout 20000 --exit", "test:destructive:debug": "yarn test:destructive --inspect=0.0.0.0:9227", "test": "yarn docker:test; export EXIT=$(echo $?); docker-compose --file ../docker-compose.test.yml --compatibility down; exit $EXIT", "coverage:destructive": "nyc --all --parser-plugins='[\"importAssertions\"]' -r lcov -e .ts -x \"*.test.ts\" npm run test:destructive", From 54dc749c7681b6938d611be4e1e15b0284014329 Mon Sep 17 00:00:00 2001 From: shadrach-tayo Date: Wed, 15 May 2024 04:42:04 +0200 Subject: [PATCH 9/9] mock inspect --- desci-server/src/services/orcid.ts | 10 +++++----- desci-server/test/integration/Attestation.test.ts | 9 ++++++--- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/desci-server/src/services/orcid.ts b/desci-server/src/services/orcid.ts index dfa2271d4..8b26a4bf6 100644 --- a/desci-server/src/services/orcid.ts +++ b/desci-server/src/services/orcid.ts @@ -87,13 +87,13 @@ class OrcidApiService { }); logger.info({ status: response.status, statusText: response.statusText, data }, 'REFRESH TOKEN RESPONSE'); } else { - logger.info( + logger.error( { status: response.status, statusText: response.statusText, BODY: await response.json() }, 'REFRESH TOKEN ERROR', ); } } catch (err) { - logger.info({ err }, 'ORCID REFRESH TOKEN ERROR'); + logger.error({ err }, 'ORCID REFRESH TOKEN ERROR'); } return authToken.accessToken; @@ -362,7 +362,7 @@ class OrcidApiService { ); } } catch (err) { - logger.info({ err }, '[ORCID_API_SERVICE]::NODE API Error Response'); + logger.error({ err }, '[ORCID_API_SERVICE]::NODE API Error Response'); } } @@ -473,13 +473,13 @@ class OrcidApiService { 'ORCID CLAIM RECORD UPDATED', ); } else { - logger.info( + logger.error( { status: response.status, response, body: await response.text() }, '[ORCID_API_SERVICE]::ORCID CLAIM API ERROR', ); } } catch (err) { - logger.info({ err }, '[ORCID_API_SERVICE]::CLAIM API Error Response'); + logger.error({ err }, '[ORCID_API_SERVICE]::CLAIM API Error Response'); } } } diff --git a/desci-server/test/integration/Attestation.test.ts b/desci-server/test/integration/Attestation.test.ts index 6f71ed323..a4d067b94 100644 --- a/desci-server/test/integration/Attestation.test.ts +++ b/desci-server/test/integration/Attestation.test.ts @@ -2188,6 +2188,7 @@ describe('Attestations Service', async () => { orcid: ORCID_ID, }); + console.log('ACTIVE MOCKS', nock.activeMocks()); let res = await request(app) .post(`/v1/attestations/verification`) .set('authorization', memberAuthHeaderVal1) @@ -2196,8 +2197,6 @@ describe('Attestations Service', async () => { }); expect(res.statusCode).to.equal(200); - scope1.isDone(); - scope2.isDone(); // setTimeout(() => { // }, 100); @@ -2207,7 +2206,7 @@ describe('Attestations Service', async () => { claimId: openCodeClaim.id, }); expect(res.statusCode).to.equal(200); - scope3.isDone(); + // setTimeout(() => { // }, 100); @@ -2216,6 +2215,10 @@ describe('Attestations Service', async () => { expect(verifications.some((v) => v.userId === members[0].userId)).to.equal(true); expect(verifications.some((v) => v.userId === members[1].userId)).to.equal(true); + console.log('Pending MOCKS', nock.pendingMocks()); + scope1.done(); + scope2.done(); + scope3.done(); console.log('INTERCEPTOR SCOPE', scope1); console.log('INTERCEPTOR SCOPE', scope2); console.log('INTERCEPTOR SCOPE', scope3);