Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: pseventbus v4 categories #366

Merged
merged 4 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ docker-phpunit-cov: tools/vendor
.PHONY: phpstan docker-phpstan
phpstan: tools/vendor prestashop/prestashop-${PS_VERSION}
phpstan analyse --memory-limit=-1 --configuration=./tests/phpstan/phpstan-local.neon;
docker-phpstan:
docker-phpstan: tools/vendor
@$(call in_docker,/usr/bin/phpstan,analyse --memory-limit=-1 --configuration=./tests/phpstan/phpstan-docker.neon)

define COMMENT
Expand Down
4 changes: 4 additions & 0 deletions config/common/new-repository.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,3 +46,7 @@ services:
PrestaShop\Module\PsEventbus\Repository\NewRepository\ProductCarrierRepository:
class: PrestaShop\Module\PsEventbus\Repository\NewRepository\ProductCarrierRepository
public: true

PrestaShop\Module\PsEventbus\Repository\NewRepository\CategoryRepository:
class: PrestaShop\Module\PsEventbus\Repository\NewRepository\CategoryRepository
public: true
6 changes: 0 additions & 6 deletions config/common/repository.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,6 @@ services:
arguments:
- '@=service("prestashop.adapter.legacy.context").getContext()'

PrestaShop\Module\PsEventbus\Repository\CategoryRepository:
class: PrestaShop\Module\PsEventbus\Repository\CategoryRepository
public: true
arguments:
- '@=service("prestashop.adapter.legacy.context").getContext()'

PrestaShop\Module\PsEventbus\Repository\CustomerRepository:
class: PrestaShop\Module\PsEventbus\Repository\CustomerRepository
public: true
Expand Down
10 changes: 8 additions & 2 deletions config/front/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -119,9 +119,9 @@ services:
class: PrestaShop\Module\PsEventbus\Service\ShopContent\ProductsService
public: true
arguments:
- '@PrestaShop\Module\PsEventbus\Repository\NewRepository\ProductRepository'
- '@PrestaShop\Module\PsEventbus\Repository\CategoryRepository'
- '@PrestaShop\Module\PsEventbus\Repository\NewRepository\ProductRepository'
- '@PrestaShop\Module\PsEventbus\Repository\LanguageRepository'
- '@PrestaShop\Module\PsEventbus\Service\ShopContent\CategoriesService'
- '@PrestaShop\Module\PsEventbus\Formatter\ArrayFormatter'

PrestaShop\Module\PsEventbus\Service\ShopContent\ProductBundlesService:
Expand All @@ -141,3 +141,9 @@ services:
public: true
arguments:
- '@PrestaShop\Module\PsEventbus\Repository\NewRepository\ProductCarrierRepository'

