import assert from 'node:assert/strict'; import test from 'node:test'; import type { ParseRestClient } from '../src/db/parse-rest.client.js'; import { ParseRestCompetitorSyncService } from '../src/modules/domestic-voc/services/parse-rest-competitor-sync.service.js'; import type { GatewayRequestClient } from '../src/modules/domestic-voc/services/jd-sync.service.js'; import type { ParseRestVocRepository } from '../src/modules/saas-platform/parse-rest-voc.repository.js'; test('competitor sync creates mapped placeholders and persists returned products as competitors', async () => { const placeholders: string[] = []; const products: Array<{ productId: string; role: string }> = []; const client = { async findAll() { return [ { competitorProductId: 'c1', competitorBrand: 'Brand A', category: 'Category' }, { competitorProductId: 'c1', competitorBrand: 'Brand A', category: 'Category' }, { competitorProductId: 'c2', competitorBrand: 'Brand B', category: 'Category' }, ]; }, async findOne() { return null; }, } as unknown as ParseRestClient; const repository = { async ensureCompetitorProduct(input: { productId: string }) { placeholders.push(input.productId); }, async upsertProduct(_workspaceId: string, product: { productId: string; role: string }) { products.push({ productId: product.productId, role: product.role }); }, } as unknown as ParseRestVocRepository; const gateway: GatewayRequestClient = { async request(_path, init) { const productId = String(init?.params?.itemId); return { code: 200, data: { code: 200, data: { item: { itemId: productId, itemName: `Product ${productId}` } } } } as never; }, }; const result = await new ParseRestCompetitorSyncService(client, repository, gateway).sync({ workspaceId: 'demashi', platform: 'jd', concurrency: 2, }); assert.deepEqual(placeholders.sort(), ['c1', 'c2']); assert.deepEqual(products.sort((left, right) => left.productId.localeCompare(right.productId)), [ { productId: 'c1', role: 'competitor' }, { productId: 'c2', role: 'competitor' }, ]); assert.deepEqual(result, { total: 2, placeholders: 2, succeeded: 2, skipped: 0, failed: 0, failedProductIds: [], }); });