From 476db5d7551755581ada5521ebffaa81a003c548 Mon Sep 17 00:00:00 2001 From: apotdevin Date: Wed, 3 Feb 2021 07:13:04 +0100 Subject: [PATCH] =?UTF-8?q?fix:=20=F0=9F=90=9B=20callback=20with=20query?= =?UTF-8?q?=20string?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../lnurl/__snapshots__/lnurl.test.ts.snap | 31 ++++++ server/schema/lnurl/lnurl.test.ts | 94 +++++++++++++++++++ server/schema/lnurl/resolvers.ts | 5 +- server/tests/__mocks__/ln-service.ts | 4 + server/tests/lnServiceResponse.ts | 7 ++ 5 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 server/schema/lnurl/__snapshots__/lnurl.test.ts.snap create mode 100644 server/schema/lnurl/lnurl.test.ts diff --git a/server/schema/lnurl/__snapshots__/lnurl.test.ts.snap b/server/schema/lnurl/__snapshots__/lnurl.test.ts.snap new file mode 100644 index 00000000..920690de --- /dev/null +++ b/server/schema/lnurl/__snapshots__/lnurl.test.ts.snap @@ -0,0 +1,31 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`LNURL Resolvers getBitcoinPrice failure 1`] = ` +Object { + "data": null, + "errors": Array [ + [GraphQLError: ProblemWithdrawingFromLnUrlService], + ], + "extensions": undefined, + "http": Object { + "headers": Headers { + Symbol(map): Object {}, + }, + }, +} +`; + +exports[`LNURL Resolvers getBitcoinPrice success 1`] = ` +Object { + "data": Object { + "lnUrlWithdraw": "requestId", + }, + "errors": undefined, + "extensions": undefined, + "http": Object { + "headers": Headers { + Symbol(map): Object {}, + }, + }, +} +`; diff --git a/server/schema/lnurl/lnurl.test.ts b/server/schema/lnurl/lnurl.test.ts new file mode 100644 index 00000000..43d7b371 --- /dev/null +++ b/server/schema/lnurl/lnurl.test.ts @@ -0,0 +1,94 @@ +import testServer from 'server/tests/testServer'; +import fetchMock from 'jest-fetch-mock'; +import { GraphQLError } from 'graphql'; +import { WITHDRAW_LN_URL } from 'src/graphql/mutations/lnUrl'; + +jest.mock('ln-service'); + +describe('LNURL Resolvers', () => { + beforeEach(() => { + fetchMock.resetMocks(); + }); + describe('getBitcoinPrice', () => { + test('success', async () => { + fetchMock.mockResponseOnce(JSON.stringify({ status: 'SUCCESS' })); + const { mutate } = testServer(); + + const res = await mutate({ + mutation: WITHDRAW_LN_URL, + variables: { + callback: 'https://domain.com', + amount: 1000, + k1: 'random', + description: 'ln-withdraw', + }, + }); + + expect(res.errors).toBe(undefined); + + expect(fetchMock).toBeCalledWith( + 'https://domain.com?k1=random&pr=boltEncodedRequest', + undefined + ); + expect(res).toMatchSnapshot(); + }); + test('success with callback that has query string', async () => { + fetchMock.mockResponseOnce(JSON.stringify({ status: 'SUCCESS' })); + const { mutate } = testServer(); + + const res = await mutate({ + mutation: WITHDRAW_LN_URL, + variables: { + callback: 'https://domain.com?user=123456', + amount: 1000, + k1: 'random', + description: 'ln-withdraw', + }, + }); + + expect(res.errors).toBe(undefined); + + expect(fetchMock).toBeCalledWith( + 'https://domain.com?user=123456&k1=random&pr=boltEncodedRequest', + undefined + ); + }); + test('success but not able to withdraw', async () => { + fetchMock.mockResponseOnce(JSON.stringify({ status: 'ERROR' })); + const { mutate } = testServer(); + + const res = await mutate({ + mutation: WITHDRAW_LN_URL, + variables: { + callback: 'https://domain.com', + amount: 1000, + k1: 'random', + description: 'ln-withdraw', + }, + }); + + expect(res.errors).toStrictEqual([ + new GraphQLError('ProblemWithdrawingFromLnUrlService'), + ]); + }); + test('failure', async () => { + fetchMock.mockRejectOnce(new Error('Error')); + const { mutate } = testServer(); + + const res = await mutate({ + mutation: WITHDRAW_LN_URL, + variables: { + callback: 'domain.com', + amount: 1000, + k1: 'random', + description: 'ln-withdraw', + }, + }); + + expect(res.errors).toStrictEqual([ + new GraphQLError('ProblemWithdrawingFromLnUrlService'), + ]); + expect(res).toMatchSnapshot(); + }); + }); +}); diff --git a/server/schema/lnurl/resolvers.ts b/server/schema/lnurl/resolvers.ts index ab03b4b7..9db934dc 100644 --- a/server/schema/lnurl/resolvers.ts +++ b/server/schema/lnurl/resolvers.ts @@ -213,7 +213,10 @@ export const lnUrlResolvers = { createInvoice({ lnd, tokens: amount, description }) ); - const finalUrl = `${callback}?k1=${k1}&pr=${info.request}`; + // If the callback url already has an initial query '?' identifier we don't need to add it again. + const initialIdentifier = callback.indexOf('?') != -1 ? '&' : '?'; + + const finalUrl = `${callback}${initialIdentifier}k1=${k1}&pr=${info.request}`; try { const response = await fetchWithProxy(finalUrl); diff --git a/server/tests/__mocks__/ln-service.ts b/server/tests/__mocks__/ln-service.ts index 7fd77e3b..23da570e 100644 --- a/server/tests/__mocks__/ln-service.ts +++ b/server/tests/__mocks__/ln-service.ts @@ -103,3 +103,7 @@ export const verifyMessage = jest export const getPublicKey = jest .fn() .mockReturnValue(Promise.resolve(res.getPublicKeyResponse)); + +export const createInvoice = jest + .fn() + .mockReturnValue(Promise.resolve(res.createInvoiceResponse)); diff --git a/server/tests/lnServiceResponse.ts b/server/tests/lnServiceResponse.ts index 0b8dd2b3..9a1f48cc 100644 --- a/server/tests/lnServiceResponse.ts +++ b/server/tests/lnServiceResponse.ts @@ -763,3 +763,10 @@ export const verifyMessageResponse = { export const getPublicKeyResponse = { public_key: 'public_key', }; + +export const createInvoiceResponse = { + request: 'boltEncodedRequest', + created_at: '', + id: 'requestId', + secret: 'secretString', +};