PrestaShop\Module\PsEventbus\Service\ShopContent\CategoriesService:
class: PrestaShop\Module\PsEventbus\Service\ShopContent\CategoriesService
public: true
arguments:
- '@PrestaShop\Module\PsEventbus\Repository\NewRepository\CategoryRepository'
1 change: 1 addition & 0 deletions e2e/src/fixtures/1.6/cart_rules.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
1 change: 1 addition & 0 deletions e2e/src/fixtures/1.7/cart_rules.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
1 change: 1 addition & 0 deletions e2e/src/fixtures/8/cart_rules.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
1 change: 1 addition & 0 deletions e2e/src/fixtures/9/cart_rules.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
[]
154 changes: 54 additions & 100 deletions e2e/src/full-sync.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as matchers from "jest-extended";
import { dumpUploadData, logAxiosError } from "./helpers/log-helper";
import axios, { AxiosError } from "axios";
import { doFullSync, probe, PsEventbusSyncUpload } from "./helpers/mock-probe";
import { from, lastValueFrom, toArray, withLatestFrom } from "rxjs";
import { lastValueFrom, toArray, withLatestFrom } from "rxjs";
import {
generatePredictableModuleId,
loadFixture,
Expand All @@ -17,13 +17,6 @@ expect.extend(matchers);
// these ShopContent will be excluded from the following test suite
const EXCLUDED_API: ShopContent[] = ["taxonomies" as ShopContent];

// FIXME : these api can't send anything to the mock api because the database is empty from the factory
const MISSING_TEST_DATA: ShopContent[] = [
"cart-rules" as ShopContent,
"translations" as ShopContent,
"wishlists" as ShopContent,
];

// these fields change from test run to test run, so we replace them with a matcher to only ensure the type and format are correct
const isDateString = (val) =>
val ? expect(val).toBeDateString() : expect(val).toBeNull();
Expand Down Expand Up @@ -70,8 +63,6 @@ describe("Full Sync", () => {
// TODO : apiGoogleTaxonomies requires an additional module to be present : devise a specific test setup for this endpoint
it.skip(`${shoContent} should accept full sync`, async () => {});

it.skip(`${shoContent} should upload to collector`, async () => {});

it(`${shoContent} should reject full sync when ps_facebook is not installed`, async () => {
// arrange
const url = `${testConfig.prestashopUrl}/index.php?fc=module&module=ps_eventbus&controller=apiFront&is_e2e=1&shop_content=${shoContent}&limit=5&full=1&job_id=${jobId}`;
Expand Down Expand Up @@ -128,98 +119,61 @@ describe("Full Sync", () => {
});
});

if (MISSING_TEST_DATA.includes(shopContent)) {
it.skip(`${shopContent} should upload to collector`, () => {});
} else {
it.skip(`${shopContent} should upload to collector`, async () => {
// arrange
const url = `${testConfig.prestashopUrl}/index.php?fc=module&module=ps_eventbus&controller=apiFront&is_e2e=1&shop_content=${shopContent}&limit=5&full=1&job_id=${jobId}`;
const message$ = probe({ url: `/upload/${jobId}` });

const callId = { call_id: Math.random().toString(36).substring(2, 11) };

// act
const request$ = from(
axios.post(url, callId, {
headers: {
Host: testConfig.prestaShopHostHeader,
"Content-Type": "application/x-www-form-urlencoded", // for compat PHP 5.6
},
}),
);

const probeMessage = await lastValueFrom(
request$.pipe(withLatestFrom(message$, (_, message) => message)),
);

// assert
expect(probeMessage).toBeTruthy();
expect(probeMessage.method).toBe("POST");
expect(probeMessage.headers).toMatchObject({
"full-sync-requested": "1",
});
});
}

if (MISSING_TEST_DATA.includes(shopContent)) {
it.skip(`${shopContent} should upload complete dataset to collector`, () => {});
} else {
it(`${shopContent} should upload complete dataset collector`, async () => {
// arrange
const response$ = doFullSync(jobId, controller, { timeout: 4000 });
const message$ = probe({ url: `/upload/${jobId}` }, { timeout: 4000 });

// this combines each response from ps_eventbus to the last request captured by the probe.
// it works because ps_eventbus sends a response after calling our mock collector server
// if ps_eventbus doesn't need to call the collector, the probe completes without value after its timeout
const messages = await lastValueFrom(
response$.pipe(
withLatestFrom(message$, (_, message) => message.body.file),
toArray(),
),
);

const syncedData: PsEventbusSyncUpload[] = messages.flat();

// dump data for easier debugging or updating fixtures
let processedData = syncedData as PsEventbusSyncUpload[];
if (testConfig.dumpFullSyncData) {
await dumpUploadData(syncedData, shopContent);
}

const fixture = await loadFixture(shopContent);
it(`${shopContent} should upload complete dataset collector`, async () => {
// arrange
const response$ = doFullSync(jobId, shopContent, { timeout: 4000 });
const message$ = probe({ url: `/upload/${jobId}` }, { timeout: 4000 });

// this combines each response from ps_eventbus to the last request captured by the probe.
// it works because ps_eventbus sends a response after calling our mock collector server
// if ps_eventbus doesn't need to call the collector, the probe completes without value after its timeout
const messages = await lastValueFrom(
response$.pipe(
withLatestFrom(message$, (_, message) => message.body.file),
toArray(),
),
);

const syncedData: PsEventbusSyncUpload[] = messages.flat();

// dump data for easier debugging or updating fixtures
let processedData = syncedData as PsEventbusSyncUpload[];
if (testConfig.dumpFullSyncData) {
await dumpUploadData(syncedData, shopContent);
}

const fixture = await loadFixture(shopContent);

// we need to process fixtures and data returned from ps_eventbus to make them easier to compare
let processedFixture = fixture;
if (shopContent === ("modules" as ShopContent)) {
processedData = generatePredictableModuleId(processedData);
processedFixture = generatePredictableModuleId(processedFixture);
}
processedData = omitProperties(
processedData,
Object.keys(specialFieldAssert),
);
processedData = sortUploadData(processedData);
processedFixture = omitProperties(
processedFixture,
Object.keys(specialFieldAssert),
);
processedFixture = sortUploadData(processedFixture);

// we need to process fixtures and data returned from ps_eventbus to make them easier to compare
let processedFixture = fixture;
if (shopContent === ("modules" as ShopContent)) {
processedData = generatePredictableModuleId(processedData);
processedFixture = generatePredictableModuleId(processedFixture);
}
processedData = omitProperties(
processedData,
Object.keys(specialFieldAssert),
);
processedData = sortUploadData(processedData);
processedFixture = omitProperties(
processedFixture,
Object.keys(specialFieldAssert),
);
processedFixture = sortUploadData(processedFixture);

// assert
expect(processedData).toMatchObject(processedFixture);

// assert special field using custom matcher
for (const data of processedData) {
for (const specialFieldName of Object.keys(specialFieldAssert)) {
if (data.properties[specialFieldName] !== undefined) {
specialFieldAssert[specialFieldName](
data.properties[specialFieldName],
);
}
// assert
expect(processedData).toMatchObject(processedFixture);

// assert special field using custom matcher
for (const data of processedData) {
for (const specialFieldName of Object.keys(specialFieldAssert)) {
if (data.properties[specialFieldName] !== undefined) {
specialFieldAssert[specialFieldName](
data.properties[specialFieldName],
);
}
}
});
}
}
});
});
});
2 changes: 1 addition & 1 deletion e2e/src/helpers/mock-probe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export function probe(

return socket.pipe(
filter((message) => (match ? R.whereEq(match, message) : true)),
takeUntil(timer(options.timeout)),
takeUntil(timer(options.timeout))
);
}

Expand Down
1 change: 1 addition & 0 deletions e2e/src/helpers/shop-contents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export const shopContentMapping = {
product_bundles: "product-bundles",
product_suppliers: "product-suppliers",
product_carriers: "product-carriers",
categories: "categories"
} as const;

type ShopContentMapping = typeof shopContentMapping;
Expand Down
40 changes: 0 additions & 40 deletions src/Decorator/CategoryDecorator.php

This file was deleted.

Loading
Loading