react-native-nami-sdk
Version:
React Native SDK for Nami - No-code paywall and onboarding flows with A/B testing.
178 lines (155 loc) • 5.1 kB
text/typescript
import {
parsePurchaseDates,
coerceSkuType,
mapToNamiPaywallAction,
parseEntitlements,
} from '../transformers';
import { NamiPaywallAction } from '../types';
describe('parsePurchaseDates', () => {
it('converts timestamp numbers to Date objects', () => {
const raw = {
skuId: 'com.example.monthly',
purchaseInitiatedTimestamp: 1700000000000,
expires: 1700086400000,
};
const result = parsePurchaseDates(raw);
expect(result.purchaseInitiatedTimestamp).toBeInstanceOf(Date);
expect(result.purchaseInitiatedTimestamp.getTime()).toBe(1700000000000);
expect(result.expires).toBeInstanceOf(Date);
expect(result.expires!.getTime()).toBe(1700086400000);
});
it('sets expires to undefined when absent', () => {
const raw = {
skuId: 'com.example.lifetime',
purchaseInitiatedTimestamp: 1700000000000,
};
const result = parsePurchaseDates(raw);
expect(result.expires).toBeUndefined();
});
it('sets expires to undefined when explicitly null', () => {
const raw = {
skuId: 'com.example.lifetime',
purchaseInitiatedTimestamp: 1700000000000,
expires: null,
};
const result = parsePurchaseDates(raw);
expect(result.expires).toBeUndefined();
});
it('preserves all other fields via spread', () => {
const raw = {
skuId: 'com.example.monthly',
transactionIdentifier: 'txn_123',
purchaseSource: 'CAMPAIGN' as const,
purchaseInitiatedTimestamp: 1700000000000,
sku: { id: 'sku_1', skuId: 'com.example.monthly', type: 'subscription' },
};
const result = parsePurchaseDates(raw);
expect(result.skuId).toBe('com.example.monthly');
expect(result.transactionIdentifier).toBe('txn_123');
expect(result.purchaseSource).toBe('CAMPAIGN');
expect(result.sku).toEqual(raw.sku);
});
});
describe('coerceSkuType', () => {
it.each(['unknown', 'one_time_purchase', 'subscription'] as const)(
'accepts valid type "%s"',
(type) => {
expect(coerceSkuType(type)).toBe(type);
},
);
it('returns "unknown" for invalid types', () => {
expect(coerceSkuType('invalid')).toBe('unknown');
expect(coerceSkuType('')).toBe('unknown');
expect(coerceSkuType('SUBSCRIPTION')).toBe('unknown');
});
});
describe('mapToNamiPaywallAction', () => {
it.each(Object.values(NamiPaywallAction))(
'accepts valid action "%s"',
(action) => {
expect(mapToNamiPaywallAction(action)).toBe(action);
},
);
it('returns UNKNOWN for unrecognized actions', () => {
expect(mapToNamiPaywallAction('NOT_A_REAL_ACTION')).toBe(
NamiPaywallAction.UNKNOWN,
);
expect(mapToNamiPaywallAction('')).toBe(NamiPaywallAction.UNKNOWN);
expect(mapToNamiPaywallAction('buy_sku')).toBe(NamiPaywallAction.UNKNOWN);
});
});
describe('parseEntitlements', () => {
const rawPurchase = {
skuId: 'com.example.monthly',
purchaseInitiatedTimestamp: 1700000000000,
expires: 1700086400000,
};
it('converts activePurchases dates', () => {
const raw = [
{
name: 'Premium',
desc: 'Premium access',
referenceId: 'premium',
activePurchases: [rawPurchase],
purchasedSkus: [{ id: 'sku_1', skuId: 'com.example.monthly', type: 'subscription' }],
relatedSkus: [],
},
];
const result = parseEntitlements(raw);
expect(result).toHaveLength(1);
expect(result[0].activePurchases[0].purchaseInitiatedTimestamp).toBeInstanceOf(Date);
expect(result[0].activePurchases[0].expires).toBeInstanceOf(Date);
});
it('defaults relatedSkus and purchasedSkus to empty arrays when missing', () => {
const raw = [
{
name: 'Basic',
desc: 'Basic access',
referenceId: 'basic',
activePurchases: [],
},
];
const result = parseEntitlements(raw);
expect(result[0].relatedSkus).toEqual([]);
expect(result[0].purchasedSkus).toEqual([]);
});
it('preserves existing relatedSkus and purchasedSkus', () => {
const sku = { id: 'sku_1', skuId: 'com.example.monthly', type: 'subscription' };
const raw = [
{
name: 'Premium',
desc: 'Premium access',
referenceId: 'premium',
activePurchases: [],
purchasedSkus: [sku],
relatedSkus: [sku],
},
];
const result = parseEntitlements(raw);
expect(result[0].purchasedSkus).toEqual([sku]);
expect(result[0].relatedSkus).toEqual([sku]);
});
it('handles empty array', () => {
expect(parseEntitlements([])).toEqual([]);
});
it('handles multiple entitlements', () => {
const raw = [
{
name: 'A',
desc: '',
referenceId: 'a',
activePurchases: [rawPurchase],
},
{
name: 'B',
desc: '',
referenceId: 'b',
activePurchases: [rawPurchase, rawPurchase],
},
];
const result = parseEntitlements(raw);
expect(result).toHaveLength(2);
expect(result[0].activePurchases).toHaveLength(1);
expect(result[1].activePurchases).toHaveLength(2);
});
});