| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119 |
- import assert from 'node:assert/strict';
- import type { AddressInfo } from 'node:net';
- import test from 'node:test';
- import { createLocalDemoApp } from '../src/local-app.js';
- import type { DomesticDataset, DomesticMetricSummary } from '../src/types/domestic-dataset.js';
- const emptyMetrics: DomesticMetricSummary = {
- gmv: 0,
- soldUnits: 0,
- transactionOrders: 0,
- transactionCustomers: 0,
- impressions: 0,
- clicks: 0,
- views: 0,
- visitors: 0,
- cartUnits: 0,
- orderAmount: 0,
- orderUnits: 0,
- orderCount: 0,
- refundAmount: 0,
- refundUnits: 0,
- refundOrders: 0,
- conversionRate: 0,
- clickThroughRate: 0,
- averageUnitPrice: 0,
- refundToGmvRate: 0,
- };
- const dataset: DomesticDataset = {
- schemaVersion: 1,
- generatedAt: '2026-07-23T00:00:00.000Z',
- caseName: 'Demashi',
- platform: 'jd',
- source: {
- sourceFile: 'demashi-summary.json',
- sourceHash: 'test',
- sheets: [],
- dateRange: { start: '2026-07-01', end: '2026-07-23' },
- },
- summary: {
- metricRows: 0,
- metricProducts: 1,
- mappingRows: 0,
- relations: 0,
- uniqueCompetitorProducts: 0,
- category2Count: 0,
- category3Count: 0,
- reviewCount: 0,
- },
- dailyTotals: [],
- products: [{
- platform: 'jd',
- productId: '11266507445',
- productKey: 'jd:11266507445',
- asin: '11266507445',
- role: 'own',
- brand: 'Demashi',
- title: 'Local demo product',
- model: '',
- category1: '',
- category2: '',
- category3: '',
- source: 'excel',
- relationCount: 0,
- summary: emptyMetrics,
- trend: [],
- }],
- mappingGroups: [],
- relations: [],
- reviews: [],
- quality: {
- orphanMappings: [],
- mappingsWithoutCompetitor: [],
- brandWithoutProductId: [],
- },
- };
- test('local demo serves a snapshot and queryable completed sync jobs without a database', async () => {
- const app = createLocalDemoApp({ dataset, corsOrigins: ['http://localhost:4200'] });
- const server = await new Promise<ReturnType<typeof app.listen>>((resolve) => {
- const listening = app.listen(0, '127.0.0.1', () => resolve(listening));
- });
- try {
- const address = server.address() as AddressInfo;
- const baseUrl = `http://127.0.0.1:${address.port}`;
- const health = await fetch(`${baseUrl}/health`);
- assert.equal(health.status, 200);
- const healthBody = await health.json() as {
- mode: string;
- database: string;
- dataset: { products: number; reviews: number };
- };
- assert.equal(healthBody.mode, 'local-demo');
- assert.equal(healthBody.database, 'deferred');
- assert.deepEqual(healthBody.dataset, { caseName: 'Demashi', platform: 'jd', products: 1, reviews: 0 });
- const snapshot = await fetch(`${baseUrl}/api/domestic-voc/snapshot?workspaceId=demashi&platform=jd`);
- assert.equal(snapshot.status, 200);
- assert.equal((await snapshot.json() as DomesticDataset).products[0]?.productId, '11266507445');
- const syncResponse = await fetch(`${baseUrl}/api/domestic-voc/sync`, {
- method: 'POST',
- headers: { 'Content-Type': 'application/json', 'Idempotency-Key': 'local-demo-sync-11266507445' },
- body: JSON.stringify({ productIds: ['11266507445'] }),
- });
- assert.equal(syncResponse.status, 202);
- const syncBody = await syncResponse.json() as { job: { id: string; status: string; progress: number } };
- assert.equal(syncBody.job.status, 'completed');
- assert.equal(syncBody.job.progress, 100);
- const jobResponse = await fetch(`${baseUrl}/api/domestic-voc/jobs/${syncBody.job.id}`);
- assert.equal(jobResponse.status, 200);
- assert.equal((await jobResponse.json() as { job: { status: string } }).job.status, 'completed');
- } finally {
- await new Promise<void>((resolve, reject) => server.close((error) => error ? reject(error) : resolve()));
- }
- });
|