import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'; import { RudderClient } from '../../src/client/RudderClient.js'; import { createFakeTokenStore } from '../helpers/FakeTokenStore.js'; import { createFakeGateway, type FakeGateway } from '../helpers/fakeGateway.js'; function makeClient(): RudderClient { return new RudderClient({ baseUrl: 'https://api.test.rudder.build', projectKey: 'test-project', tokenStore: createFakeTokenStore(), runtime: { loginEvent: null }, }); } describe('E2E: player storage', () => { let gateway: FakeGateway; let client: RudderClient; beforeEach(() => { gateway = createFakeGateway(); gateway.install(); client = makeClient(); }); afterEach(() => vi.unstubAllGlobals()); it('saves items then reads them back (round-trip through the gateway)', async () => { await client.auth.loginWithDevice(); await client.storage.save([ { id: 'save_1', type: 'progress', data: JSON.stringify({ level: 7, gold: 1200 }) }, { id: 'settings', type: 'prefs', data: JSON.stringify({ sound: false }) }, ]); const all = await client.storage.reload(); expect(all.items).toHaveLength(2); const progress = all.items!.find((i) => i.id === 'save_1'); expect(JSON.parse(progress!.data!)).toEqual({ level: 7, gold: 1200 }); }); it('filters by type', async () => { await client.auth.loginWithDevice(); await client.storage.save([ { id: 'a', type: 'progress', data: '{}' }, { id: 'b', type: 'prefs', data: '{}' }, ]); // v0.2 fetches the whole storage; filtering by type is client-side. const all = await client.storage.reload(); const prefs = (all.items ?? []).filter((i) => i.type === 'prefs'); expect(prefs).toHaveLength(1); expect(prefs[0].id).toBe('b'); // The read went out as a storage fetch with limit as a query param, not a path segment. const getReq = gateway.recorded.findLast((r) => r.method === 'GET' && r.path === '/sdk/v1/storage'); expect(getReq?.query.get('limit')).toBe('100'); }); it('deletes a type and the items are gone', async () => { await client.auth.loginWithDevice(); await client.storage.save([ { id: 'a', type: 'progress', data: '{}' }, { id: 'b', type: 'prefs', data: '{}' }, ]); await client.storage.delete('progress'); const remaining = await client.storage.reload(); expect(remaining.items?.map((i) => i.id)).toEqual(['b']); }); it('storage writes carry the auth token', async () => { const token = (await client.auth.loginWithDevice()).accessToken; await client.storage.save([{ id: 'a', type: 't', data: '{}' }]); const put = gateway.recorded.find((r) => r.method === 'PUT' && r.path === '/sdk/v1/storage'); expect(put?.authToken).toBe(token); }); });