mirror of
https://github.com/jjbrunton/Sauci.git
synced 2026-10-31 18:19:43 +00:00
test(coverage): enforce API and app floors
Measure untouched mobile source, add regression coverage for native media paths and account operations, and enforce ratcheting API and mobile thresholds in required CI checks.
This commit is contained in:
1 parent
5c973c4ac5
commit
5f77b06044
13 files changed
+592
-1
No files matched your search
@@ -0,0 +1,84 @@
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
|
||||
import { AccountOperationsService } from '../src/domains/account-operations/service.js';
|
||||
import type { AuthAdminClient, PartnerNotifier, RevenueCatClient } from '../src/domains/account-operations/clients.js';
|
||||
import type { AccountOperationsRepository } from '../src/domains/account-operations/repository.js';
|
||||
|
||||
function setup(partnerPushToken: string | null = 'ExponentPushToken[partner]') {
|
||||
const repository = {
|
||||
deleteRelationship: vi.fn(async () => ({ partnerPushToken })),
|
||||
resetProgress: vi.fn(async () => ({ partnerPushToken })),
|
||||
deleteAccount: vi.fn(async (_userId: string, deleteAuthUser: () => Promise<void>) => {
|
||||
await deleteAuthUser();
|
||||
return { partnerPushToken };
|
||||
}),
|
||||
setPremium: vi.fn(async () => undefined),
|
||||
close: vi.fn(async () => undefined),
|
||||
} satisfies AccountOperationsRepository;
|
||||
const authAdmin = { deleteUser: vi.fn(async () => undefined) } satisfies AuthAdminClient;
|
||||
const revenueCat = { isEntitled: vi.fn(async () => true) } satisfies RevenueCatClient;
|
||||
const notifier = {
|
||||
relationshipDeleted: vi.fn(async () => undefined),
|
||||
progressReset: vi.fn(async () => undefined),
|
||||
partnerAccountDeleted: vi.fn(async () => undefined),
|
||||
} satisfies PartnerNotifier;
|
||||
return {
|
||||
repository,
|
||||
authAdmin,
|
||||
revenueCat,
|
||||
notifier,
|
||||
service: new AccountOperationsService(repository, authAdmin, revenueCat, notifier),
|
||||
};
|
||||
}
|
||||
|
||||
describe('AccountOperationsService', () => {
|
||||
it('deletes relationship data and notifies the partner', async () => {
|
||||
const { service, repository, notifier } = setup();
|
||||
await expect(service.deleteRelationship('user-1')).resolves.toEqual({
|
||||
success: true,
|
||||
message: 'Relationship data deleted successfully',
|
||||
});
|
||||
expect(repository.deleteRelationship).toHaveBeenCalledWith('user-1');
|
||||
expect(notifier.relationshipDeleted).toHaveBeenCalledWith('ExponentPushToken[partner]');
|
||||
});
|
||||
|
||||
it('resets progress and skips notification without a partner token', async () => {
|
||||
const { service, notifier } = setup(null);
|
||||
await expect(service.resetProgress('user-1')).resolves.toEqual({
|
||||
success: true,
|
||||
message: 'Progress reset successfully',
|
||||
});
|
||||
expect(notifier.progressReset).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('deletes hosted auth inside the repository operation before notifying', async () => {
|
||||
const { service, repository, authAdmin, notifier } = setup();
|
||||
await expect(service.deleteAccount('user-1')).resolves.toEqual({
|
||||
success: true,
|
||||
message: 'Account deleted successfully',
|
||||
});
|
||||
expect(repository.deleteAccount).toHaveBeenCalledOnce();
|
||||
expect(authAdmin.deleteUser).toHaveBeenCalledWith('user-1');
|
||||
expect(notifier.partnerAccountDeleted).toHaveBeenCalledWith('ExponentPushToken[partner]');
|
||||
});
|
||||
|
||||
it('persists the entitlement returned by RevenueCat', async () => {
|
||||
const { service, repository, revenueCat } = setup();
|
||||
revenueCat.isEntitled.mockResolvedValueOnce(false);
|
||||
await expect(service.syncSubscription('user-1')).resolves.toEqual({
|
||||
success: true,
|
||||
is_premium: false,
|
||||
});
|
||||
expect(repository.setPremium).toHaveBeenCalledWith('user-1', false);
|
||||
});
|
||||
|
||||
it('keeps a committed destructive operation successful when notification fails', async () => {
|
||||
const { service, notifier } = setup();
|
||||
notifier.relationshipDeleted.mockRejectedValueOnce(new Error('push unavailable'));
|
||||
const error = vi.spyOn(console, 'error').mockImplementation(() => undefined);
|
||||
|
||||
await expect(service.deleteRelationship('user-1')).resolves.toMatchObject({ success: true });
|
||||
expect(error).toHaveBeenCalledWith('Partner notification failed', expect.any(Error));
|
||||
error.mockRestore();
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user