diff --git a/packages/nodes-base/nodes/GraphQL/GraphQL.node.ts b/packages/nodes-base/nodes/GraphQL/GraphQL.node.ts index 1480e847b2..53682b1a9c 100644 --- a/packages/nodes-base/nodes/GraphQL/GraphQL.node.ts +++ b/packages/nodes-base/nodes/GraphQL/GraphQL.node.ts @@ -497,9 +497,20 @@ export class GraphQL implements INodeType { if (oAuth1Api !== undefined) { response = await this.helpers.requestOAuth1.call(this, 'oAuth1Api', requestOptions); } else if (oAuth2Api !== undefined) { - response = await this.helpers.requestOAuth2.call(this, 'oAuth2Api', requestOptions, { - tokenType: 'Bearer', - }); + response = await this.helpers.requestOAuth2.call( + this, + 'oAuth2Api', + { + ...requestOptions, + // needed for the refresh mechanism to work properly + resolveWithFullResponse: true, + }, + { + tokenType: 'Bearer', + }, + ); + // since we are using `resolveWithFullResponse: true`, we need to grab the body + response = response.body; } else { response = await this.helpers.request(requestOptions); } diff --git a/packages/nodes-base/nodes/GraphQL/test/GraphQL.node.test.ts b/packages/nodes-base/nodes/GraphQL/test/GraphQL.node.test.ts index 44bbf1e18c..97785f909a 100644 --- a/packages/nodes-base/nodes/GraphQL/test/GraphQL.node.test.ts +++ b/packages/nodes-base/nodes/GraphQL/test/GraphQL.node.test.ts @@ -2,9 +2,8 @@ import { NodeTestHarness } from '@nodes-testing/node-test-harness'; import nock from 'nock'; describe('GraphQL Node', () => { - const baseUrl = 'https://api.n8n.io/'; - - beforeAll(async () => { + describe('valid request', () => { + const baseUrl = 'https://api.n8n.io/'; nock(baseUrl) .matchHeader('accept', 'application/json') .matchHeader('content-type', 'application/json') @@ -54,7 +53,61 @@ describe('GraphQL Node', () => { }, }, }); + + new NodeTestHarness().setupTests({ + workflowFiles: ['workflow.json'], + }); }); - new NodeTestHarness().setupTests(); + describe('invalid expression', () => { + new NodeTestHarness().setupTests({ + workflowFiles: ['workflow.error_invalid_expression.json'], + }); + }); + + describe('oauth2 refresh token', () => { + const credentials = { + oAuth2Api: { + scope: '', + accessTokenUrl: 'http://test/token', + clientId: 'dummy_client_id', + clientSecret: 'dummy_client_secret', + oauthTokenData: { + access_token: 'dummy_access_token', + refresh_token: 'dummy_refresh_token', + }, + }, + }; + const baseUrl = 'http://test'; + nock(baseUrl) + .post('/graphql', '{"query":"query { foo }","variables":{},"operationName":null}') + .reply(401, { + errors: [ + { + message: 'Unauthorized', + }, + ], + }); + nock(baseUrl) + .post('/token', { + refresh_token: 'dummy_refresh_token', + grant_type: 'refresh_token', + }) + .reply(200, { + access_token: 'dummy_access_token', + refresh_token: 'dummy_refresh_token', + expires_in: 3600, + }); + nock(baseUrl) + .post('/graphql', '{"query":"query { foo }","variables":{},"operationName":null}') + .reply(200, { + data: { + foo: 'bar', + }, + }); + new NodeTestHarness().setupTests({ + workflowFiles: ['workflow.refresh_token.json'], + credentials, + }); + }); }); diff --git a/packages/nodes-base/nodes/GraphQL/test/workflow.refresh_token.json b/packages/nodes-base/nodes/GraphQL/test/workflow.refresh_token.json new file mode 100644 index 0000000000..2e9859063a --- /dev/null +++ b/packages/nodes-base/nodes/GraphQL/test/workflow.refresh_token.json @@ -0,0 +1,67 @@ +{ + "name": "GraphQL Refersh Token", + "nodes": [ + { + "parameters": {}, + "id": "ae67b437-48c0-4c4b-9c8f-005b8911ca5f", + "name": "When clicking ‘Execute workflow’", + "type": "n8n-nodes-base.manualTrigger", + "typeVersion": 1, + "position": [32, 80] + }, + { + "parameters": { + "authentication": "oAuth2", + "endpoint": "http://test/graphql", + "requestFormat": "json", + "query": "query { foo }" + }, + "name": "GraphQL", + "type": "n8n-nodes-base.graphql", + "typeVersion": 1, + "position": [256, 80], + "id": "6cb4c117-907a-40b9-b3ba-cd3756b1cb7b", + "credentials": { + "oAuth2Api": { + "id": "PpmTbnw41Q2nqqoW", + "name": "Dummy (local)" + } + } + } + ], + "pinData": { + "GraphQL": [ + { + "json": { + "data": { + "foo": "bar" + } + } + } + ] + }, + "connections": { + "When clicking ‘Execute workflow’": { + "main": [ + [ + { + "node": "GraphQL", + "type": "main", + "index": 0 + } + ] + ] + } + }, + "active": false, + "settings": { + "executionOrder": "v1" + }, + "versionId": "659c76f4-ac29-4c2f-bf40-70b476afbc1d", + "meta": { + "templateCredsSetupCompleted": true, + "instanceId": "eeda9e3069aca300d1dfceeb64beb5b53d715db44a50461bbc5cb0cf6daa01e3" + }, + "id": "O4IzQ2D7h7cfZtB4", + "tags": [] +}