Skip to content

Commit 1d12977

Browse files
authored
Merge pull request #20210 from mozilla/fxa-12618
test(auth-server): migrate IAP and PayPal Mocha tests to Jest
2 parents 0403c92 + c778291 commit 1d12977

14 files changed

Lines changed: 4707 additions & 0 deletions
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
/** Migrated from test/local/payments/iap/apple-app-store/app-store-helper.js (Mocha → Jest). */
6+
7+
import sinon from 'sinon';
8+
import { Container } from 'typedi';
9+
10+
import { AuthLogger, AppConfig } from '../../../types';
11+
12+
const { mockLog } = require('../../../../test/mocks');
13+
14+
// Mock AppStoreServerAPI to avoid PKCS#8 key parsing
15+
const mockAppStoreServerAPI: any = {};
16+
jest.mock('app-store-server-api', () => {
17+
const actual = jest.requireActual('app-store-server-api');
18+
return {
19+
...actual,
20+
AppStoreServerAPI: function () {
21+
return mockAppStoreServerAPI;
22+
},
23+
};
24+
});
25+
26+
// Must require after jest.mock
27+
const { AppStoreHelper } = require('./app-store-helper');
28+
29+
const mockBundleIdWithUnderscores = 'org_mozilla_ios_FirefoxVPN';
30+
const mockBundleId = mockBundleIdWithUnderscores.replace(/_/g, '.');
31+
const mockConfig = {
32+
subscriptions: {
33+
appStore: {
34+
credentials: {
35+
[mockBundleIdWithUnderscores]: {
36+
issuerId: 'issuer_id',
37+
serverApiKey: 'key',
38+
serverApiKeyId: 'key_id',
39+
},
40+
},
41+
sandbox: true,
42+
},
43+
},
44+
};
45+
46+
describe('AppStoreHelper', () => {
47+
let appStoreHelper: any;
48+
let sandbox: sinon.SinonSandbox;
49+
let log: any;
50+
51+
beforeEach(() => {
52+
sandbox = sinon.createSandbox();
53+
log = mockLog();
54+
Container.set(AuthLogger, log);
55+
Container.set(AppConfig, mockConfig);
56+
appStoreHelper = Container.get(AppStoreHelper);
57+
});
58+
59+
afterEach(() => {
60+
Container.reset();
61+
sandbox.restore();
62+
});
63+
64+
it('can be instantiated', () => {
65+
const appStoreServerApiClients = {
66+
[mockBundleId]: mockAppStoreServerAPI,
67+
};
68+
const credentialsByBundleId = {
69+
[mockBundleId]:
70+
mockConfig.subscriptions.appStore.credentials[
71+
mockBundleIdWithUnderscores
72+
],
73+
};
74+
expect(appStoreHelper.log).toBe(log);
75+
expect(appStoreHelper.appStoreServerApiClients).toEqual(
76+
appStoreServerApiClients
77+
);
78+
expect(appStoreHelper.credentialsByBundleId).toEqual(credentialsByBundleId);
79+
expect(appStoreHelper.environment).toBe('Sandbox');
80+
});
81+
82+
describe('clientByBundleId', () => {
83+
let mockApiClient: any;
84+
85+
beforeEach(() => {
86+
mockApiClient = {};
87+
});
88+
89+
it('returns the existing API client for the bundleId', () => {
90+
appStoreHelper.appStoreServerApiClients[mockBundleId] = mockApiClient;
91+
const actual = appStoreHelper.clientByBundleId(mockBundleId);
92+
const expected = mockApiClient;
93+
expect(actual).toEqual(expected);
94+
});
95+
it("initializes an API client for a given bundleId if it doesn't exist", () => {
96+
appStoreHelper.appStoreServerApiClients = {};
97+
const actual = appStoreHelper.clientByBundleId(mockBundleId);
98+
const expected = mockAppStoreServerAPI;
99+
expect(actual).toEqual(expected);
100+
});
101+
it('throws an error if no credentials are found for the given bundleId', () => {
102+
appStoreHelper.appStoreServerApiClients = {};
103+
appStoreHelper.credentialsByBundleId = {};
104+
const expectedMessage = `No App Store credentials found for app with bundleId: ${mockBundleId}.`;
105+
expect(() => appStoreHelper.clientByBundleId(mockBundleId)).toThrow(
106+
expectedMessage
107+
);
108+
});
109+
});
110+
111+
describe('getSubscriptionStatuses', () => {
112+
it('calls the corresponding method on the API client', async () => {
113+
const mockOriginalTransactionId = '100000000';
114+
// Mock App Store Client API response
115+
const expected = { data: 'wow' };
116+
mockAppStoreServerAPI.getSubscriptionStatuses = sinon
117+
.stub()
118+
.resolves(expected);
119+
appStoreHelper.clientByBundleId = sandbox
120+
.stub()
121+
.returns(mockAppStoreServerAPI);
122+
const actual = await appStoreHelper.getSubscriptionStatuses(
123+
mockBundleId,
124+
mockOriginalTransactionId
125+
);
126+
expect(actual).toEqual(expected);
127+
128+
sinon.assert.calledOnceWithExactly(
129+
appStoreHelper.clientByBundleId,
130+
mockBundleId
131+
);
132+
sinon.assert.calledOnceWithExactly(
133+
mockAppStoreServerAPI.getSubscriptionStatuses,
134+
mockOriginalTransactionId
135+
);
136+
});
137+
});
138+
});
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/* This Source Code Form is subject to the terms of the Mozilla Public
2+
* License, v. 2.0. If a copy of the MPL was not distributed with this
3+
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4+
5+
/** Migrated from test/local/payments/iap/apple-app-store/apple-iap.js (Mocha → Jest). */
6+
7+
// Mock AppStoreHelper to avoid PKCS#8 key parsing in AppStoreServerAPI constructor
8+
jest.mock('./app-store-helper', () => ({
9+
AppStoreHelper: class MockAppStoreHelper {},
10+
}));
11+
12+
import sinon from 'sinon';
13+
import { Container } from 'typedi';
14+
15+
import { AuthFirestore, AuthLogger, AppConfig } from '../../../types';
16+
import { AppleIAP } from '.';
17+
18+
const { mockLog } = require('../../../../test/mocks');
19+
20+
const mockConfig = {
21+
authFirestore: {
22+
prefix: 'mock-fxa-',
23+
},
24+
subscriptions: {
25+
appStore: {
26+
credentials: {
27+
org_mozilla_ios_FirefoxVPN: {
28+
issuerId: 'issuer_id',
29+
serverApiKey: 'key',
30+
serverApiKeyId: 'key_id',
31+
},
32+
},
33+
},
34+
},
35+
};
36+
37+
describe('AppleIAP', () => {
38+
let collectionMock: sinon.SinonStub;
39+
let purchasesDbRefMock: any;
40+
let sandbox: sinon.SinonSandbox;
41+
let firestore: any;
42+
let log: any;
43+
44+
beforeEach(() => {
45+
sandbox = sinon.createSandbox();
46+
log = mockLog();
47+
collectionMock = sinon.stub();
48+
firestore = {
49+
collection: collectionMock,
50+
};
51+
purchasesDbRefMock = {};
52+
collectionMock.returns(purchasesDbRefMock);
53+
Container.set(AuthFirestore, firestore);
54+
Container.set(AuthLogger, log);
55+
Container.set(AppConfig, mockConfig);
56+
Container.remove(AppleIAP);
57+
});
58+
59+
afterEach(() => {
60+
Container.reset();
61+
sandbox.restore();
62+
});
63+
64+
it('can be instantiated', () => {
65+
const appleIAP = Container.get(AppleIAP);
66+
expect((appleIAP as any).log).toBe(log);
67+
expect((appleIAP as any).firestore).toBe(firestore);
68+
expect((appleIAP as any).prefix).toBe('mock-fxa-iap-');
69+
});
70+
});

0 commit comments

Comments
 (0)