@bytebrand/export-cars 1.26.35 → 1.26.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bytebrand/export-cars",
3
- "version": "1.26.35",
3
+ "version": "1.26.36",
4
4
  "description": "",
5
5
  "author": "bytebrand",
6
6
  "license": "UNLICENSED",
@@ -11,7 +11,7 @@
11
11
  "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
12
12
  "lint": "eslint -c .eslintrc.js --ext .ts src/",
13
13
  "start:dev": "nest start --watch",
14
- "test": "ts-node --transpile-only test/google-feed-envkv.test.ts && ts-node --transpile-only test/google-feed-item-row.test.ts && ts-node --transpile-only test/publication-gate.test.ts && ts-node --transpile-only test/images-regression.test.ts && ts-node --transpile-only test/clean-images.test.ts && ts-node --transpile-only test/image-url-validator.test.ts && ts-node --transpile-only test/openai-image-fields.test.ts && ts-node --transpile-only test/openai-ads-mapping.test.ts && ts-node --transpile-only test/openai-ads-feed-run.test.ts && ts-node --transpile-only test/openai-ads-finance.test.ts && ts-node --transpile-only test/openai-ads-price-cap.test.ts && ts-node --transpile-only test/meinstadt-mapping.test.ts && ts-node --transpile-only test/meinstadt-feed-run.test.ts && ts-node --transpile-only test/autouncle-mapping.test.ts && ts-node --transpile-only test/autouncle-feed-run.test.ts"
14
+ "test": "ts-node --transpile-only test/google-feed-envkv.test.ts && ts-node --transpile-only test/google-feed-item-row.test.ts && ts-node --transpile-only test/publication-gate.test.ts && ts-node --transpile-only test/images-regression.test.ts && ts-node --transpile-only test/clean-images.test.ts && ts-node --transpile-only test/image-url-validator.test.ts && ts-node --transpile-only test/openai-image-fields.test.ts && ts-node --transpile-only test/openai-ads-mapping.test.ts && ts-node --transpile-only test/openai-ads-feed-run.test.ts && ts-node --transpile-only test/openai-ads-finance.test.ts && ts-node --transpile-only test/openai-ads-price-cap.test.ts && ts-node --transpile-only test/meinstadt-mapping.test.ts && ts-node --transpile-only test/meinstadt-feed-run.test.ts && ts-node --transpile-only test/autouncle-mapping.test.ts && ts-node --transpile-only test/autouncle-feed-run.test.ts && ts-node --transpile-only test/criteo-images.test.ts"
15
15
  },
16
16
  "dependencies": {
17
17
  "@bytebrand/autode-request": "^1.19.2",
@@ -28,19 +28,24 @@ export class CriteoExporter implements Exporter {
28
28
  await googleXmlBuilder.buildStart(this.configService.config.domain);
29
29
 
30
30
  const criteoTransformer = await this.moduleRef.create(CriteoTransformer);
31
+ let withoutImage = 0;
31
32
 
32
33
  await this.loaderService.process(async (chunk: FsChunkInterface) => {
33
34
  chunk.data = chunk.data.filter(car => this.carService.filterCar(car, this.rulesService.rules));
34
35
 
35
36
  for (const data of chunk.data) {
36
37
  const car = await criteoTransformer.transform(data);
37
- if (car)
38
+ if (car) {
38
39
  await googleXmlBuilder.addItem(car);
40
+ } else {
41
+ withoutImage += 1;
42
+ }
39
43
  this.carService.counter.countCar(data.images);
40
44
  }
41
45
  });
42
46
 
43
47
  await googleXmlBuilder.buildEnd();
44
48
  console.log(this.carService.counter.getCountedCars());
49
+ console.log(`criteo: ${withoutImage} cars skipped without a marketing image`);
45
50
  }
46
51
  }
@@ -20,14 +20,19 @@ export class CriteoTransformer {
20
20
  this.translator = new TranslatorExtended(dict);
21
21
  }
22
22
 
23
- async transform({ car, images }: { car: DataSchemes.Car; images: Array<any> }): Promise<CriteoXmlItem> {
23
+ // Returns null for a car without a real marketing image — such cars are not sent to Criteo
24
+ // (no noimage placeholders in the feed).
25
+ async transform({ car, images }: { car: DataSchemes.Car; images: Array<any> }): Promise<CriteoXmlItem | null> {
24
26
  const carId = toString(get(car, '_id', ''));
25
27
  const transformedImages = await this.imageService.getImages(
26
28
  car,
27
29
  images,
28
30
  this.configService.config.imageType,
29
- false,
31
+ true,
30
32
  );
33
+ if (!transformedImages[0]) {
34
+ return null;
35
+ }
31
36
 
32
37
  return {
33
38
  id: carId,
@@ -0,0 +1,54 @@
1
+ // Run: npm test (ts-node, no test framework needed)
2
+ // ADV-319: a car without a real Criteo marketing image is left out of the feed; no noimage placeholders.
3
+ import * as assert from 'node:assert/strict';
4
+ import { CriteoTransformer } from '../src/transformers/criteo.transformer';
5
+
6
+ const car: any = {
7
+ _id: '00000000-0000-4000-8000-000000000001',
8
+ mainData: { make: 'Volkswagen', model: 'Golf', condition: 'selector_condition_used', category: 'selector_category_limousine' },
9
+ price: { currentSalesPrice: 19990 },
10
+ offer: { availabilityMode: 'selector_availabilityMode_always' },
11
+ metaData: { ownerId: 'test-dealer', imagesCount: 5 },
12
+ };
13
+
14
+ const makeTransformer = (images: string[]) => {
15
+ const calls: boolean[] = [];
16
+ const imageService: any = {
17
+ getImages: async (_car: any, _images: any, _type: any, ignoreDefImages: boolean) => {
18
+ calls.push(ignoreDefImages);
19
+ return images;
20
+ },
21
+ };
22
+ const configService: any = { config: { isCriteo: true, imageType: 'marketing', domain: 'autode-dev.de' } };
23
+ return { transformer: new CriteoTransformer({} as any, configService, imageService), calls };
24
+ };
25
+
26
+ const tests: Array<[string, () => Promise<void>]> = [
27
+ ['car with a marketing image is exported with it as image_link', async () => {
28
+ const url = 'https://images.autode-dev.de/generated_images/0/0/0/00000000-0000-4000-8000-000000000001/criteo-Test.jpg';
29
+ const { transformer, calls } = makeTransformer([url]);
30
+ const item = await transformer.transform({ car, images: [] });
31
+ assert.equal(item?.image_link, url);
32
+ assert.equal(item?.id, car._id);
33
+ assert.deepEqual(calls, [true]);
34
+ }],
35
+ ['car without a marketing image is skipped and placeholders are never requested', async () => {
36
+ const { transformer, calls } = makeTransformer([]);
37
+ assert.equal(await transformer.transform({ car, images: [] }), null);
38
+ assert.deepEqual(calls, [true]);
39
+ }],
40
+ ];
41
+
42
+ (async () => {
43
+ let failed = 0;
44
+ for (const [name, fn] of tests) {
45
+ try {
46
+ await fn();
47
+ console.log(`ok ${name}`);
48
+ } catch (e) {
49
+ failed += 1;
50
+ console.error(`FAIL ${name}\n ${e.message}`);
51
+ }
52
+ }
53
+ if (failed) process.exit(1);
54
+ })();