Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module.exports = {
// https://github.com/facebook/jest/issues/2070#issuecomment-431706685
'<rootDir>/.*/__mocks__'
],
testPathIgnorePatterns: ['/__tests__/helper/'],
globals: {
__VERSION__: packageJSON.version
}
Expand Down
3 changes: 0 additions & 3 deletions sample/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ elements.authorizeBtn.onclick = () => {
authorizeOptions.scopes = scopesSelectedOptions.map((x) => x.value);
}

authorizeOptions.pkce = true;

mtLinkSdk.authorize(authorizeOptions);
};

Expand All @@ -75,7 +73,6 @@ elements.doOnboardBtn.onclick = async () => {
}

onBoardOptions.email = onboardOptionsElms.email.value;
onBoardOptions.pkce = true;

mtLinkSdk.onboard(onBoardOptions);
} catch (error) {
Expand Down
21 changes: 21 additions & 0 deletions src/__tests__/helper/expect-url-to-match.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import qs from 'qs';

export interface UrlExpectation {
baseUrl: string;
path: string;
query?: Record<string, string>;
}

export default function expectUrlToMatchWithPKCE(actual: URL | string, expectation: UrlExpectation) {
const url = typeof actual === 'string' ? new URL(actual) : actual;
const actualQuery = qs.parse(new URLSearchParams(url.search).toString());

expect(actualQuery.code_challenge).toBeDefined();
delete actualQuery.code_challenge; // ignore PKCE code challenge because it's randomly generated
expect(actualQuery.code_challenge_method).toBe('S256');
delete actualQuery.code_challenge_method;

expect(url.pathname).toBe(expectation.path);
expect(`${url.protocol}//${url.hostname}`).toBe(expectation.baseUrl);
expect(actualQuery).toEqual(expectation.query || {});
}
32 changes: 22 additions & 10 deletions src/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import tokenInfo from '../api/token-info';
import mtLinkSdk, { Mode, MtLinkSdk } from '..';

import packageJson from '../../package.json';
import expectUrlToMatchWithPKCE from './helper/expect-url-to-match';

jest.mock('../api/authorize');
jest.mock('../api/onboard');
Expand Down Expand Up @@ -80,19 +81,30 @@ describe('index', () => {

const sdkVersion = packageJson.version;

const authQuery = {
client_id: 'clientId',
response_type: 'code',
scope: 'scopes',
redirect_uri: 'redirectUri',
country: 'JP',
configs: `authn_method=sso&sdk_platform=js&sdk_version=${sdkVersion}`
}
const result8 = instance.authorizeUrl({ scopes: 'scopes' });
expect(result8).toBe(
'https://myaccount.getmoneytree.com/oauth/authorize?client_id=clientId&response_type=code&' +
'scope=scopes&redirect_uri=redirectUri&country=JP&saml_subject_id=samlSubjectId&' +
`configs=authn_method%3Dsso%26sdk_platform%3Djs%26sdk_version%3D${sdkVersion}`
);
expectUrlToMatchWithPKCE(result8, {
baseUrl: 'https://myaccount.getmoneytree.com',
path: '/oauth/authorize',
query: {
...authQuery,
saml_subject_id: 'samlSubjectId',
}
})

const result9 = instance.onboardUrl({ scopes: 'scopes' });
expect(result9).toBe(
'https://myaccount.getmoneytree.com/onboard?client_id=clientId&response_type=code&' +
'scope=scopes&redirect_uri=redirectUri&country=JP&' +
`configs=authn_method%3Dsso%26sdk_platform%3Djs%26sdk_version%3D${sdkVersion}`
);
expectUrlToMatchWithPKCE(result9, {
baseUrl: 'https://myaccount.getmoneytree.com',
path: '/onboard',
query: authQuery
})

const result10 = instance.logoutUrl({ backTo: 'backTo' });
expect(result10).toBe(
Expand Down
15 changes: 7 additions & 8 deletions src/api/__tests__/authorize-url.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import qs from 'qs';
import { mocked } from 'ts-jest/utils';

import { MY_ACCOUNT_DOMAINS } from '../../server-paths';
import { MtLinkSdk } from '../..';
import authorizeUrl from '../authorize-url';
import { generateConfigs } from '../../helper';
import storage from '../../storage';
import expectUrlToMatchWithPKCE from '../../__tests__/helper/expect-url-to-match';

jest.mock('../../storage');

Expand Down Expand Up @@ -53,7 +53,7 @@ describe('api', () => {

const url = authorizeUrl(mtLinkSdk.storedOptions);

const query = qs.stringify({
const query = {
client_id: clientId,
cobrand_client_id: cobrandClientId,
response_type: 'code',
Expand All @@ -63,9 +63,8 @@ describe('api', () => {
locale,
saml_subject_id: samlSubjectId,
configs: generateConfigs()
});

expect(url).toBe(`${MY_ACCOUNT_DOMAINS.production}/oauth/authorize?${query}`);
};
expectUrlToMatchWithPKCE(url, {baseUrl: MY_ACCOUNT_DOMAINS.production, path: '/oauth/authorize', query})
});

test('with options', () => {
Expand All @@ -85,7 +84,7 @@ describe('api', () => {
scopes
});

const query = qs.stringify({
const query = {
client_id: clientId,
response_type: 'code',
scope: scopes,
Expand All @@ -94,8 +93,8 @@ describe('api', () => {
country,
saml_subject_id: samlSubjectId,
configs: generateConfigs()
});
expect(url).toBe(`${MY_ACCOUNT_DOMAINS.production}/oauth/authorize?${query}`);
}
expectUrlToMatchWithPKCE(url, {baseUrl: MY_ACCOUNT_DOMAINS.production, path: '/oauth/authorize', query})
});
});
});
22 changes: 11 additions & 11 deletions src/api/__tests__/authorize.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import qs from 'qs';
import { mocked } from 'ts-jest/utils';

import { MY_ACCOUNT_DOMAINS } from '../../server-paths';
import { MtLinkSdk } from '../..';
import authorize from '../authorize';
import { generateConfigs } from '../../helper';
import storage from '../../storage';
import expectUrlToMatchWithPKCE from '../../__tests__/helper/expect-url-to-match';

jest.mock('../../storage');

Expand Down Expand Up @@ -57,8 +57,9 @@ describe('api', () => {
authorize(mtLinkSdk.storedOptions);

expect(open).toBeCalledTimes(1);

const query = qs.stringify({
expect(open).toBeCalledWith(expect.any(String), '_self', 'noreferrer');
const url = open.mock.calls[0][0]
const query = {
client_id: clientId,
cobrand_client_id: cobrandClientId,
response_type: 'code',
Expand All @@ -68,9 +69,8 @@ describe('api', () => {
locale,
saml_subject_id: samlSubjectId,
configs: generateConfigs()
});
const url = `${MY_ACCOUNT_DOMAINS.production}/oauth/authorize?${query}`;
expect(open).toBeCalledWith(url, '_self', 'noreferrer');
};
expectUrlToMatchWithPKCE(url, {baseUrl: MY_ACCOUNT_DOMAINS.production, path: '/oauth/authorize', query })
});

test('with options', () => {
Expand All @@ -92,8 +92,9 @@ describe('api', () => {
});

expect(open).toBeCalledTimes(1);

const query = qs.stringify({
expect(open).toBeCalledWith(expect.any(String), '_self', 'noreferrer');
const url = open.mock.calls[0][0]
const query = {
client_id: clientId,
response_type: 'code',
scope: scopes,
Expand All @@ -102,9 +103,8 @@ describe('api', () => {
country,
saml_subject_id: samlSubjectId,
configs: generateConfigs()
});
const url = `${MY_ACCOUNT_DOMAINS.production}/oauth/authorize?${query}`;
expect(open).toBeCalledWith(url, '_self', 'noreferrer');
};
expectUrlToMatchWithPKCE(url, {baseUrl: MY_ACCOUNT_DOMAINS.production, path: '/oauth/authorize', query })
});

test('without window', () => {
Expand Down
24 changes: 13 additions & 11 deletions src/api/__tests__/onboard-url.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { MtLinkSdk } from '../..';
import onboardUrl from '../onboard-url';
import { generateConfigs } from '../../helper';
import storage from '../../storage';
import expectUrlToMatchWithPKCE from '../../__tests__/helper/expect-url-to-match';

jest.mock('../../storage');

Expand Down Expand Up @@ -53,7 +54,7 @@ describe('api', () => {

const url = onboardUrl(mtLinkSdk.storedOptions);

const query = qs.stringify({
const query = {
client_id: clientId,
cobrand_client_id: cobrandClientId,
response_type: 'code',
Expand All @@ -62,9 +63,9 @@ describe('api', () => {
country,
locale,
configs: generateConfigs({ email })
});
};

expect(url).toBe(`${MY_ACCOUNT_DOMAINS.production}/onboard?${query}`);
expectUrlToMatchWithPKCE(url, {baseUrl: MY_ACCOUNT_DOMAINS.production, path: '/onboard', query: query })
});

test('with options', () => {
Expand All @@ -78,23 +79,24 @@ describe('api', () => {
mtLinkSdk.init(clientId);

const url = onboardUrl(mtLinkSdk.storedOptions, {
state,
redirectUri,
scopes,
email
});
state,
redirectUri,
scopes,
email
}
);

const query = qs.stringify({
const query = {
client_id: clientId,
response_type: 'code',
scope: scopes,
redirect_uri: redirectUri,
state,
country,
configs: generateConfigs({ email })
});
};

expect(url).toBe(`${MY_ACCOUNT_DOMAINS.production}/onboard?${query}`);
expectUrlToMatchWithPKCE(url, {baseUrl: MY_ACCOUNT_DOMAINS.production, path: '/onboard', query})
});
});
});
23 changes: 12 additions & 11 deletions src/api/__tests__/onboard.test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import qs from 'qs';
import { mocked } from 'ts-jest/utils';

import { MY_ACCOUNT_DOMAINS } from '../../server-paths';
import { MtLinkSdk } from '../..';
import onboard from '../onboard';
import { generateConfigs } from '../../helper';
import storage from '../../storage';
import expectUrlToMatchWithPKCE from '../../__tests__/helper/expect-url-to-match';

jest.mock('../../storage');

Expand Down Expand Up @@ -57,8 +57,9 @@ describe('api', () => {
onboard(mtLinkSdk.storedOptions);

expect(open).toBeCalledTimes(1);

const query = qs.stringify({
expect(open).toBeCalledWith(expect.any(String), '_self', 'noreferrer');
const url = open.mock.calls[0][0]
const query = {
client_id: clientId,
cobrand_client_id: cobrandClientId,
response_type: 'code',
Expand All @@ -67,9 +68,8 @@ describe('api', () => {
country,
locale,
configs: generateConfigs({ email })
});
const url = `${MY_ACCOUNT_DOMAINS.production}/onboard?${query}`;
expect(open).toBeCalledWith(url, '_self', 'noreferrer');
};
expectUrlToMatchWithPKCE(url, {baseUrl: MY_ACCOUNT_DOMAINS.production, path: '/onboard', query})
});

test('with options', () => {
Expand All @@ -91,18 +91,19 @@ describe('api', () => {
});

expect(open).toBeCalledTimes(1);

const query = qs.stringify({
expect(open).toBeCalledWith(expect.any(String), '_self', 'noreferrer');
const url = open.mock.calls[0][0]
const query = {
client_id: clientId,
response_type: 'code',
scope: scopes,
redirect_uri: redirectUri,
state,
country,
configs: generateConfigs({ email })
});
const url = `${MY_ACCOUNT_DOMAINS.production}/onboard?${query}`;
expect(open).toBeCalledWith(url, '_self', 'noreferrer');
};

expectUrlToMatchWithPKCE(url, {baseUrl: MY_ACCOUNT_DOMAINS.production, path: '/onboard', query})
});

test('without window', () => {
Expand Down
11 changes: 2 additions & 9 deletions src/api/authorize-url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,7 @@ export default function authorize(storedOptions: StoredOptions, options: Authori
throw new Error('[mt-link-sdk] Make sure to call `init` before calling `authorizeUrl/authorize`.');
}

const {
scopes = defaultScopes,
redirectUri = defaultRedirectUri,
pkce = false,
codeChallenge,
state,
...rest
} = options;
const { scopes = defaultScopes, redirectUri = defaultRedirectUri, codeChallenge, state, ...rest } = options;

if (!redirectUri) {
throw new Error(
Expand All @@ -37,7 +30,7 @@ export default function authorize(storedOptions: StoredOptions, options: Authori

storage.del('cv');

const cc = codeChallenge || (pkce && generateCodeChallenge());
const cc = codeChallenge || generateCodeChallenge();

const queryString = stringify({
client_id: clientId,
Expand Down
11 changes: 2 additions & 9 deletions src/api/onboard-url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,7 @@ export default function onboardUrl(storedOptions: StoredOptions, options: Onboar
throw new Error('[mt-link-sdk] Make sure to call `init` before calling `onboardUrl/onboard`.');
}

const {
scopes = defaultScopes,
redirectUri = defaultRedirectUri,
pkce = false,
codeChallenge,
state,
...rest
} = options;
const { scopes = defaultScopes, redirectUri = defaultRedirectUri, codeChallenge, state, ...rest } = options;

const configs = mergeConfigs(storedOptions, rest, ['authAction', 'showAuthToggle', 'showRememberMe', 'forceLogout']);

Expand All @@ -38,7 +31,7 @@ export default function onboardUrl(storedOptions: StoredOptions, options: Onboar

storage.del('cv');

const cc = codeChallenge || (pkce && generateCodeChallenge());
const cc = codeChallenge || generateCodeChallenge();

const queryString = stringify({
client_id: clientId,
Expand Down
Loading