storebound/tests/misc-drift.test.ts

74 lines
4.4 KiB
TypeScript

import { describe, expect, test } from 'bun:test';
import { campaignDiff } from '../cli/apple/offer-codes';
import { winBackDiff } from '../cli/apple/win-back';
import { cppDeepLinkReq, type AppEventDef, eventAttrDiff, eventPatchReq, extraCppLocales } from '../cli/lib/cpp-events';
import { missingVersionLocales } from '../cli/apple/screenshots';
import { dataSafetyDryNote } from '../cli/play/data-safety';
describe('offer code campaign drift', () => {
const cur = { eligibility: ['NON_SPENDER'], prices: [{ territory: 'USA', pointId: 'p1' }, { territory: 'DEU', pointId: 'p2' }] };
test('equal: no differences', () => {
expect(campaignDiff(cur, { eligibility: ['NON_SPENDER'], free: false, prices: cur.prices })).toEqual([]);
});
test('eligibility, territories, price and mode differ', () => {
const d = campaignDiff(cur, { eligibility: ['NON_SPENDER', 'CHURNED_SPENDER'], free: false, prices: [{ territory: 'USA', pointId: 'p9' }, { territory: 'FRA', pointId: 'p3' }] });
expect(d.join('|')).toContain('eligibility');
expect(d.join('|')).toContain('+1 (FRA)');
expect(d.join('|')).toContain('-1 (DEU)');
expect(d.join('|')).toContain('prices differ in 1 territory');
expect(campaignDiff(cur, { eligibility: ['NON_SPENDER'], free: true, prices: cur.prices }).join()).toContain('mode paid -> free');
});
});
describe('win-back drift', () => {
const want = { id: 'wb', type: 'pay-as-you-go', usd: 2.99, paidMonths: 3, lapsedMonths: { min: 1, max: 12 }, start: '2027-01-01', end: '2027-02-01' } as const;
test('equal', () => expect(winBackDiff({ offerMode: 'PAY_AS_YOU_GO', startDate: '2027-01-01', endDate: '2027-02-01' }, 2.99, want)).toEqual([]));
test('mode, price, dates', () => {
const d = winBackDiff({ offerMode: 'FREE_TRIAL', startDate: '2027-01-05', endDate: null }, 1.99, want);
expect(d.length).toBe(4);
expect(winBackDiff({ offerMode: 'PAY_AS_YOU_GO', startDate: '2027-01-01', endDate: '2027-02-01' }, undefined, want)).toEqual([]);
});
});
describe('event attribute drift', () => {
const ev: AppEventDef = { referenceName: 'Spring', badge: 'CHALLENGE', priority: 'high', schedule: { publishStart: '2027-03-01T00:00:00Z', eventStart: '2027-03-05T00:00:00Z', eventEnd: '2027-03-10T00:00:00Z' }, listings: {} };
const now = { badge: 'CHALLENGE', priority: 'HIGH', purpose: 'APPROPRIATE_FOR_ALL_USERS', territorySchedules: [{ territories: ['USA'], publishStart: '2027-03-01T00:00:00.000Z', eventStart: '2027-03-05T00:00:00.000Z', eventEnd: '2027-03-10T00:00:00.000Z' }] };
test('same instants in another format: no drift', () => {
const d = eventAttrDiff(ev, now);
expect(d.lines).toEqual([]);
expect(eventPatchReq('e1', 'Spring', d.attrs, d.lines)).toBeNull();
});
test('badge, priority and end differ: one PATCH', () => {
const d = eventAttrDiff({ ...ev, badge: 'MAJOR_UPDATE', priority: 'normal', schedule: { ...ev.schedule, eventEnd: '2027-03-12T00:00:00Z' } }, now);
expect(d.lines.length).toBe(3);
const r = eventPatchReq('e1', 'Spring', d.attrs, d.lines)!;
expect(r.method).toBe('PATCH');
expect(r.path).toBe('/v1/appEvents/e1');
expect((r.body as { data: { attributes: Record<string, unknown> } }).data.attributes.territorySchedules).toHaveLength(1);
});
});
describe('custom product page drift', () => {
test('deep link removed is cleared', () => {
const r = cppDeepLinkReq('v1', 'Page', undefined, 'example://old')!;
expect(r.note).toContain('removed');
expect((r.body as { data: { attributes: { deepLink: unknown } } }).data.attributes.deepLink).toBeNull();
});
test('equal or both empty: nothing', () => {
expect(cppDeepLinkReq('v1', 'Page', 'example://a', 'example://a')).toBeNull();
expect(cppDeepLinkReq('v1', 'Page', undefined, null)).toBeNull();
});
test('extra locales on the page', () => expect(extraCppLocales(['en-US', 'fr-FR'], ['en-US'])).toEqual(['fr-FR']));
});
describe('screenshots and data safety notes', () => {
test('version without a localization for a config language', () => {
expect(missingVersionLocales([{ apple: 'en-US' }, { apple: 'tr' }, {}], ['en-US'])).toEqual(['tr']);
});
test('data safety dry note says Play cannot be read and --force re-sends', () => {
const n = dataSafetyDryNote({ at: '2027-01-01T10:00:00Z' });
expect(n).toContain('no read API');
expect(n).toContain('--force');
expect(dataSafetyDryNote(null)).toContain('none recorded');
});
});