113 lines
4.9 KiB
TypeScript
113 lines
4.9 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { readFileSync } from 'node:fs';
|
|
import { join } from 'node:path';
|
|
|
|
const schema = readFileSync(join(process.cwd(), 'prisma/schema.prisma'), 'utf8');
|
|
const migration = readFileSync(join(process.cwd(), 'prisma/migrations/20260621090000_init_v2_schema/migration.sql'), 'utf8');
|
|
const authMigration = readFileSync(join(process.cwd(), 'prisma/migrations/20260621093000_auth_sessions/migration.sql'), 'utf8');
|
|
const numberLibraryMigration = readFileSync(join(process.cwd(), 'prisma/migrations/20260624095000_number_library/migration.sql'), 'utf8');
|
|
const businessPrefixMigration = readFileSync(
|
|
join(process.cwd(), 'prisma/migrations/20260624121000_business_prefix_gateway_rewrite/migration.sql'),
|
|
'utf8'
|
|
);
|
|
|
|
describe('Prisma schema contract', () => {
|
|
it('defines every V2 core business table', () => {
|
|
const tables = [
|
|
'customers',
|
|
'customer_gateways',
|
|
'customer_gateway_ips',
|
|
'business_prefixes',
|
|
'customer_gateway_business_prefixes',
|
|
'customer_gateway_caller_prefixes',
|
|
'customer_gateway_policies',
|
|
'customer_recharges',
|
|
'vendors',
|
|
'vendor_recharges',
|
|
'vendor_gateways',
|
|
'vendor_gateway_blocked_regions',
|
|
'vendor_gateway_forbidden_periods',
|
|
'vendor_gateway_codecs',
|
|
'vendor_gateway_prefix_rules',
|
|
'vendor_gateway_caller_rewrite_pool',
|
|
'landing_line_groups',
|
|
'landing_line_group_items',
|
|
'geo_cities',
|
|
'phone_number_segments',
|
|
'phone_area_codes',
|
|
'carrier_prefix_rules',
|
|
'raw_cdrs',
|
|
'rated_cdrs',
|
|
'recordings',
|
|
'quality_sampling_rules',
|
|
'quality_reviews',
|
|
'users',
|
|
'roles',
|
|
'permissions',
|
|
'user_roles',
|
|
'user_sessions',
|
|
'role_permissions',
|
|
'audit_logs',
|
|
'outbox_events',
|
|
'idempotency_keys'
|
|
];
|
|
|
|
for (const table of tables) {
|
|
expect(schema).toContain(`@@map("${table}")`);
|
|
expect(`${migration}\n${authMigration}\n${numberLibraryMigration}\n${businessPrefixMigration}`).toContain(
|
|
`CREATE TABLE \`${table}\``
|
|
);
|
|
}
|
|
});
|
|
|
|
it('keeps money and idempotent facts constrained', () => {
|
|
expect(migration).toContain('DECIMAL(20, 6)');
|
|
expect(migration).toContain('UNIQUE INDEX `raw_cdrs_event_id_key`');
|
|
expect(migration).toContain('UNIQUE INDEX `raw_cdrs_call_id_ended_at_key`');
|
|
expect(migration).toContain('UNIQUE INDEX `customer_recharges_idempotency_key_key`');
|
|
expect(migration).toContain('UNIQUE INDEX `vendor_recharges_idempotency_key_key`');
|
|
expect(migration).toContain('UNIQUE INDEX `idempotency_keys_key_key`');
|
|
});
|
|
|
|
it('captures number library and CDR callee attribution fields', () => {
|
|
expect(schema).toContain('model GeoCity');
|
|
expect(schema).toContain('model PhoneNumberSegment');
|
|
expect(schema).toContain('model CarrierPrefixRule');
|
|
expect(numberLibraryMigration).toContain('`segment7` CHAR(7) NOT NULL');
|
|
expect(numberLibraryMigration).toContain('`callee_city_code` VARCHAR(12) NULL');
|
|
expect(numberLibraryMigration).toContain('`callee_operator` ENUM');
|
|
expect(numberLibraryMigration).toContain('CREATE INDEX `raw_cdrs_callee_operator_started_at_idx`');
|
|
});
|
|
|
|
it('models phase-2 business prefix gateway matching and landing rewrites', () => {
|
|
expect(schema).toContain('model BusinessPrefix');
|
|
expect(schema).toContain('model CustomerGatewayIp');
|
|
expect(schema).toContain('model CustomerGatewayBusinessPrefix');
|
|
expect(schema).toContain('model CustomerGatewayCallerPrefix');
|
|
expect(schema).toContain('model VendorGatewayCallerRewrite');
|
|
expect(schema).toContain('enum CustomerGatewayCallerMatchMode');
|
|
expect(schema).toContain('enum CustomerGatewayCalleeMatchMode');
|
|
expect(businessPrefixMigration).toContain('`billing_cycle_sec` INTEGER NOT NULL DEFAULT 60');
|
|
expect(businessPrefixMigration).toContain('`landing_callee_prefix` VARCHAR(64) NULL');
|
|
expect(businessPrefixMigration).toContain('`raw_callee` VARCHAR(64) NULL');
|
|
expect(businessPrefixMigration).toContain('`landing_caller` VARCHAR(64) NULL');
|
|
expect(businessPrefixMigration).toContain('CREATE INDEX `raw_cdrs_business_prefix_id_started_at_idx`');
|
|
});
|
|
|
|
it('models audit columns and outbox publishing state', () => {
|
|
expect(schema).toContain('createdAt');
|
|
expect(schema).toContain('updatedAt');
|
|
expect(schema).toContain('version');
|
|
expect(schema).toContain('model OutboxEvent');
|
|
expect(schema).toContain('enum OutboxStatus');
|
|
});
|
|
|
|
it('stores refresh sessions as revocable token digests', () => {
|
|
expect(schema).toContain('model UserSession');
|
|
expect(authMigration).toContain('`refresh_token_hash` CHAR(64) NOT NULL');
|
|
expect(authMigration).toContain('UNIQUE INDEX `user_sessions_refresh_token_hash_key`');
|
|
expect(authMigration).toContain('`revoked_at` DATETIME(3) NULL');
|
|
expect(authMigration).toContain('`rotated_from_id` VARCHAR(40) NULL');
|
|
});
|
|
});
|