@purchasely/cordova-plugin-purchasely 6.0.0 → 6.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Package.swift +77 -0
- package/package.json +11 -2
- package/plugin.xml +4 -4
- package/src/ios/CDVPurchasely.m +22 -4
- package/www/Purchasely.js +1 -1
- package/__tests__/Purchasely.test.js +0 -1826
- package/example/IOS_8_1_1_TEST_MATRIX.md +0 -25
- package/example/android.sh +0 -10
- package/example/config.xml +0 -27
- package/example/e2e/README.md +0 -44
- package/example/e2e/helpers/driver.js +0 -187
- package/example/e2e/package.json +0 -19
- package/example/e2e/specs/bridge.e2e.js +0 -154
- package/example/e2e/specs/dismiss.e2e.js +0 -57
- package/example/e2e/tools/ci_run_e2e.sh +0 -63
- package/example/e2e/tools/ci_run_e2e_ios.sh +0 -56
- package/example/e2e/wdio.android.conf.js +0 -24
- package/example/e2e/wdio.ios.conf.js +0 -44
- package/example/e2e/wdio.shared.conf.js +0 -28
- package/example/ios.sh +0 -17
- package/example/package-lock.json +0 -859
- package/example/package.json +0 -37
- package/example/www/css/index.css +0 -110
- package/example/www/img/logo.png +0 -0
- package/example/www/index.html +0 -78
- package/example/www/js/index.js +0 -453
- package/purchasely.iml +0 -11
|
@@ -1,1826 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit tests for Purchasely.js
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
// Mock cordova/exec
|
|
6
|
-
const mockExec = jest.fn();
|
|
7
|
-
jest.mock('cordova/exec', () => mockExec, { virtual: true });
|
|
8
|
-
|
|
9
|
-
// Mock cordova global
|
|
10
|
-
global.cordova = {
|
|
11
|
-
define: {
|
|
12
|
-
moduleMap: {
|
|
13
|
-
'cordova/plugin_list': {
|
|
14
|
-
exports: {
|
|
15
|
-
metadata: {
|
|
16
|
-
'cordova-plugin-purchasely': '5.6.2'
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
// Import the module after mocks are set up
|
|
25
|
-
const Purchasely = require('../www/Purchasely');
|
|
26
|
-
|
|
27
|
-
describe('Purchasely', () => {
|
|
28
|
-
beforeEach(() => {
|
|
29
|
-
mockExec.mockClear();
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
describe('Constants', () => {
|
|
33
|
-
describe('LogLevel', () => {
|
|
34
|
-
it('should have correct log level values', () => {
|
|
35
|
-
expect(Purchasely.LogLevel.DEBUG).toBe(0);
|
|
36
|
-
expect(Purchasely.LogLevel.INFO).toBe(1);
|
|
37
|
-
expect(Purchasely.LogLevel.WARN).toBe(2);
|
|
38
|
-
expect(Purchasely.LogLevel.ERROR).toBe(3);
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
describe('Attribute', () => {
|
|
43
|
-
it('should have correct attribute values', () => {
|
|
44
|
-
expect(Purchasely.Attribute.FIREBASE_APP_INSTANCE_ID).toBe(0);
|
|
45
|
-
expect(Purchasely.Attribute.AIRSHIP_CHANNEL_ID).toBe(1);
|
|
46
|
-
expect(Purchasely.Attribute.ADJUST_ID).toBe(4);
|
|
47
|
-
expect(Purchasely.Attribute.APPSFLYER_ID).toBe(5);
|
|
48
|
-
expect(Purchasely.Attribute.AMPLITUDE_USER_ID).toBe(16);
|
|
49
|
-
expect(Purchasely.Attribute.BATCH_CUSTOM_USER_ID).toBe(20);
|
|
50
|
-
// ENM-02 / REC-11
|
|
51
|
-
expect(Purchasely.Attribute.ONESIGNAL_USER_ID).toBe(21);
|
|
52
|
-
expect(Purchasely.Attribute.oneSignalPlayerId).toBeUndefined();
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
describe('DataProcessingLegalBasis', () => {
|
|
57
|
-
it('should have correct legal basis values', () => {
|
|
58
|
-
expect(Purchasely.DataProcessingLegalBasis.essential).toBe('ESSENTIAL');
|
|
59
|
-
expect(Purchasely.DataProcessingLegalBasis.optional).toBe('OPTIONAL');
|
|
60
|
-
});
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
describe('DataProcessingPurpose', () => {
|
|
64
|
-
it('should have correct purpose values', () => {
|
|
65
|
-
expect(Purchasely.DataProcessingPurpose.allNonEssentials).toBe('ALL_NON_ESSENTIALS');
|
|
66
|
-
expect(Purchasely.DataProcessingPurpose.analytics).toBe('ANALYTICS');
|
|
67
|
-
expect(Purchasely.DataProcessingPurpose.identifiedAnalytics).toBe('IDENTIFIED_ANALYTICS');
|
|
68
|
-
expect(Purchasely.DataProcessingPurpose.campaigns).toBe('CAMPAIGNS');
|
|
69
|
-
expect(Purchasely.DataProcessingPurpose.personalization).toBe('PERSONALIZATION');
|
|
70
|
-
expect(Purchasely.DataProcessingPurpose.thirdPartyIntegrations).toBe('THIRD_PARTY_INTEGRATIONS');
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
describe('PurchaseResult', () => {
|
|
75
|
-
it('should have correct purchase result values', () => {
|
|
76
|
-
expect(Purchasely.PurchaseResult.PURCHASED).toBe(0);
|
|
77
|
-
expect(Purchasely.PurchaseResult.CANCELLED).toBe(1);
|
|
78
|
-
expect(Purchasely.PurchaseResult.RESTORED).toBe(2);
|
|
79
|
-
});
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
describe('SubscriptionSource', () => {
|
|
83
|
-
it('should have correct subscription source values', () => {
|
|
84
|
-
expect(Purchasely.SubscriptionSource.appleAppStore).toBe(0);
|
|
85
|
-
expect(Purchasely.SubscriptionSource.googlePlayStore).toBe(1);
|
|
86
|
-
expect(Purchasely.SubscriptionSource.amazonAppstore).toBe(2);
|
|
87
|
-
expect(Purchasely.SubscriptionSource.huaweiAppGallery).toBe(3);
|
|
88
|
-
expect(Purchasely.SubscriptionSource.none).toBe(4);
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
describe('PlanType', () => {
|
|
93
|
-
it('should have correct plan type values', () => {
|
|
94
|
-
expect(Purchasely.PlanType.consumable).toBe(0);
|
|
95
|
-
expect(Purchasely.PlanType.nonConsumable).toBe(1);
|
|
96
|
-
expect(Purchasely.PlanType.autoRenewingSubscription).toBe(2);
|
|
97
|
-
expect(Purchasely.PlanType.nonRenewingSubscription).toBe(3);
|
|
98
|
-
expect(Purchasely.PlanType.unknown).toBe(4);
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
describe('BillingPlanType', () => {
|
|
103
|
-
it('should have correct billing plan type values (iOS 26.4+ commitment, Apple only)', () => {
|
|
104
|
-
expect(Purchasely.BillingPlanType.unspecified).toBe(0);
|
|
105
|
-
expect(Purchasely.BillingPlanType.upFront).toBe(1);
|
|
106
|
-
expect(Purchasely.BillingPlanType.monthly).toBe(2);
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
describe('RunningMode', () => {
|
|
111
|
-
it('should expose the Purchasely 6.0 running modes by name', () => {
|
|
112
|
-
expect(Purchasely.RunningMode.observer).toBe('observer');
|
|
113
|
-
expect(Purchasely.RunningMode.full).toBe('full');
|
|
114
|
-
});
|
|
115
|
-
});
|
|
116
|
-
|
|
117
|
-
describe('PresentationAction', () => {
|
|
118
|
-
it('should have correct presentation action values', () => {
|
|
119
|
-
expect(Purchasely.PresentationAction.close).toBe('close');
|
|
120
|
-
expect(Purchasely.PresentationAction.closeAll).toBe('close_all');
|
|
121
|
-
expect(Purchasely.PresentationAction.login).toBe('login');
|
|
122
|
-
expect(Purchasely.PresentationAction.navigate).toBe('navigate');
|
|
123
|
-
expect(Purchasely.PresentationAction.purchase).toBe('purchase');
|
|
124
|
-
expect(Purchasely.PresentationAction.restore).toBe('restore');
|
|
125
|
-
expect(Purchasely.PresentationAction.openPresentation).toBe('open_presentation');
|
|
126
|
-
expect(Purchasely.PresentationAction.openPlacement).toBe('open_placement');
|
|
127
|
-
expect(Purchasely.PresentationAction.promoCode).toBe('promo_code');
|
|
128
|
-
expect(Purchasely.PresentationAction.webCheckout).toBe('web_checkout');
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
describe('InterceptResult', () => {
|
|
133
|
-
it('should have correct intercept result values', () => {
|
|
134
|
-
expect(Purchasely.InterceptResult.success).toBe('success');
|
|
135
|
-
expect(Purchasely.InterceptResult.failed).toBe('failed');
|
|
136
|
-
expect(Purchasely.InterceptResult.notHandled).toBe('notHandled');
|
|
137
|
-
});
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
describe('PresentationType', () => {
|
|
141
|
-
it('should have correct presentation type values', () => {
|
|
142
|
-
expect(Purchasely.PresentationType.normal).toBe(0);
|
|
143
|
-
expect(Purchasely.PresentationType.fallback).toBe(1);
|
|
144
|
-
expect(Purchasely.PresentationType.deactivated).toBe(2);
|
|
145
|
-
expect(Purchasely.PresentationType.client).toBe(3);
|
|
146
|
-
});
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
describe('CloseReason', () => {
|
|
150
|
-
it('should have correct close reason values', () => {
|
|
151
|
-
expect(Purchasely.CloseReason.button).toBe('button');
|
|
152
|
-
expect(Purchasely.CloseReason.backSystem).toBe('back_system');
|
|
153
|
-
expect(Purchasely.CloseReason.programmatic).toBe('programmatic');
|
|
154
|
-
});
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
describe('TransitionType', () => {
|
|
158
|
-
it('should have correct transition type values', () => {
|
|
159
|
-
expect(Purchasely.TransitionType.fullScreen).toBe('fullScreen');
|
|
160
|
-
expect(Purchasely.TransitionType.modal).toBe('modal');
|
|
161
|
-
expect(Purchasely.TransitionType.drawer).toBe('drawer');
|
|
162
|
-
expect(Purchasely.TransitionType.popin).toBe('popin');
|
|
163
|
-
expect(Purchasely.TransitionType.push).toBe('push');
|
|
164
|
-
expect(Purchasely.TransitionType.inlinePaywall).toBe('inlinePaywall');
|
|
165
|
-
});
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
describe('DimensionType', () => {
|
|
169
|
-
it('should have correct dimension type values', () => {
|
|
170
|
-
expect(Purchasely.DimensionType.pixel).toBe('pixel');
|
|
171
|
-
expect(Purchasely.DimensionType.percentage).toBe('percentage');
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
describe('Store', () => {
|
|
176
|
-
it('should have correct store values', () => {
|
|
177
|
-
expect(Purchasely.Store.google).toBe('Google');
|
|
178
|
-
expect(Purchasely.Store.huawei).toBe('Huawei');
|
|
179
|
-
expect(Purchasely.Store.amazon).toBe('Amazon');
|
|
180
|
-
});
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
describe('StorekitVersion', () => {
|
|
184
|
-
it('should have correct storekit version values', () => {
|
|
185
|
-
expect(Purchasely.StorekitVersion.storeKit1).toBe('storeKit1');
|
|
186
|
-
expect(Purchasely.StorekitVersion.storeKit2).toBe('storeKit2');
|
|
187
|
-
});
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
describe('ThemeMode', () => {
|
|
191
|
-
it('should have correct theme mode values', () => {
|
|
192
|
-
expect(Purchasely.ThemeMode.light).toBe(0);
|
|
193
|
-
expect(Purchasely.ThemeMode.dark).toBe(1);
|
|
194
|
-
expect(Purchasely.ThemeMode.system).toBe(2);
|
|
195
|
-
});
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
describe('UserAttributeAction', () => {
|
|
199
|
-
it('should have correct user attribute action values', () => {
|
|
200
|
-
expect(Purchasely.UserAttributeAction.ADD).toBe('add');
|
|
201
|
-
expect(Purchasely.UserAttributeAction.REMOVE).toBe('remove');
|
|
202
|
-
});
|
|
203
|
-
});
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
describe('start', () => {
|
|
207
|
-
it('should call exec with a single options object (with sdkVersion appended)', () => {
|
|
208
|
-
const success = jest.fn();
|
|
209
|
-
const error = jest.fn();
|
|
210
|
-
|
|
211
|
-
Purchasely.start(
|
|
212
|
-
{
|
|
213
|
-
apiKey: 'API_KEY',
|
|
214
|
-
stores: [Purchasely.Store.google],
|
|
215
|
-
storeKit1: false,
|
|
216
|
-
appUserId: 'user123',
|
|
217
|
-
logLevel: Purchasely.LogLevel.INFO,
|
|
218
|
-
runningMode: Purchasely.RunningMode.full
|
|
219
|
-
},
|
|
220
|
-
success,
|
|
221
|
-
error
|
|
222
|
-
);
|
|
223
|
-
|
|
224
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
225
|
-
success,
|
|
226
|
-
error,
|
|
227
|
-
'Purchasely',
|
|
228
|
-
'start',
|
|
229
|
-
[
|
|
230
|
-
{
|
|
231
|
-
apiKey: 'API_KEY',
|
|
232
|
-
stores: ['Google'],
|
|
233
|
-
storeKit1: false,
|
|
234
|
-
appUserId: 'user123',
|
|
235
|
-
logLevel: 1,
|
|
236
|
-
runningMode: 'full',
|
|
237
|
-
sdkVersion: '5.6.2'
|
|
238
|
-
}
|
|
239
|
-
]
|
|
240
|
-
);
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
it('should fall back to the literal default sdkVersion when plugin_list metadata is missing', () => {
|
|
244
|
-
const metadata = global.cordova.define.moduleMap['cordova/plugin_list'].exports.metadata;
|
|
245
|
-
const original = metadata['cordova-plugin-purchasely'];
|
|
246
|
-
delete metadata['cordova-plugin-purchasely'];
|
|
247
|
-
|
|
248
|
-
try {
|
|
249
|
-
Purchasely.start({ apiKey: 'API_KEY' }, jest.fn(), jest.fn());
|
|
250
|
-
|
|
251
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
252
|
-
expect.any(Function),
|
|
253
|
-
expect.any(Function),
|
|
254
|
-
'Purchasely',
|
|
255
|
-
'start',
|
|
256
|
-
[{ apiKey: 'API_KEY', sdkVersion: '6.0.0' }]
|
|
257
|
-
);
|
|
258
|
-
} finally {
|
|
259
|
-
metadata['cordova-plugin-purchasely'] = original;
|
|
260
|
-
}
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
it('should treat a v5-style positional call as broken (no longer supported)', () => {
|
|
264
|
-
// Purchasely 6.0: `start` takes a single options object. A v5-style positional
|
|
265
|
-
// call (apiKey, stores, storeKit1, ...) is NOT supported: `options` becomes the
|
|
266
|
-
// raw apiKey string (sdkVersion silently fails to attach to a string primitive),
|
|
267
|
-
// and `success`/`error` are mis-bound to the 2nd/3rd positional args instead of
|
|
268
|
-
// the real callbacks. This documents the breaking change from MIGRATION-v6.md.
|
|
269
|
-
const legacyStores = ['Google'];
|
|
270
|
-
const legacyStoreKit1 = false;
|
|
271
|
-
|
|
272
|
-
Purchasely.start('API_KEY', legacyStores, legacyStoreKit1, null, 0, 'full', jest.fn(), jest.fn());
|
|
273
|
-
|
|
274
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
275
|
-
legacyStores,
|
|
276
|
-
legacyStoreKit1,
|
|
277
|
-
'Purchasely',
|
|
278
|
-
'start',
|
|
279
|
-
['API_KEY']
|
|
280
|
-
);
|
|
281
|
-
});
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
describe('builder(apiKey) (fluent alias of start)', () => {
|
|
285
|
-
it('accumulates chained options and delegates to exports.start with (success, error) callbacks', () => {
|
|
286
|
-
const success = jest.fn();
|
|
287
|
-
const error = jest.fn();
|
|
288
|
-
|
|
289
|
-
Purchasely.builder('API_KEY')
|
|
290
|
-
.appUserId('user123')
|
|
291
|
-
.runningMode(Purchasely.RunningMode.full)
|
|
292
|
-
.logLevel(Purchasely.LogLevel.INFO)
|
|
293
|
-
.allowDeeplink(true)
|
|
294
|
-
.allowCampaigns(false)
|
|
295
|
-
.stores([Purchasely.Store.google])
|
|
296
|
-
.storekitVersion(Purchasely.StorekitVersion.storeKit2)
|
|
297
|
-
.storeKit1(false)
|
|
298
|
-
.deeplink('myapp://deeplink')
|
|
299
|
-
.start(success, error);
|
|
300
|
-
|
|
301
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
302
|
-
success,
|
|
303
|
-
error,
|
|
304
|
-
'Purchasely',
|
|
305
|
-
'start',
|
|
306
|
-
[
|
|
307
|
-
{
|
|
308
|
-
apiKey: 'API_KEY',
|
|
309
|
-
appUserId: 'user123',
|
|
310
|
-
runningMode: 'full',
|
|
311
|
-
logLevel: 1,
|
|
312
|
-
allowDeeplink: true,
|
|
313
|
-
allowCampaigns: false,
|
|
314
|
-
stores: ['Google'],
|
|
315
|
-
storekitVersion: 'storeKit2',
|
|
316
|
-
storeKit1: false,
|
|
317
|
-
deeplink: 'myapp://deeplink',
|
|
318
|
-
sdkVersion: '5.6.2'
|
|
319
|
-
}
|
|
320
|
-
]
|
|
321
|
-
);
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
it('start() with no callbacks returns a Promise resolving the isConfigured value', async () => {
|
|
325
|
-
const startPromise = Purchasely.builder('API_KEY').start();
|
|
326
|
-
|
|
327
|
-
const call = mockExec.mock.calls[mockExec.mock.calls.length - 1];
|
|
328
|
-
expect(call[2]).toBe('Purchasely');
|
|
329
|
-
expect(call[3]).toBe('start');
|
|
330
|
-
expect(call[4]).toEqual([{ apiKey: 'API_KEY', sdkVersion: '5.6.2' }]);
|
|
331
|
-
call[0](true); // native success callback -> isConfigured
|
|
332
|
-
|
|
333
|
-
await expect(startPromise).resolves.toBe(true);
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
it('rejects the Promise on native start failure', async () => {
|
|
337
|
-
const startPromise = Purchasely.builder('API_KEY').start();
|
|
338
|
-
|
|
339
|
-
const call = mockExec.mock.calls[mockExec.mock.calls.length - 1];
|
|
340
|
-
call[1]('Invalid API Key');
|
|
341
|
-
|
|
342
|
-
await expect(startPromise).rejects.toEqual({ message: 'Invalid API Key' });
|
|
343
|
-
});
|
|
344
|
-
});
|
|
345
|
-
|
|
346
|
-
describe('addEventListener (canonical, REC-18/PAR-18)', () => {
|
|
347
|
-
it('should call exec with correct parameters', () => {
|
|
348
|
-
const success = jest.fn();
|
|
349
|
-
const error = jest.fn();
|
|
350
|
-
|
|
351
|
-
Purchasely.addEventListener(success, error);
|
|
352
|
-
|
|
353
|
-
expect(mockExec).toHaveBeenCalledWith(success, error, 'Purchasely', 'addEventsListener', []);
|
|
354
|
-
});
|
|
355
|
-
});
|
|
356
|
-
|
|
357
|
-
describe('addEventsListener (deprecated alias)', () => {
|
|
358
|
-
it('should call exec with correct parameters', () => {
|
|
359
|
-
const success = jest.fn();
|
|
360
|
-
const error = jest.fn();
|
|
361
|
-
|
|
362
|
-
Purchasely.addEventsListener(success, error);
|
|
363
|
-
|
|
364
|
-
expect(mockExec).toHaveBeenCalledWith(success, error, 'Purchasely', 'addEventsListener', []);
|
|
365
|
-
});
|
|
366
|
-
});
|
|
367
|
-
|
|
368
|
-
describe('addUserAttributeListener', () => {
|
|
369
|
-
it('should call exec with correct parameters', () => {
|
|
370
|
-
const success = jest.fn();
|
|
371
|
-
const error = jest.fn();
|
|
372
|
-
|
|
373
|
-
Purchasely.addUserAttributeListener(success, error);
|
|
374
|
-
|
|
375
|
-
expect(mockExec).toHaveBeenCalledWith(success, error, 'Purchasely', 'addUserAttributeListener', []);
|
|
376
|
-
});
|
|
377
|
-
});
|
|
378
|
-
|
|
379
|
-
describe('removeEventListener (canonical, REC-18/PAR-18)', () => {
|
|
380
|
-
it('should call exec with correct parameters', () => {
|
|
381
|
-
Purchasely.removeEventListener();
|
|
382
|
-
|
|
383
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
384
|
-
expect.any(Function),
|
|
385
|
-
expect.any(Function),
|
|
386
|
-
'Purchasely',
|
|
387
|
-
'removeEventsListener',
|
|
388
|
-
[]
|
|
389
|
-
);
|
|
390
|
-
});
|
|
391
|
-
});
|
|
392
|
-
|
|
393
|
-
describe('removeEventsListener (deprecated alias)', () => {
|
|
394
|
-
it('should call exec with correct parameters', () => {
|
|
395
|
-
Purchasely.removeEventsListener();
|
|
396
|
-
|
|
397
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
398
|
-
expect.any(Function),
|
|
399
|
-
expect.any(Function),
|
|
400
|
-
'Purchasely',
|
|
401
|
-
'removeEventsListener',
|
|
402
|
-
[]
|
|
403
|
-
);
|
|
404
|
-
});
|
|
405
|
-
});
|
|
406
|
-
|
|
407
|
-
describe('removeUserAttributeListener', () => {
|
|
408
|
-
it('should call exec with correct parameters', () => {
|
|
409
|
-
Purchasely.removeUserAttributeListener();
|
|
410
|
-
|
|
411
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
412
|
-
expect.any(Function),
|
|
413
|
-
expect.any(Function),
|
|
414
|
-
'Purchasely',
|
|
415
|
-
'removeUserAttributeListener',
|
|
416
|
-
[]
|
|
417
|
-
);
|
|
418
|
-
});
|
|
419
|
-
});
|
|
420
|
-
|
|
421
|
-
describe('getAnonymousUserId', () => {
|
|
422
|
-
it('should call exec with correct parameters', () => {
|
|
423
|
-
const success = jest.fn();
|
|
424
|
-
const error = jest.fn();
|
|
425
|
-
|
|
426
|
-
Purchasely.getAnonymousUserId(success, error);
|
|
427
|
-
|
|
428
|
-
expect(mockExec).toHaveBeenCalledWith(success, error, 'Purchasely', 'getAnonymousUserId', []);
|
|
429
|
-
});
|
|
430
|
-
});
|
|
431
|
-
|
|
432
|
-
describe('isAnonymous (REC-12 / PAR-04)', () => {
|
|
433
|
-
it('should call exec with correct parameters', () => {
|
|
434
|
-
const success = jest.fn();
|
|
435
|
-
const error = jest.fn();
|
|
436
|
-
|
|
437
|
-
Purchasely.isAnonymous(success, error);
|
|
438
|
-
|
|
439
|
-
expect(mockExec).toHaveBeenCalledWith(success, error, 'Purchasely', 'isAnonymous', []);
|
|
440
|
-
});
|
|
441
|
-
});
|
|
442
|
-
|
|
443
|
-
describe('userLogin', () => {
|
|
444
|
-
it('should call exec with correct parameters', () => {
|
|
445
|
-
const success = jest.fn();
|
|
446
|
-
|
|
447
|
-
Purchasely.userLogin('user123', success);
|
|
448
|
-
|
|
449
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
450
|
-
success,
|
|
451
|
-
expect.any(Function),
|
|
452
|
-
'Purchasely',
|
|
453
|
-
'userLogin',
|
|
454
|
-
['user123']
|
|
455
|
-
);
|
|
456
|
-
});
|
|
457
|
-
});
|
|
458
|
-
|
|
459
|
-
describe('userLogout', () => {
|
|
460
|
-
it('defaults clearUserAttributes to true when omitted (PAR-30)', () => {
|
|
461
|
-
Purchasely.userLogout();
|
|
462
|
-
|
|
463
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
464
|
-
expect.any(Function),
|
|
465
|
-
expect.any(Function),
|
|
466
|
-
'Purchasely',
|
|
467
|
-
'userLogout',
|
|
468
|
-
[true]
|
|
469
|
-
);
|
|
470
|
-
});
|
|
471
|
-
|
|
472
|
-
it('forwards an explicit clearUserAttributes value', () => {
|
|
473
|
-
Purchasely.userLogout(false);
|
|
474
|
-
|
|
475
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
476
|
-
expect.any(Function),
|
|
477
|
-
expect.any(Function),
|
|
478
|
-
'Purchasely',
|
|
479
|
-
'userLogout',
|
|
480
|
-
[false]
|
|
481
|
-
);
|
|
482
|
-
});
|
|
483
|
-
});
|
|
484
|
-
|
|
485
|
-
describe('setLogLevel', () => {
|
|
486
|
-
it('should call exec with correct parameters', () => {
|
|
487
|
-
Purchasely.setLogLevel(Purchasely.LogLevel.DEBUG);
|
|
488
|
-
|
|
489
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
490
|
-
expect.any(Function),
|
|
491
|
-
expect.any(Function),
|
|
492
|
-
'Purchasely',
|
|
493
|
-
'setLogLevel',
|
|
494
|
-
[0]
|
|
495
|
-
);
|
|
496
|
-
});
|
|
497
|
-
});
|
|
498
|
-
|
|
499
|
-
describe('setAttribute', () => {
|
|
500
|
-
it('should call exec with correct parameters', () => {
|
|
501
|
-
Purchasely.setAttribute(Purchasely.Attribute.FIREBASE_APP_INSTANCE_ID, 'firebase123');
|
|
502
|
-
|
|
503
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
504
|
-
expect.any(Function),
|
|
505
|
-
expect.any(Function),
|
|
506
|
-
'Purchasely',
|
|
507
|
-
'setAttribute',
|
|
508
|
-
[0, 'firebase123']
|
|
509
|
-
);
|
|
510
|
-
});
|
|
511
|
-
});
|
|
512
|
-
|
|
513
|
-
describe('allowDeeplink', () => {
|
|
514
|
-
it('should call exec with correct parameters', () => {
|
|
515
|
-
Purchasely.allowDeeplink(true);
|
|
516
|
-
|
|
517
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
518
|
-
expect.any(Function),
|
|
519
|
-
expect.any(Function),
|
|
520
|
-
'Purchasely',
|
|
521
|
-
'allowDeeplink',
|
|
522
|
-
[true]
|
|
523
|
-
);
|
|
524
|
-
});
|
|
525
|
-
});
|
|
526
|
-
|
|
527
|
-
describe('allowCampaigns', () => {
|
|
528
|
-
it('should call exec with correct parameters', () => {
|
|
529
|
-
Purchasely.allowCampaigns(false);
|
|
530
|
-
|
|
531
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
532
|
-
expect.any(Function),
|
|
533
|
-
expect.any(Function),
|
|
534
|
-
'Purchasely',
|
|
535
|
-
'allowCampaigns',
|
|
536
|
-
[false]
|
|
537
|
-
);
|
|
538
|
-
});
|
|
539
|
-
});
|
|
540
|
-
|
|
541
|
-
describe('setDefaultPresentationDismissHandler', () => {
|
|
542
|
-
it('should call exec with correct parameters', () => {
|
|
543
|
-
const success = jest.fn();
|
|
544
|
-
const error = jest.fn();
|
|
545
|
-
|
|
546
|
-
Purchasely.setDefaultPresentationDismissHandler(success, error);
|
|
547
|
-
|
|
548
|
-
expect(mockExec).toHaveBeenCalledWith(success, error, 'Purchasely', 'setDefaultPresentationDismissHandler', []);
|
|
549
|
-
});
|
|
550
|
-
});
|
|
551
|
-
|
|
552
|
-
describe('synchronize', () => {
|
|
553
|
-
it('should call exec with the provided callbacks', () => {
|
|
554
|
-
const success = jest.fn();
|
|
555
|
-
const error = jest.fn();
|
|
556
|
-
|
|
557
|
-
Purchasely.synchronize(success, error);
|
|
558
|
-
|
|
559
|
-
expect(mockExec).toHaveBeenCalledWith(success, error, 'Purchasely', 'synchronize', []);
|
|
560
|
-
});
|
|
561
|
-
|
|
562
|
-
it('should default callbacks when none provided', () => {
|
|
563
|
-
Purchasely.synchronize();
|
|
564
|
-
|
|
565
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
566
|
-
expect.any(Function),
|
|
567
|
-
expect.any(Function),
|
|
568
|
-
'Purchasely',
|
|
569
|
-
'synchronize',
|
|
570
|
-
[]
|
|
571
|
-
);
|
|
572
|
-
});
|
|
573
|
-
});
|
|
574
|
-
|
|
575
|
-
// Purchasely 6.0: the v5 presentation surface (fetchPresentation*, presentPresentation*,
|
|
576
|
-
// backPresentation) is REMOVED, replaced by the promise-based v6 builder
|
|
577
|
-
// (Purchasely.presentation), which re-wraps the very same native exec actions.
|
|
578
|
-
describe('presentation builder (v6)', () => {
|
|
579
|
-
// Grabs the exec() call for a given native action, most recent first.
|
|
580
|
-
const execCallFor = (action) => {
|
|
581
|
-
const calls = mockExec.mock.calls.filter((c) => c[3] === action);
|
|
582
|
-
return calls[calls.length - 1];
|
|
583
|
-
};
|
|
584
|
-
|
|
585
|
-
// normalizePresentation always returns this exact whitelist of documented fields
|
|
586
|
-
// (defaulting the ones the raw payload didn't carry to null); tests merge in the
|
|
587
|
-
// fields they care about rather than repeating the full shape each time.
|
|
588
|
-
const fullPresentation = (overrides) => ({
|
|
589
|
-
screenId: null,
|
|
590
|
-
placementId: null,
|
|
591
|
-
contentId: null,
|
|
592
|
-
audienceId: null,
|
|
593
|
-
abTestId: null,
|
|
594
|
-
abTestVariantId: null,
|
|
595
|
-
campaignId: null,
|
|
596
|
-
flowId: null,
|
|
597
|
-
language: null,
|
|
598
|
-
type: null,
|
|
599
|
-
plans: null,
|
|
600
|
-
metadata: null,
|
|
601
|
-
height: null,
|
|
602
|
-
...overrides,
|
|
603
|
-
});
|
|
604
|
-
|
|
605
|
-
describe('sources', () => {
|
|
606
|
-
it('.placement(id).build().display() calls presentPresentationForPlacement', async () => {
|
|
607
|
-
const outcomePromise = Purchasely.presentation.placement('placement1').build().display();
|
|
608
|
-
|
|
609
|
-
const call = execCallFor('presentPresentationForPlacement');
|
|
610
|
-
expect(call[4]).toEqual(['placement1', null, undefined]);
|
|
611
|
-
call[0]({ purchaseResult: null, plan: null, closeReason: 'button', error: null, presentation: null });
|
|
612
|
-
|
|
613
|
-
const outcome = await outcomePromise;
|
|
614
|
-
expect(outcome.closeReason).toBe('button');
|
|
615
|
-
});
|
|
616
|
-
|
|
617
|
-
it('.screen(id).build().display() calls presentPresentationWithIdentifier', async () => {
|
|
618
|
-
const outcomePromise = Purchasely.presentation.screen('screen1').build().display();
|
|
619
|
-
|
|
620
|
-
const call = execCallFor('presentPresentationWithIdentifier');
|
|
621
|
-
expect(call[4]).toEqual(['screen1', null, undefined]);
|
|
622
|
-
call[0]({ purchaseResult: null, plan: null, closeReason: 'programmatic', error: null, presentation: null });
|
|
623
|
-
|
|
624
|
-
await outcomePromise;
|
|
625
|
-
});
|
|
626
|
-
|
|
627
|
-
it('.defaultSource().build().display() calls presentPresentationForDefault', async () => {
|
|
628
|
-
const outcomePromise = Purchasely.presentation.defaultSource().build().display();
|
|
629
|
-
|
|
630
|
-
const call = execCallFor('presentPresentationForDefault');
|
|
631
|
-
expect(call[4]).toEqual([null, undefined]);
|
|
632
|
-
call[0]({ purchaseResult: null, plan: null, closeReason: 'button', error: null, presentation: null });
|
|
633
|
-
|
|
634
|
-
await outcomePromise;
|
|
635
|
-
});
|
|
636
|
-
|
|
637
|
-
it('.default() is an alias of .defaultSource()', async () => {
|
|
638
|
-
const outcomePromise = Purchasely.presentation.default().build().display();
|
|
639
|
-
|
|
640
|
-
const call = execCallFor('presentPresentationForDefault');
|
|
641
|
-
expect(call[4]).toEqual([null, undefined]);
|
|
642
|
-
call[0]({ purchaseResult: null, plan: null, closeReason: 'button', error: null, presentation: null });
|
|
643
|
-
|
|
644
|
-
await outcomePromise;
|
|
645
|
-
});
|
|
646
|
-
});
|
|
647
|
-
|
|
648
|
-
describe('contentId', () => {
|
|
649
|
-
it('is forwarded to the matching present* action', async () => {
|
|
650
|
-
const outcomePromise = Purchasely.presentation.placement('placement1').contentId('content1').build().display();
|
|
651
|
-
|
|
652
|
-
const call = execCallFor('presentPresentationForPlacement');
|
|
653
|
-
expect(call[4]).toEqual(['placement1', 'content1', undefined]);
|
|
654
|
-
call[0]({ closeReason: 'button' });
|
|
655
|
-
|
|
656
|
-
await outcomePromise;
|
|
657
|
-
});
|
|
658
|
-
});
|
|
659
|
-
|
|
660
|
-
describe('display(transition)', () => {
|
|
661
|
-
it('normalizes a display-mode string to a transition object', async () => {
|
|
662
|
-
const outcomePromise = Purchasely.presentation.screen('screen1').build().display(Purchasely.TransitionType.drawer);
|
|
663
|
-
|
|
664
|
-
const call = execCallFor('presentPresentationWithIdentifier');
|
|
665
|
-
expect(call[4][2]).toEqual({ type: 'drawer' });
|
|
666
|
-
call[0]({ closeReason: 'button' });
|
|
667
|
-
|
|
668
|
-
await outcomePromise;
|
|
669
|
-
});
|
|
670
|
-
|
|
671
|
-
it('passes a full transition object through unchanged', async () => {
|
|
672
|
-
const transition = { type: 'drawer', dismissible: false, height: { type: 'percentage', value: 0.8 } };
|
|
673
|
-
const outcomePromise = Purchasely.presentation.placement('placement1').build().display(transition);
|
|
674
|
-
|
|
675
|
-
const call = execCallFor('presentPresentationForPlacement');
|
|
676
|
-
expect(call[4][2]).toEqual(transition);
|
|
677
|
-
call[0]({ closeReason: 'button' });
|
|
678
|
-
|
|
679
|
-
await outcomePromise;
|
|
680
|
-
});
|
|
681
|
-
});
|
|
682
|
-
|
|
683
|
-
describe('backgroundColor', () => {
|
|
684
|
-
it('merges into the transition object on the direct present* path (no forced type)', async () => {
|
|
685
|
-
const outcomePromise = Purchasely.presentation
|
|
686
|
-
.placement('placement1')
|
|
687
|
-
.backgroundColor('#101010')
|
|
688
|
-
.build()
|
|
689
|
-
.display();
|
|
690
|
-
|
|
691
|
-
const call = execCallFor('presentPresentationForPlacement');
|
|
692
|
-
// No display-mode given: only backgroundColor, no `type`, so the backend
|
|
693
|
-
// transition default is still honored (CDV-W-12).
|
|
694
|
-
expect(call[4][2]).toEqual({ backgroundColor: '#101010' });
|
|
695
|
-
call[0]({ closeReason: 'button' });
|
|
696
|
-
await outcomePromise;
|
|
697
|
-
});
|
|
698
|
-
|
|
699
|
-
it('is forwarded as presentPresentation\'s native backgroundColor arg on the re-display path', async () => {
|
|
700
|
-
const request = Purchasely.presentation.screen('screen1').backgroundColor('#202020').build();
|
|
701
|
-
|
|
702
|
-
const preloadPromise = request.preload();
|
|
703
|
-
const rawFetched = { screenId: 'screen1', fetchId: 'ply_fetch_789' };
|
|
704
|
-
execCallFor('fetchPresentation')[0](rawFetched);
|
|
705
|
-
await preloadPromise;
|
|
706
|
-
|
|
707
|
-
const outcomePromise = request.display();
|
|
708
|
-
const displayCall = execCallFor('presentPresentation');
|
|
709
|
-
expect(displayCall[4][0]).toBe(rawFetched);
|
|
710
|
-
expect(displayCall[4][2]).toBe('#202020');
|
|
711
|
-
displayCall[0]({ closeReason: 'programmatic' });
|
|
712
|
-
await outcomePromise;
|
|
713
|
-
});
|
|
714
|
-
|
|
715
|
-
it('does not expose progressColor / displayCloseButton / displayBackButton (no Cordova native support)', () => {
|
|
716
|
-
const builder = Purchasely.presentation.placement('placement1');
|
|
717
|
-
expect(builder.progressColor).toBeUndefined();
|
|
718
|
-
expect(builder.displayCloseButton).toBeUndefined();
|
|
719
|
-
expect(builder.displayBackButton).toBeUndefined();
|
|
720
|
-
});
|
|
721
|
-
});
|
|
722
|
-
|
|
723
|
-
describe('lifecycle callbacks', () => {
|
|
724
|
-
it('routes presented/closeRequested envelopes to the builder callbacks, and the final outcome to onDismissed + the resolved promise', async () => {
|
|
725
|
-
const onPresented = jest.fn();
|
|
726
|
-
const onCloseRequested = jest.fn();
|
|
727
|
-
const onDismissed = jest.fn();
|
|
728
|
-
|
|
729
|
-
const outcomePromise = Purchasely.presentation
|
|
730
|
-
.placement('placement1')
|
|
731
|
-
.onPresented(onPresented)
|
|
732
|
-
.onCloseRequested(onCloseRequested)
|
|
733
|
-
.onDismissed(onDismissed)
|
|
734
|
-
.build()
|
|
735
|
-
.display();
|
|
736
|
-
|
|
737
|
-
const call = execCallFor('presentPresentationForPlacement');
|
|
738
|
-
const dispatch = call[0];
|
|
739
|
-
dispatch({ event: 'presented', presentation: { screenId: 's' } });
|
|
740
|
-
dispatch({ event: 'closeRequested' });
|
|
741
|
-
dispatch({ purchaseResult: 'cancelled', plan: null, closeReason: 'button', error: null, presentation: { screenId: 's' } });
|
|
742
|
-
|
|
743
|
-
const outcome = await outcomePromise;
|
|
744
|
-
|
|
745
|
-
// The 'presented' envelope's presentation is screenId-normalized like everywhere else.
|
|
746
|
-
expect(onPresented).toHaveBeenCalledWith(fullPresentation({ screenId: 's' }), null);
|
|
747
|
-
expect(onCloseRequested).toHaveBeenCalledTimes(1);
|
|
748
|
-
expect(onDismissed).toHaveBeenCalledWith(outcome);
|
|
749
|
-
expect(outcome).toEqual({
|
|
750
|
-
presentation: fullPresentation({ screenId: 's' }),
|
|
751
|
-
purchaseResult: 'cancelled',
|
|
752
|
-
plan: null,
|
|
753
|
-
closeReason: 'button',
|
|
754
|
-
error: null,
|
|
755
|
-
});
|
|
756
|
-
});
|
|
757
|
-
});
|
|
758
|
-
|
|
759
|
-
describe('outcome normalization (5 fields)', () => {
|
|
760
|
-
it('exposes exactly presentation/purchaseResult/plan/closeReason/error, with screenId tolerance', async () => {
|
|
761
|
-
const outcomePromise = Purchasely.presentation.placement('placement1').build().display();
|
|
762
|
-
|
|
763
|
-
const call = execCallFor('presentPresentationForPlacement');
|
|
764
|
-
call[0]({
|
|
765
|
-
result: 1, // legacy field: not part of the v6 builder's outcome contract
|
|
766
|
-
purchaseResult: 'purchased',
|
|
767
|
-
plan: { name: 'Plus' },
|
|
768
|
-
closeReason: null,
|
|
769
|
-
error: null,
|
|
770
|
-
presentation: { id: 'screen-id-only' }, // no screenId key: exercises the fallback
|
|
771
|
-
});
|
|
772
|
-
|
|
773
|
-
const outcome = await outcomePromise;
|
|
774
|
-
expect(outcome).toEqual({
|
|
775
|
-
presentation: fullPresentation({ screenId: 'screen-id-only' }),
|
|
776
|
-
purchaseResult: 'purchased',
|
|
777
|
-
plan: { name: 'Plus' },
|
|
778
|
-
closeReason: null,
|
|
779
|
-
error: null,
|
|
780
|
-
});
|
|
781
|
-
expect(outcome.result).toBeUndefined();
|
|
782
|
-
});
|
|
783
|
-
|
|
784
|
-
it('synthesizes an outcome carrying `error` when the native call fails, without rejecting', async () => {
|
|
785
|
-
const outcomePromise = Purchasely.presentation.placement('placement1').build().display();
|
|
786
|
-
|
|
787
|
-
const call = execCallFor('presentPresentationForPlacement');
|
|
788
|
-
call[1]('Presentation not loaded'); // native error callback
|
|
789
|
-
|
|
790
|
-
const outcome = await outcomePromise;
|
|
791
|
-
expect(outcome.error).toBe('Presentation not loaded');
|
|
792
|
-
expect(outcome.presentation).toBeNull();
|
|
793
|
-
expect(outcome.closeReason).toBeNull();
|
|
794
|
-
});
|
|
795
|
-
});
|
|
796
|
-
|
|
797
|
-
describe('preload() -> display() re-display', () => {
|
|
798
|
-
it('preload() resolves a screenId-normalized presentation, and the follow-up display() re-displays it via presentPresentation carrying the native handle', async () => {
|
|
799
|
-
const request = Purchasely.presentation.placement('placement1').build();
|
|
800
|
-
|
|
801
|
-
const preloadPromise = request.preload();
|
|
802
|
-
const fetchCall = execCallFor('fetchPresentation');
|
|
803
|
-
expect(fetchCall[4]).toEqual(['placement1', null, null]);
|
|
804
|
-
|
|
805
|
-
const rawFetched = { screenId: 'onboarding-screen', placementId: 'placement1', fetchId: 'ply_fetch_123' };
|
|
806
|
-
fetchCall[0](rawFetched);
|
|
807
|
-
|
|
808
|
-
const presentation = await preloadPromise;
|
|
809
|
-
// The screenId-normalized data is present (methods are added on top, below).
|
|
810
|
-
expect(presentation).toMatchObject(fullPresentation({ screenId: 'onboarding-screen', placementId: 'placement1' }));
|
|
811
|
-
// The native re-display handle is never exposed on the returned object.
|
|
812
|
-
expect(presentation.fetchId).toBeUndefined();
|
|
813
|
-
expect(presentation.id).toBeUndefined();
|
|
814
|
-
|
|
815
|
-
const outcomePromise = request.display();
|
|
816
|
-
const displayCall = execCallFor('presentPresentation');
|
|
817
|
-
// The exact raw fetch payload (with its private handle) is forwarded as-is.
|
|
818
|
-
expect(displayCall[4][0]).toBe(rawFetched);
|
|
819
|
-
displayCall[0]({ closeReason: 'programmatic' });
|
|
820
|
-
|
|
821
|
-
const outcome = await outcomePromise;
|
|
822
|
-
expect(outcome.closeReason).toBe('programmatic');
|
|
823
|
-
});
|
|
824
|
-
|
|
825
|
-
it('the loaded presentation exposes display()/close()/back() delegating to its request', async () => {
|
|
826
|
-
const request = Purchasely.presentation.screen('screen1').build();
|
|
827
|
-
|
|
828
|
-
const preloadPromise = request.preload();
|
|
829
|
-
const rawFetched = { screenId: 'screen1', fetchId: 'ply_fetch_456' };
|
|
830
|
-
execCallFor('fetchPresentation')[0](rawFetched);
|
|
831
|
-
|
|
832
|
-
const loaded = await preloadPromise;
|
|
833
|
-
expect(typeof loaded.display).toBe('function');
|
|
834
|
-
expect(typeof loaded.close).toBe('function');
|
|
835
|
-
expect(typeof loaded.back).toBe('function');
|
|
836
|
-
|
|
837
|
-
// display() on the loaded object re-displays via the same request/handle.
|
|
838
|
-
const outcomePromise = loaded.display();
|
|
839
|
-
const displayCall = execCallFor('presentPresentation');
|
|
840
|
-
expect(displayCall[4][0]).toBe(rawFetched);
|
|
841
|
-
displayCall[0]({ closeReason: 'programmatic' });
|
|
842
|
-
await outcomePromise;
|
|
843
|
-
|
|
844
|
-
// close() / back() delegate to the request's native actions.
|
|
845
|
-
loaded.close();
|
|
846
|
-
expect(execCallFor('closeAllScreens')).toBeDefined();
|
|
847
|
-
loaded.back();
|
|
848
|
-
expect(execCallFor('backPresentation')).toBeDefined();
|
|
849
|
-
});
|
|
850
|
-
|
|
851
|
-
it('rejects preload() on native failure', async () => {
|
|
852
|
-
const request = Purchasely.presentation.screen('screen1').build();
|
|
853
|
-
const preloadPromise = request.preload();
|
|
854
|
-
|
|
855
|
-
const fetchCall = execCallFor('fetchPresentation');
|
|
856
|
-
fetchCall[1]('Screen not found');
|
|
857
|
-
|
|
858
|
-
await expect(preloadPromise).rejects.toEqual({ message: 'Screen not found' });
|
|
859
|
-
});
|
|
860
|
-
|
|
861
|
-
// Android asymmetry regression (v6 audit): onPresented/onCloseRequested previously only
|
|
862
|
-
// fired on the direct present* path. The re-display action (presentPresentation, reached
|
|
863
|
-
// via preload() -> display()) must route the very same keep-alive envelopes to the
|
|
864
|
-
// builder's callbacks, resolving the display() Promise only once the final (non-kept)
|
|
865
|
-
// outcome envelope arrives -- envelopes strictly before resolution.
|
|
866
|
-
it('routes presented/closeRequested envelopes on the preload() -> display() path too, resolving only at the final outcome', async () => {
|
|
867
|
-
const onPresented = jest.fn();
|
|
868
|
-
const onCloseRequested = jest.fn();
|
|
869
|
-
const order = [];
|
|
870
|
-
onPresented.mockImplementation(() => order.push('presented'));
|
|
871
|
-
onCloseRequested.mockImplementation(() => order.push('closeRequested'));
|
|
872
|
-
|
|
873
|
-
const request = Purchasely.presentation
|
|
874
|
-
.screen('screen1')
|
|
875
|
-
.onPresented(onPresented)
|
|
876
|
-
.onCloseRequested(onCloseRequested)
|
|
877
|
-
.build();
|
|
878
|
-
|
|
879
|
-
const preloadPromise = request.preload();
|
|
880
|
-
const rawFetched = { screenId: 'screen1', fetchId: 'ply_fetch_789' };
|
|
881
|
-
execCallFor('fetchPresentation')[0](rawFetched);
|
|
882
|
-
await preloadPromise;
|
|
883
|
-
|
|
884
|
-
const outcomePromise = request.display();
|
|
885
|
-
const displayCall = execCallFor('presentPresentation');
|
|
886
|
-
const dispatch = displayCall[0];
|
|
887
|
-
|
|
888
|
-
dispatch({ event: 'presented', presentation: { screenId: 'screen1' } });
|
|
889
|
-
dispatch({ event: 'closeRequested' });
|
|
890
|
-
expect(order).toEqual(['presented', 'closeRequested']);
|
|
891
|
-
// Neither envelope resolves the Promise -- only the final outcome does.
|
|
892
|
-
let settled = false;
|
|
893
|
-
outcomePromise.then(() => { settled = true; });
|
|
894
|
-
await Promise.resolve();
|
|
895
|
-
expect(settled).toBe(false);
|
|
896
|
-
order.push('outcome-dispatched');
|
|
897
|
-
|
|
898
|
-
dispatch({ closeReason: 'button', presentation: { screenId: 'screen1' } });
|
|
899
|
-
const outcome = await outcomePromise;
|
|
900
|
-
|
|
901
|
-
// Envelopes fired strictly before the Promise resolved.
|
|
902
|
-
expect(order).toEqual(['presented', 'closeRequested', 'outcome-dispatched']);
|
|
903
|
-
expect(onPresented).toHaveBeenCalledWith(fullPresentation({ screenId: 'screen1' }), null);
|
|
904
|
-
expect(onCloseRequested).toHaveBeenCalledTimes(1);
|
|
905
|
-
expect(outcome.closeReason).toBe('button');
|
|
906
|
-
});
|
|
907
|
-
});
|
|
908
|
-
|
|
909
|
-
describe('onLoaded builder callback', () => {
|
|
910
|
-
it('fires onLoaded with the screenId-normalized presentation once preload() loads it', async () => {
|
|
911
|
-
const onLoaded = jest.fn();
|
|
912
|
-
const request = Purchasely.presentation.screen('screen1').onLoaded(onLoaded).build();
|
|
913
|
-
|
|
914
|
-
const preloadPromise = request.preload();
|
|
915
|
-
const rawFetched = { screenId: 'screen1', fetchId: 'ply_fetch_loaded' };
|
|
916
|
-
execCallFor('fetchPresentation')[0](rawFetched);
|
|
917
|
-
|
|
918
|
-
await preloadPromise;
|
|
919
|
-
|
|
920
|
-
expect(onLoaded).toHaveBeenCalledWith(fullPresentation({ screenId: 'screen1' }), null);
|
|
921
|
-
});
|
|
922
|
-
|
|
923
|
-
it('does not fire onLoaded when preload() fails (parity with RN/Flutter)', async () => {
|
|
924
|
-
const onLoaded = jest.fn();
|
|
925
|
-
const request = Purchasely.presentation.screen('screen1').onLoaded(onLoaded).build();
|
|
926
|
-
|
|
927
|
-
const preloadPromise = request.preload();
|
|
928
|
-
execCallFor('fetchPresentation')[1]('Screen not found');
|
|
929
|
-
|
|
930
|
-
await expect(preloadPromise).rejects.toEqual({ message: 'Screen not found' });
|
|
931
|
-
expect(onLoaded).not.toHaveBeenCalled();
|
|
932
|
-
});
|
|
933
|
-
});
|
|
934
|
-
|
|
935
|
-
describe('display() direct (no prior preload())', () => {
|
|
936
|
-
it('calls the matching present* action directly, without ever calling fetchPresentation', async () => {
|
|
937
|
-
mockExec.mockClear();
|
|
938
|
-
const outcomePromise = Purchasely.presentation.screen('screen1').build().display();
|
|
939
|
-
|
|
940
|
-
expect(mockExec.mock.calls.some((c) => c[3] === 'fetchPresentation')).toBe(false);
|
|
941
|
-
expect(mockExec.mock.calls.some((c) => c[3] === 'presentPresentationWithIdentifier')).toBe(true);
|
|
942
|
-
|
|
943
|
-
const call = execCallFor('presentPresentationWithIdentifier');
|
|
944
|
-
call[0]({ closeReason: 'button' });
|
|
945
|
-
await outcomePromise;
|
|
946
|
-
});
|
|
947
|
-
});
|
|
948
|
-
|
|
949
|
-
describe('request.close()', () => {
|
|
950
|
-
it('delegates to closeAllScreens (current bridge semantics)', () => {
|
|
951
|
-
mockExec.mockClear();
|
|
952
|
-
const request = Purchasely.presentation.placement('placement1').build();
|
|
953
|
-
|
|
954
|
-
request.close();
|
|
955
|
-
|
|
956
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
957
|
-
expect.any(Function),
|
|
958
|
-
expect.any(Function),
|
|
959
|
-
'Purchasely',
|
|
960
|
-
'closeAllScreens',
|
|
961
|
-
[]
|
|
962
|
-
);
|
|
963
|
-
});
|
|
964
|
-
});
|
|
965
|
-
|
|
966
|
-
describe('request.back()', () => {
|
|
967
|
-
it('calls exec with the backPresentation native action', () => {
|
|
968
|
-
mockExec.mockClear();
|
|
969
|
-
const request = Purchasely.presentation.placement('placement1').build();
|
|
970
|
-
|
|
971
|
-
request.back();
|
|
972
|
-
|
|
973
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
974
|
-
expect.any(Function),
|
|
975
|
-
expect.any(Function),
|
|
976
|
-
'Purchasely',
|
|
977
|
-
'backPresentation',
|
|
978
|
-
[]
|
|
979
|
-
);
|
|
980
|
-
});
|
|
981
|
-
});
|
|
982
|
-
});
|
|
983
|
-
|
|
984
|
-
describe('removeDefaultPresentationDismissHandler', () => {
|
|
985
|
-
it('should call exec with correct parameters', () => {
|
|
986
|
-
Purchasely.removeDefaultPresentationDismissHandler();
|
|
987
|
-
|
|
988
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
989
|
-
expect.any(Function),
|
|
990
|
-
expect.any(Function),
|
|
991
|
-
'Purchasely',
|
|
992
|
-
'removeDefaultPresentationDismissHandler',
|
|
993
|
-
[]
|
|
994
|
-
);
|
|
995
|
-
});
|
|
996
|
-
});
|
|
997
|
-
|
|
998
|
-
describe('purchaseWithPlanVendorId', () => {
|
|
999
|
-
it('should call exec with correct parameters', () => {
|
|
1000
|
-
const success = jest.fn();
|
|
1001
|
-
const error = jest.fn();
|
|
1002
|
-
|
|
1003
|
-
Purchasely.purchaseWithPlanVendorId('plan1', 'offer1', 'content1', success, error);
|
|
1004
|
-
|
|
1005
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1006
|
-
success,
|
|
1007
|
-
error,
|
|
1008
|
-
'Purchasely',
|
|
1009
|
-
'purchaseWithPlanVendorId',
|
|
1010
|
-
['plan1', 'offer1', 'content1']
|
|
1011
|
-
);
|
|
1012
|
-
});
|
|
1013
|
-
});
|
|
1014
|
-
|
|
1015
|
-
describe('restoreAllProducts', () => {
|
|
1016
|
-
it('should call exec with correct parameters', () => {
|
|
1017
|
-
const success = jest.fn();
|
|
1018
|
-
const error = jest.fn();
|
|
1019
|
-
|
|
1020
|
-
Purchasely.restoreAllProducts(success, error);
|
|
1021
|
-
|
|
1022
|
-
expect(mockExec).toHaveBeenCalledWith(success, error, 'Purchasely', 'restoreAllProducts', []);
|
|
1023
|
-
});
|
|
1024
|
-
});
|
|
1025
|
-
|
|
1026
|
-
describe('silentRestoreAllProducts', () => {
|
|
1027
|
-
it('should call exec with correct parameters', () => {
|
|
1028
|
-
const success = jest.fn();
|
|
1029
|
-
const error = jest.fn();
|
|
1030
|
-
|
|
1031
|
-
Purchasely.silentRestoreAllProducts(success, error);
|
|
1032
|
-
|
|
1033
|
-
expect(mockExec).toHaveBeenCalledWith(success, error, 'Purchasely', 'silentRestoreAllProducts', []);
|
|
1034
|
-
});
|
|
1035
|
-
});
|
|
1036
|
-
|
|
1037
|
-
describe('purchasedSubscription', () => {
|
|
1038
|
-
it('should call exec with correct parameters', () => {
|
|
1039
|
-
const success = jest.fn();
|
|
1040
|
-
const error = jest.fn();
|
|
1041
|
-
|
|
1042
|
-
Purchasely.purchasedSubscription(success, error);
|
|
1043
|
-
|
|
1044
|
-
expect(mockExec).toHaveBeenCalledWith(success, error, 'Purchasely', 'purchasedSubscription', []);
|
|
1045
|
-
});
|
|
1046
|
-
});
|
|
1047
|
-
|
|
1048
|
-
describe('handleDeeplink', () => {
|
|
1049
|
-
it('should call exec with correct parameters', () => {
|
|
1050
|
-
const success = jest.fn();
|
|
1051
|
-
const error = jest.fn();
|
|
1052
|
-
|
|
1053
|
-
Purchasely.handleDeeplink('https://example.com/deeplink', success, error);
|
|
1054
|
-
|
|
1055
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1056
|
-
success,
|
|
1057
|
-
error,
|
|
1058
|
-
'Purchasely',
|
|
1059
|
-
'handleDeeplink',
|
|
1060
|
-
['https://example.com/deeplink']
|
|
1061
|
-
);
|
|
1062
|
-
});
|
|
1063
|
-
});
|
|
1064
|
-
|
|
1065
|
-
describe('allProducts', () => {
|
|
1066
|
-
it('should call exec with correct parameters', () => {
|
|
1067
|
-
const success = jest.fn();
|
|
1068
|
-
const error = jest.fn();
|
|
1069
|
-
|
|
1070
|
-
Purchasely.allProducts(success, error);
|
|
1071
|
-
|
|
1072
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1073
|
-
success,
|
|
1074
|
-
expect.any(Function),
|
|
1075
|
-
'Purchasely',
|
|
1076
|
-
'allProducts',
|
|
1077
|
-
[]
|
|
1078
|
-
);
|
|
1079
|
-
});
|
|
1080
|
-
});
|
|
1081
|
-
|
|
1082
|
-
describe('planWithIdentifier', () => {
|
|
1083
|
-
it('should call exec with correct parameters', () => {
|
|
1084
|
-
const success = jest.fn();
|
|
1085
|
-
|
|
1086
|
-
Purchasely.planWithIdentifier('plan1', success);
|
|
1087
|
-
|
|
1088
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1089
|
-
success,
|
|
1090
|
-
expect.any(Function),
|
|
1091
|
-
'Purchasely',
|
|
1092
|
-
'planWithIdentifier',
|
|
1093
|
-
['plan1']
|
|
1094
|
-
);
|
|
1095
|
-
});
|
|
1096
|
-
});
|
|
1097
|
-
|
|
1098
|
-
describe('productWithIdentifier', () => {
|
|
1099
|
-
it('should call exec with correct parameters', () => {
|
|
1100
|
-
const success = jest.fn();
|
|
1101
|
-
|
|
1102
|
-
Purchasely.productWithIdentifier('product1', success);
|
|
1103
|
-
|
|
1104
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1105
|
-
success,
|
|
1106
|
-
expect.any(Function),
|
|
1107
|
-
'Purchasely',
|
|
1108
|
-
'productWithIdentifier',
|
|
1109
|
-
['product1']
|
|
1110
|
-
);
|
|
1111
|
-
});
|
|
1112
|
-
});
|
|
1113
|
-
|
|
1114
|
-
// Flush pending microtasks (the interceptor result is reported through a Promise chain).
|
|
1115
|
-
const flush = () => new Promise((resolve) => setTimeout(resolve, 0));
|
|
1116
|
-
|
|
1117
|
-
// Returns the native success callback exec() was given for a registerActionInterceptor(kind).
|
|
1118
|
-
const nativeInterceptorFor = (kind) => {
|
|
1119
|
-
const call = mockExec.mock.calls.find(
|
|
1120
|
-
(c) => c[3] === 'registerActionInterceptor' && c[4][0] === kind
|
|
1121
|
-
);
|
|
1122
|
-
return call && call[0];
|
|
1123
|
-
};
|
|
1124
|
-
|
|
1125
|
-
describe('interceptAction (v6 per-action)', () => {
|
|
1126
|
-
it('registers a native interceptor for the given kind', () => {
|
|
1127
|
-
Purchasely.interceptAction('purchase', jest.fn());
|
|
1128
|
-
|
|
1129
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1130
|
-
expect.any(Function),
|
|
1131
|
-
expect.any(Function),
|
|
1132
|
-
'Purchasely',
|
|
1133
|
-
'registerActionInterceptor',
|
|
1134
|
-
['purchase']
|
|
1135
|
-
);
|
|
1136
|
-
});
|
|
1137
|
-
|
|
1138
|
-
it('invokes the handler with (info, parameters) and reports its result', async () => {
|
|
1139
|
-
const handler = jest.fn().mockReturnValue(Purchasely.InterceptResult.success);
|
|
1140
|
-
Purchasely.interceptAction('purchase', handler);
|
|
1141
|
-
const nativeSuccess = nativeInterceptorFor('purchase');
|
|
1142
|
-
mockExec.mockClear();
|
|
1143
|
-
|
|
1144
|
-
const event = {
|
|
1145
|
-
action: 'purchase',
|
|
1146
|
-
callbackId: 'purchase#1',
|
|
1147
|
-
info: { contentId: 'c1' },
|
|
1148
|
-
parameters: { plan: 'p1' },
|
|
1149
|
-
};
|
|
1150
|
-
nativeSuccess(event);
|
|
1151
|
-
await flush();
|
|
1152
|
-
|
|
1153
|
-
expect(handler).toHaveBeenCalledWith(event.info, event.parameters);
|
|
1154
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1155
|
-
expect.any(Function),
|
|
1156
|
-
expect.any(Function),
|
|
1157
|
-
'Purchasely',
|
|
1158
|
-
'completeActionInterceptor',
|
|
1159
|
-
['purchase#1', 'success']
|
|
1160
|
-
);
|
|
1161
|
-
});
|
|
1162
|
-
|
|
1163
|
-
// Commitment fields (iOS 26.4+, Apple only) ride on the plan carried by the purchase
|
|
1164
|
-
// payload's `parameters.plan`. The JS layer forwards `parameters` verbatim, so a plan's
|
|
1165
|
-
// `commitmentInfo` must survive untouched — this guards against a future param whitelist
|
|
1166
|
-
// silently dropping it.
|
|
1167
|
-
it('forwards a purchase payload plan carrying commitmentInfo to the handler', async () => {
|
|
1168
|
-
const handler = jest.fn().mockReturnValue(Purchasely.InterceptResult.success);
|
|
1169
|
-
Purchasely.interceptAction('purchase', handler);
|
|
1170
|
-
const nativeSuccess = nativeInterceptorFor('purchase');
|
|
1171
|
-
|
|
1172
|
-
const parameters = {
|
|
1173
|
-
plan: {
|
|
1174
|
-
vendorId: 'plan_monthly_12m',
|
|
1175
|
-
commitmentInfo: [
|
|
1176
|
-
{
|
|
1177
|
-
billingPlanType: Purchasely.BillingPlanType.monthly,
|
|
1178
|
-
billingPrice: 9.99,
|
|
1179
|
-
billingPeriod: 'P1M',
|
|
1180
|
-
totalPrice: 119.88,
|
|
1181
|
-
totalPeriod: 'P1Y',
|
|
1182
|
-
totalDuration: 12,
|
|
1183
|
-
},
|
|
1184
|
-
],
|
|
1185
|
-
},
|
|
1186
|
-
};
|
|
1187
|
-
nativeSuccess({ action: 'purchase', callbackId: 'purchase#c', info: null, parameters });
|
|
1188
|
-
await flush();
|
|
1189
|
-
|
|
1190
|
-
expect(handler).toHaveBeenCalledWith(null, parameters);
|
|
1191
|
-
expect(handler.mock.calls[0][1].plan.commitmentInfo[0].billingPlanType).toBe(2);
|
|
1192
|
-
});
|
|
1193
|
-
|
|
1194
|
-
it('ignores events whose action does not match the registered kind', async () => {
|
|
1195
|
-
const handler = jest.fn();
|
|
1196
|
-
Purchasely.interceptAction('restore', handler);
|
|
1197
|
-
const nativeSuccess = nativeInterceptorFor('restore');
|
|
1198
|
-
|
|
1199
|
-
nativeSuccess({ action: 'purchase', callbackId: 'purchase#2' });
|
|
1200
|
-
await flush();
|
|
1201
|
-
|
|
1202
|
-
expect(handler).not.toHaveBeenCalled();
|
|
1203
|
-
});
|
|
1204
|
-
|
|
1205
|
-
it('reports failed when the handler throws', async () => {
|
|
1206
|
-
Purchasely.interceptAction('purchase', () => { throw new Error('boom'); });
|
|
1207
|
-
const nativeSuccess = nativeInterceptorFor('purchase');
|
|
1208
|
-
mockExec.mockClear();
|
|
1209
|
-
|
|
1210
|
-
nativeSuccess({ action: 'purchase', callbackId: 'purchase#3' });
|
|
1211
|
-
await flush();
|
|
1212
|
-
|
|
1213
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1214
|
-
expect.any(Function),
|
|
1215
|
-
expect.any(Function),
|
|
1216
|
-
'Purchasely',
|
|
1217
|
-
'completeActionInterceptor',
|
|
1218
|
-
['purchase#3', 'failed']
|
|
1219
|
-
);
|
|
1220
|
-
});
|
|
1221
|
-
});
|
|
1222
|
-
|
|
1223
|
-
describe('removeActionInterceptor', () => {
|
|
1224
|
-
it('unregisters a single kind', () => {
|
|
1225
|
-
Purchasely.removeActionInterceptor('purchase');
|
|
1226
|
-
|
|
1227
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1228
|
-
expect.any(Function),
|
|
1229
|
-
expect.any(Function),
|
|
1230
|
-
'Purchasely',
|
|
1231
|
-
'unregisterActionInterceptor',
|
|
1232
|
-
['purchase']
|
|
1233
|
-
);
|
|
1234
|
-
});
|
|
1235
|
-
});
|
|
1236
|
-
|
|
1237
|
-
describe('removeAllActionInterceptors', () => {
|
|
1238
|
-
it('unregisters every registered kind', () => {
|
|
1239
|
-
Purchasely.interceptAction('purchase', jest.fn());
|
|
1240
|
-
Purchasely.interceptAction('restore', jest.fn());
|
|
1241
|
-
mockExec.mockClear();
|
|
1242
|
-
|
|
1243
|
-
Purchasely.removeAllActionInterceptors();
|
|
1244
|
-
|
|
1245
|
-
const unregistered = mockExec.mock.calls
|
|
1246
|
-
.filter((c) => c[3] === 'unregisterActionInterceptor')
|
|
1247
|
-
.map((c) => c[4][0]);
|
|
1248
|
-
expect(unregistered).toEqual(expect.arrayContaining(['purchase', 'restore']));
|
|
1249
|
-
});
|
|
1250
|
-
});
|
|
1251
|
-
|
|
1252
|
-
describe('userDidConsumeSubscriptionContent', () => {
|
|
1253
|
-
it('should call exec with correct parameters', () => {
|
|
1254
|
-
Purchasely.userDidConsumeSubscriptionContent();
|
|
1255
|
-
|
|
1256
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1257
|
-
expect.any(Function),
|
|
1258
|
-
expect.any(Function),
|
|
1259
|
-
'Purchasely',
|
|
1260
|
-
'userDidConsumeSubscriptionContent',
|
|
1261
|
-
[]
|
|
1262
|
-
);
|
|
1263
|
-
});
|
|
1264
|
-
});
|
|
1265
|
-
|
|
1266
|
-
describe('userSubscriptions', () => {
|
|
1267
|
-
it('defaults invalidateCache to false when omitted (PAR-29)', () => {
|
|
1268
|
-
const success = jest.fn();
|
|
1269
|
-
const error = jest.fn();
|
|
1270
|
-
|
|
1271
|
-
Purchasely.userSubscriptions(success, error);
|
|
1272
|
-
|
|
1273
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1274
|
-
success,
|
|
1275
|
-
expect.any(Function),
|
|
1276
|
-
'Purchasely',
|
|
1277
|
-
'userSubscriptions',
|
|
1278
|
-
[false]
|
|
1279
|
-
);
|
|
1280
|
-
});
|
|
1281
|
-
|
|
1282
|
-
it('forwards an explicit invalidateCache value', () => {
|
|
1283
|
-
const success = jest.fn();
|
|
1284
|
-
const error = jest.fn();
|
|
1285
|
-
|
|
1286
|
-
Purchasely.userSubscriptions(success, error, true);
|
|
1287
|
-
|
|
1288
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1289
|
-
success,
|
|
1290
|
-
expect.any(Function),
|
|
1291
|
-
'Purchasely',
|
|
1292
|
-
'userSubscriptions',
|
|
1293
|
-
[true]
|
|
1294
|
-
);
|
|
1295
|
-
});
|
|
1296
|
-
});
|
|
1297
|
-
|
|
1298
|
-
describe('userSubscriptionsHistory', () => {
|
|
1299
|
-
it('defaults invalidateCache to false when omitted (PAR-29)', () => {
|
|
1300
|
-
const success = jest.fn();
|
|
1301
|
-
const error = jest.fn();
|
|
1302
|
-
|
|
1303
|
-
Purchasely.userSubscriptionsHistory(success, error);
|
|
1304
|
-
|
|
1305
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1306
|
-
success,
|
|
1307
|
-
expect.any(Function),
|
|
1308
|
-
'Purchasely',
|
|
1309
|
-
'userSubscriptionsHistory',
|
|
1310
|
-
[false]
|
|
1311
|
-
);
|
|
1312
|
-
});
|
|
1313
|
-
|
|
1314
|
-
it('forwards an explicit invalidateCache value', () => {
|
|
1315
|
-
const success = jest.fn();
|
|
1316
|
-
const error = jest.fn();
|
|
1317
|
-
|
|
1318
|
-
Purchasely.userSubscriptionsHistory(success, error, true);
|
|
1319
|
-
|
|
1320
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1321
|
-
success,
|
|
1322
|
-
expect.any(Function),
|
|
1323
|
-
'Purchasely',
|
|
1324
|
-
'userSubscriptionsHistory',
|
|
1325
|
-
[true]
|
|
1326
|
-
);
|
|
1327
|
-
});
|
|
1328
|
-
});
|
|
1329
|
-
|
|
1330
|
-
describe('setLanguage', () => {
|
|
1331
|
-
it('should call exec with correct parameters', () => {
|
|
1332
|
-
Purchasely.setLanguage('fr');
|
|
1333
|
-
|
|
1334
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1335
|
-
expect.any(Function),
|
|
1336
|
-
expect.any(Function),
|
|
1337
|
-
'Purchasely',
|
|
1338
|
-
'setLanguage',
|
|
1339
|
-
['fr']
|
|
1340
|
-
);
|
|
1341
|
-
});
|
|
1342
|
-
});
|
|
1343
|
-
|
|
1344
|
-
describe('closeAllScreens', () => {
|
|
1345
|
-
it('should call exec with correct parameters', () => {
|
|
1346
|
-
const success = jest.fn();
|
|
1347
|
-
const error = jest.fn();
|
|
1348
|
-
|
|
1349
|
-
Purchasely.closeAllScreens(success, error);
|
|
1350
|
-
|
|
1351
|
-
expect(mockExec).toHaveBeenCalledWith(success, error, 'Purchasely', 'closeAllScreens', []);
|
|
1352
|
-
});
|
|
1353
|
-
|
|
1354
|
-
it('should default callbacks when none provided', () => {
|
|
1355
|
-
Purchasely.closeAllScreens();
|
|
1356
|
-
|
|
1357
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1358
|
-
expect.any(Function),
|
|
1359
|
-
expect.any(Function),
|
|
1360
|
-
'Purchasely',
|
|
1361
|
-
'closeAllScreens',
|
|
1362
|
-
[]
|
|
1363
|
-
);
|
|
1364
|
-
});
|
|
1365
|
-
});
|
|
1366
|
-
|
|
1367
|
-
describe('closePresentation (deprecated alias of closeAllScreens)', () => {
|
|
1368
|
-
it('should delegate to closeAllScreens', () => {
|
|
1369
|
-
Purchasely.closePresentation();
|
|
1370
|
-
|
|
1371
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1372
|
-
expect.any(Function),
|
|
1373
|
-
expect.any(Function),
|
|
1374
|
-
'Purchasely',
|
|
1375
|
-
'closeAllScreens',
|
|
1376
|
-
[]
|
|
1377
|
-
);
|
|
1378
|
-
});
|
|
1379
|
-
});
|
|
1380
|
-
|
|
1381
|
-
describe('User Attributes', () => {
|
|
1382
|
-
describe('setUserAttributeWithString', () => {
|
|
1383
|
-
it('should call exec with correct parameters', () => {
|
|
1384
|
-
Purchasely.setUserAttributeWithString('name', 'John', 'ESSENTIAL');
|
|
1385
|
-
|
|
1386
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1387
|
-
expect.any(Function),
|
|
1388
|
-
expect.any(Function),
|
|
1389
|
-
'Purchasely',
|
|
1390
|
-
'setUserAttributeWithString',
|
|
1391
|
-
['name', 'John', 'ESSENTIAL']
|
|
1392
|
-
);
|
|
1393
|
-
});
|
|
1394
|
-
});
|
|
1395
|
-
|
|
1396
|
-
describe('setUserAttributeWithBoolean', () => {
|
|
1397
|
-
it('should call exec with correct parameters', () => {
|
|
1398
|
-
Purchasely.setUserAttributeWithBoolean('isPremium', true, 'OPTIONAL');
|
|
1399
|
-
|
|
1400
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1401
|
-
expect.any(Function),
|
|
1402
|
-
expect.any(Function),
|
|
1403
|
-
'Purchasely',
|
|
1404
|
-
'setUserAttributeWithBoolean',
|
|
1405
|
-
['isPremium', true, 'OPTIONAL']
|
|
1406
|
-
);
|
|
1407
|
-
});
|
|
1408
|
-
});
|
|
1409
|
-
|
|
1410
|
-
describe('setUserAttributeWithInt', () => {
|
|
1411
|
-
it('should call exec with correct parameters', () => {
|
|
1412
|
-
Purchasely.setUserAttributeWithInt('age', 25, 'ESSENTIAL');
|
|
1413
|
-
|
|
1414
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1415
|
-
expect.any(Function),
|
|
1416
|
-
expect.any(Function),
|
|
1417
|
-
'Purchasely',
|
|
1418
|
-
'setUserAttributeWithInt',
|
|
1419
|
-
['age', 25, 'ESSENTIAL']
|
|
1420
|
-
);
|
|
1421
|
-
});
|
|
1422
|
-
});
|
|
1423
|
-
|
|
1424
|
-
describe('setUserAttributeWithDouble', () => {
|
|
1425
|
-
it('should call exec with correct parameters', () => {
|
|
1426
|
-
Purchasely.setUserAttributeWithDouble('balance', 99.99, 'ESSENTIAL');
|
|
1427
|
-
|
|
1428
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1429
|
-
expect.any(Function),
|
|
1430
|
-
expect.any(Function),
|
|
1431
|
-
'Purchasely',
|
|
1432
|
-
'setUserAttributeWithDouble',
|
|
1433
|
-
['balance', 99.99, 'ESSENTIAL']
|
|
1434
|
-
);
|
|
1435
|
-
});
|
|
1436
|
-
});
|
|
1437
|
-
|
|
1438
|
-
describe('setUserAttributeWithDate', () => {
|
|
1439
|
-
it('should call exec with correct parameters', () => {
|
|
1440
|
-
Purchasely.setUserAttributeWithDate('birthdate', '1990-01-01', 'ESSENTIAL');
|
|
1441
|
-
|
|
1442
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1443
|
-
expect.any(Function),
|
|
1444
|
-
expect.any(Function),
|
|
1445
|
-
'Purchasely',
|
|
1446
|
-
'setUserAttributeWithDate',
|
|
1447
|
-
['birthdate', '1990-01-01', 'ESSENTIAL']
|
|
1448
|
-
);
|
|
1449
|
-
});
|
|
1450
|
-
});
|
|
1451
|
-
|
|
1452
|
-
describe('setUserAttributeWithStringArray', () => {
|
|
1453
|
-
it('should call exec with correct parameters', () => {
|
|
1454
|
-
Purchasely.setUserAttributeWithStringArray('tags', ['a', 'b'], 'ESSENTIAL');
|
|
1455
|
-
|
|
1456
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1457
|
-
expect.any(Function),
|
|
1458
|
-
expect.any(Function),
|
|
1459
|
-
'Purchasely',
|
|
1460
|
-
'setUserAttributeWithStringArray',
|
|
1461
|
-
['tags', ['a', 'b'], 'ESSENTIAL']
|
|
1462
|
-
);
|
|
1463
|
-
});
|
|
1464
|
-
});
|
|
1465
|
-
|
|
1466
|
-
describe('setUserAttributeWithIntArray', () => {
|
|
1467
|
-
it('should call exec with correct parameters', () => {
|
|
1468
|
-
Purchasely.setUserAttributeWithIntArray('scores', [1, 2, 3], 'ESSENTIAL');
|
|
1469
|
-
|
|
1470
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1471
|
-
expect.any(Function),
|
|
1472
|
-
expect.any(Function),
|
|
1473
|
-
'Purchasely',
|
|
1474
|
-
'setUserAttributeWithIntArray',
|
|
1475
|
-
['scores', [1, 2, 3], 'ESSENTIAL']
|
|
1476
|
-
);
|
|
1477
|
-
});
|
|
1478
|
-
});
|
|
1479
|
-
|
|
1480
|
-
describe('setUserAttributeWithDoubleArray', () => {
|
|
1481
|
-
it('should call exec with correct parameters', () => {
|
|
1482
|
-
Purchasely.setUserAttributeWithDoubleArray('prices', [1.1, 2.2], 'ESSENTIAL');
|
|
1483
|
-
|
|
1484
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1485
|
-
expect.any(Function),
|
|
1486
|
-
expect.any(Function),
|
|
1487
|
-
'Purchasely',
|
|
1488
|
-
'setUserAttributeWithDoubleArray',
|
|
1489
|
-
['prices', [1.1, 2.2], 'ESSENTIAL']
|
|
1490
|
-
);
|
|
1491
|
-
});
|
|
1492
|
-
});
|
|
1493
|
-
|
|
1494
|
-
describe('setUserAttributeWithBooleanArray', () => {
|
|
1495
|
-
it('should call exec with correct parameters', () => {
|
|
1496
|
-
Purchasely.setUserAttributeWithBooleanArray('flags', [true, false], 'ESSENTIAL');
|
|
1497
|
-
|
|
1498
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1499
|
-
expect.any(Function),
|
|
1500
|
-
expect.any(Function),
|
|
1501
|
-
'Purchasely',
|
|
1502
|
-
'setUserAttributeWithBooleanArray',
|
|
1503
|
-
['flags', [true, false], 'ESSENTIAL']
|
|
1504
|
-
);
|
|
1505
|
-
});
|
|
1506
|
-
});
|
|
1507
|
-
|
|
1508
|
-
describe('userAttribute', () => {
|
|
1509
|
-
it('should call exec with correct parameters', () => {
|
|
1510
|
-
const success = jest.fn();
|
|
1511
|
-
const error = jest.fn();
|
|
1512
|
-
|
|
1513
|
-
Purchasely.userAttribute('name', success, error);
|
|
1514
|
-
|
|
1515
|
-
expect(mockExec).toHaveBeenCalledWith(success, error, 'Purchasely', 'userAttribute', ['name']);
|
|
1516
|
-
});
|
|
1517
|
-
});
|
|
1518
|
-
|
|
1519
|
-
describe('clearUserAttribute', () => {
|
|
1520
|
-
it('should call exec with correct parameters', () => {
|
|
1521
|
-
Purchasely.clearUserAttribute('name');
|
|
1522
|
-
|
|
1523
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1524
|
-
expect.any(Function),
|
|
1525
|
-
expect.any(Function),
|
|
1526
|
-
'Purchasely',
|
|
1527
|
-
'clearUserAttribute',
|
|
1528
|
-
['name']
|
|
1529
|
-
);
|
|
1530
|
-
});
|
|
1531
|
-
});
|
|
1532
|
-
|
|
1533
|
-
describe('clearUserAttributes', () => {
|
|
1534
|
-
it('should call exec with correct parameters', () => {
|
|
1535
|
-
Purchasely.clearUserAttributes();
|
|
1536
|
-
|
|
1537
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1538
|
-
expect.any(Function),
|
|
1539
|
-
expect.any(Function),
|
|
1540
|
-
'Purchasely',
|
|
1541
|
-
'clearUserAttributes',
|
|
1542
|
-
[]
|
|
1543
|
-
);
|
|
1544
|
-
});
|
|
1545
|
-
});
|
|
1546
|
-
|
|
1547
|
-
describe('clearBuiltInAttributes', () => {
|
|
1548
|
-
it('should call exec with correct parameters', () => {
|
|
1549
|
-
Purchasely.clearBuiltInAttributes();
|
|
1550
|
-
|
|
1551
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1552
|
-
expect.any(Function),
|
|
1553
|
-
expect.any(Function),
|
|
1554
|
-
'Purchasely',
|
|
1555
|
-
'clearBuiltInAttributes',
|
|
1556
|
-
[]
|
|
1557
|
-
);
|
|
1558
|
-
});
|
|
1559
|
-
});
|
|
1560
|
-
|
|
1561
|
-
describe('getBuiltInAttributes (PAR-07)', () => {
|
|
1562
|
-
it('should call exec with correct parameters', () => {
|
|
1563
|
-
const success = jest.fn();
|
|
1564
|
-
const error = jest.fn();
|
|
1565
|
-
|
|
1566
|
-
Purchasely.getBuiltInAttributes(success, error);
|
|
1567
|
-
|
|
1568
|
-
expect(mockExec).toHaveBeenCalledWith(success, error, 'Purchasely', 'getBuiltInAttributes', []);
|
|
1569
|
-
});
|
|
1570
|
-
});
|
|
1571
|
-
|
|
1572
|
-
describe('getBuiltInAttribute (PAR-07)', () => {
|
|
1573
|
-
it('should call exec with correct parameters', () => {
|
|
1574
|
-
const success = jest.fn();
|
|
1575
|
-
const error = jest.fn();
|
|
1576
|
-
|
|
1577
|
-
Purchasely.getBuiltInAttribute('ply_session_count', success, error);
|
|
1578
|
-
|
|
1579
|
-
expect(mockExec).toHaveBeenCalledWith(success, error, 'Purchasely', 'getBuiltInAttribute', ['ply_session_count']);
|
|
1580
|
-
});
|
|
1581
|
-
});
|
|
1582
|
-
|
|
1583
|
-
describe('userAttributes (REC-12 / PAR-03)', () => {
|
|
1584
|
-
it('should call exec with correct parameters', () => {
|
|
1585
|
-
const success = jest.fn();
|
|
1586
|
-
const error = jest.fn();
|
|
1587
|
-
|
|
1588
|
-
Purchasely.userAttributes(success, error);
|
|
1589
|
-
|
|
1590
|
-
expect(mockExec).toHaveBeenCalledWith(success, error, 'Purchasely', 'userAttributes', []);
|
|
1591
|
-
});
|
|
1592
|
-
});
|
|
1593
|
-
|
|
1594
|
-
describe('incrementUserAttribute (REC-12 / PAR-02)', () => {
|
|
1595
|
-
it('should call exec with correct parameters', () => {
|
|
1596
|
-
Purchasely.incrementUserAttribute('counter', 5);
|
|
1597
|
-
|
|
1598
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1599
|
-
expect.any(Function),
|
|
1600
|
-
expect.any(Function),
|
|
1601
|
-
'Purchasely',
|
|
1602
|
-
'incrementUserAttribute',
|
|
1603
|
-
['counter', 5]
|
|
1604
|
-
);
|
|
1605
|
-
});
|
|
1606
|
-
|
|
1607
|
-
it('should forward an omitted value as-is (native defaults it to 1)', () => {
|
|
1608
|
-
Purchasely.incrementUserAttribute('counter');
|
|
1609
|
-
|
|
1610
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1611
|
-
expect.any(Function),
|
|
1612
|
-
expect.any(Function),
|
|
1613
|
-
'Purchasely',
|
|
1614
|
-
'incrementUserAttribute',
|
|
1615
|
-
['counter', undefined]
|
|
1616
|
-
);
|
|
1617
|
-
});
|
|
1618
|
-
});
|
|
1619
|
-
|
|
1620
|
-
describe('decrementUserAttribute (REC-12 / PAR-02)', () => {
|
|
1621
|
-
it('should call exec with correct parameters', () => {
|
|
1622
|
-
Purchasely.decrementUserAttribute('counter', 3);
|
|
1623
|
-
|
|
1624
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1625
|
-
expect.any(Function),
|
|
1626
|
-
expect.any(Function),
|
|
1627
|
-
'Purchasely',
|
|
1628
|
-
'decrementUserAttribute',
|
|
1629
|
-
['counter', 3]
|
|
1630
|
-
);
|
|
1631
|
-
});
|
|
1632
|
-
});
|
|
1633
|
-
});
|
|
1634
|
-
|
|
1635
|
-
describe('isEligibleForIntroOffer', () => {
|
|
1636
|
-
it('should call exec with correct parameters', () => {
|
|
1637
|
-
const success = jest.fn();
|
|
1638
|
-
const error = jest.fn();
|
|
1639
|
-
|
|
1640
|
-
Purchasely.isEligibleForIntroOffer('plan1', success, error);
|
|
1641
|
-
|
|
1642
|
-
expect(mockExec).toHaveBeenCalledWith(success, error, 'Purchasely', 'isEligibleForIntroOffer', ['plan1']);
|
|
1643
|
-
});
|
|
1644
|
-
});
|
|
1645
|
-
|
|
1646
|
-
describe('signPromotionalOffer', () => {
|
|
1647
|
-
it('should call exec with correct parameters', () => {
|
|
1648
|
-
const success = jest.fn();
|
|
1649
|
-
const error = jest.fn();
|
|
1650
|
-
|
|
1651
|
-
Purchasely.signPromotionalOffer('product1', 'offer1', success, error);
|
|
1652
|
-
|
|
1653
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1654
|
-
success,
|
|
1655
|
-
error,
|
|
1656
|
-
'Purchasely',
|
|
1657
|
-
'signPromotionalOffer',
|
|
1658
|
-
['product1', 'offer1']
|
|
1659
|
-
);
|
|
1660
|
-
});
|
|
1661
|
-
});
|
|
1662
|
-
|
|
1663
|
-
describe('setThemeMode', () => {
|
|
1664
|
-
it('should call exec with correct parameters', () => {
|
|
1665
|
-
Purchasely.setThemeMode(Purchasely.ThemeMode.dark);
|
|
1666
|
-
|
|
1667
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1668
|
-
expect.any(Function),
|
|
1669
|
-
expect.any(Function),
|
|
1670
|
-
'Purchasely',
|
|
1671
|
-
'setThemeMode',
|
|
1672
|
-
[1]
|
|
1673
|
-
);
|
|
1674
|
-
});
|
|
1675
|
-
});
|
|
1676
|
-
|
|
1677
|
-
describe('revokeDataProcessingConsent', () => {
|
|
1678
|
-
it('should call exec with correct parameters', () => {
|
|
1679
|
-
Purchasely.revokeDataProcessingConsent(['ANALYTICS', 'CAMPAIGNS']);
|
|
1680
|
-
|
|
1681
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1682
|
-
expect.any(Function),
|
|
1683
|
-
expect.any(Function),
|
|
1684
|
-
'Purchasely',
|
|
1685
|
-
'revokeDataProcessingConsent',
|
|
1686
|
-
[['ANALYTICS', 'CAMPAIGNS']]
|
|
1687
|
-
);
|
|
1688
|
-
});
|
|
1689
|
-
});
|
|
1690
|
-
|
|
1691
|
-
describe('setDebugMode', () => {
|
|
1692
|
-
it('should call exec with correct parameters', () => {
|
|
1693
|
-
Purchasely.setDebugMode(true);
|
|
1694
|
-
|
|
1695
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1696
|
-
expect.any(Function),
|
|
1697
|
-
expect.any(Function),
|
|
1698
|
-
'Purchasely',
|
|
1699
|
-
'setDebugMode',
|
|
1700
|
-
[true]
|
|
1701
|
-
);
|
|
1702
|
-
});
|
|
1703
|
-
});
|
|
1704
|
-
|
|
1705
|
-
describe('Dynamic Offerings (PAR-05)', () => {
|
|
1706
|
-
describe('setDynamicOffering', () => {
|
|
1707
|
-
it('should call exec with correct parameters, forwarding billingPlanType', () => {
|
|
1708
|
-
const success = jest.fn();
|
|
1709
|
-
const error = jest.fn();
|
|
1710
|
-
|
|
1711
|
-
Purchasely.setDynamicOffering('ref_1', 'plan_vendor_id', 'offer_vendor_id', Purchasely.BillingPlanType.monthly, success, error);
|
|
1712
|
-
|
|
1713
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1714
|
-
success,
|
|
1715
|
-
error,
|
|
1716
|
-
'Purchasely',
|
|
1717
|
-
'setDynamicOffering',
|
|
1718
|
-
['ref_1', 'plan_vendor_id', 'offer_vendor_id', 2]
|
|
1719
|
-
);
|
|
1720
|
-
});
|
|
1721
|
-
|
|
1722
|
-
it('should forward a null offerVendorId and default billingPlanType to unspecified when omitted', () => {
|
|
1723
|
-
Purchasely.setDynamicOffering('ref_1', 'plan_vendor_id', null, undefined, jest.fn(), jest.fn());
|
|
1724
|
-
|
|
1725
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1726
|
-
expect.any(Function),
|
|
1727
|
-
expect.any(Function),
|
|
1728
|
-
'Purchasely',
|
|
1729
|
-
'setDynamicOffering',
|
|
1730
|
-
['ref_1', 'plan_vendor_id', null, 0]
|
|
1731
|
-
);
|
|
1732
|
-
});
|
|
1733
|
-
});
|
|
1734
|
-
|
|
1735
|
-
describe('getDynamicOfferings', () => {
|
|
1736
|
-
it('should call exec with correct parameters', () => {
|
|
1737
|
-
const success = jest.fn();
|
|
1738
|
-
const error = jest.fn();
|
|
1739
|
-
|
|
1740
|
-
Purchasely.getDynamicOfferings(success, error);
|
|
1741
|
-
|
|
1742
|
-
expect(mockExec).toHaveBeenCalledWith(success, error, 'Purchasely', 'getDynamicOfferings', []);
|
|
1743
|
-
});
|
|
1744
|
-
});
|
|
1745
|
-
|
|
1746
|
-
describe('removeDynamicOffering', () => {
|
|
1747
|
-
it('should call exec with correct parameters', () => {
|
|
1748
|
-
Purchasely.removeDynamicOffering('ref_1');
|
|
1749
|
-
|
|
1750
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1751
|
-
expect.any(Function),
|
|
1752
|
-
expect.any(Function),
|
|
1753
|
-
'Purchasely',
|
|
1754
|
-
'removeDynamicOffering',
|
|
1755
|
-
['ref_1']
|
|
1756
|
-
);
|
|
1757
|
-
});
|
|
1758
|
-
});
|
|
1759
|
-
|
|
1760
|
-
describe('clearDynamicOfferings', () => {
|
|
1761
|
-
it('should call exec with correct parameters', () => {
|
|
1762
|
-
Purchasely.clearDynamicOfferings();
|
|
1763
|
-
|
|
1764
|
-
expect(mockExec).toHaveBeenCalledWith(
|
|
1765
|
-
expect.any(Function),
|
|
1766
|
-
expect.any(Function),
|
|
1767
|
-
'Purchasely',
|
|
1768
|
-
'clearDynamicOfferings',
|
|
1769
|
-
[]
|
|
1770
|
-
);
|
|
1771
|
-
});
|
|
1772
|
-
});
|
|
1773
|
-
});
|
|
1774
|
-
|
|
1775
|
-
// Purchasely 6.0: these v5 APIs were deliberately removed (see MIGRATION-v6.md).
|
|
1776
|
-
// Asserting their absence guards against accidental resurrection/typos reintroducing
|
|
1777
|
-
// a v5-shaped surface alongside the v6 replacements.
|
|
1778
|
-
describe('Removed v5 APIs (should not exist in v6)', () => {
|
|
1779
|
-
it('removes the presentation methods with no v6 native screen equivalent', () => {
|
|
1780
|
-
expect(Purchasely.presentSubscriptions).toBeUndefined();
|
|
1781
|
-
expect(Purchasely.presentProductWithIdentifier).toBeUndefined();
|
|
1782
|
-
expect(Purchasely.presentPlanWithIdentifier).toBeUndefined();
|
|
1783
|
-
expect(Purchasely.showPresentation).toBeUndefined();
|
|
1784
|
-
expect(Purchasely.hidePresentation).toBeUndefined();
|
|
1785
|
-
});
|
|
1786
|
-
|
|
1787
|
-
// The imperative presentation surface is replaced by the Purchasely.presentation
|
|
1788
|
-
// builder (see the 'presentation builder (v6)' suite above).
|
|
1789
|
-
it('removes the imperative presentation surface in favor of Purchasely.presentation', () => {
|
|
1790
|
-
expect(Purchasely.fetchPresentation).toBeUndefined();
|
|
1791
|
-
expect(Purchasely.fetchPresentationForPlacement).toBeUndefined();
|
|
1792
|
-
expect(Purchasely.fetchPresentationForDefault).toBeUndefined();
|
|
1793
|
-
expect(Purchasely.presentPresentationWithIdentifier).toBeUndefined();
|
|
1794
|
-
expect(Purchasely.presentPresentationForPlacement).toBeUndefined();
|
|
1795
|
-
expect(Purchasely.presentPresentationForDefault).toBeUndefined();
|
|
1796
|
-
expect(Purchasely.presentPresentation).toBeUndefined();
|
|
1797
|
-
expect(Purchasely.backPresentation).toBeUndefined();
|
|
1798
|
-
|
|
1799
|
-
expect(typeof Purchasely.presentation.placement).toBe('function');
|
|
1800
|
-
expect(typeof Purchasely.presentation.screen).toBe('function');
|
|
1801
|
-
expect(typeof Purchasely.presentation.defaultSource).toBe('function');
|
|
1802
|
-
expect(typeof Purchasely.presentation.default).toBe('function');
|
|
1803
|
-
});
|
|
1804
|
-
|
|
1805
|
-
it('removes the single global action interceptor in favor of interceptAction(kind, handler)', () => {
|
|
1806
|
-
expect(Purchasely.setPaywallActionInterceptor).toBeUndefined();
|
|
1807
|
-
expect(Purchasely.onProcessAction).toBeUndefined();
|
|
1808
|
-
expect(Purchasely.PaywallAction).toBeUndefined();
|
|
1809
|
-
});
|
|
1810
|
-
|
|
1811
|
-
it('removes the renamed deeplink methods', () => {
|
|
1812
|
-
expect(Purchasely.readyToOpenDeeplink).toBeUndefined();
|
|
1813
|
-
expect(Purchasely.isDeeplinkHandled).toBeUndefined();
|
|
1814
|
-
});
|
|
1815
|
-
|
|
1816
|
-
it('removes the renamed default dismiss handler', () => {
|
|
1817
|
-
expect(Purchasely.setDefaultPresentationResultHandler).toBeUndefined();
|
|
1818
|
-
});
|
|
1819
|
-
|
|
1820
|
-
it('removes the RunningMode values dropped by native 6.0', () => {
|
|
1821
|
-
expect(Purchasely.RunningMode.paywallObserver).toBeUndefined();
|
|
1822
|
-
expect(Purchasely.RunningMode.transactionOnly).toBeUndefined();
|
|
1823
|
-
expect(Object.keys(Purchasely.RunningMode).sort()).toEqual(['full', 'observer']);
|
|
1824
|
-
});
|
|
1825
|
-
});
|
|
1826
|
-
});
|