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 reviewProducts: Array<{ productId: string; count: number }> = []; 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; }, async count() { return 0; }, } 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 }); }, async upsertReviews(_workspaceId: string, _platform: string, productId: string, reviews: unknown[]) { reviewProducts.push({ productId, count: reviews.length }); return reviews.length; }, } as unknown as ParseRestVocRepository; const gateway: GatewayRequestClient = { async request(path, init) { const productId = String(init?.params?.itemId); if (path.includes('comments')) { return { data: { data: { data: [{ commentId: `review-${productId}`, commentData: `Review ${productId}`, commentScore: '5', commentDate: '2026-07-24 10:00:00', }], pageInfo: { maxPage: 1, nowPage: 1 } } } } as never; } 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, includeReviews: true, }); 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(reviewProducts.sort((left, right) => left.productId.localeCompare(right.productId)), [ { productId: 'c1', count: 1 }, { productId: 'c2', count: 1 }, ]); assert.deepEqual(result, { total: 2, placeholders: 2, succeeded: 2, skipped: 0, failed: 0, failedProductIds: [], reviewProductsRequested: 2, reviewProductsSucceeded: 2, reviewProductsSkipped: 0, reviewProductsFailed: 0, reviewsUpserted: 2, failedReviewProductIds: [], }); });