From 1555d6ba8668ac06c982d6083b8c366d8c2c515e Mon Sep 17 00:00:00 2001 From: Florian Robel Date: Fri, 6 Dec 2024 10:32:21 +0100 Subject: [PATCH] feat: add analytics assignment and creation of sales channel analytics --- src/services/TestDataService.ts | 129 ++++++++++++++++-- src/types/ShopwareTypes.ts | 4 + tests/TestDataService/TestDataService.spec.ts | 9 ++ 3 files changed, 132 insertions(+), 10 deletions(-) diff --git a/src/services/TestDataService.ts b/src/services/TestDataService.ts index d90b9768..4e316ef8 100644 --- a/src/services/TestDataService.ts +++ b/src/services/TestDataService.ts @@ -28,9 +28,15 @@ import type { Country, CustomerGroup, SystemConfig, + SalesChannelAnalytics, } from '../types/ShopwareTypes'; import { expect } from '@playwright/test'; +export interface SalesChannelRecord { + salesChannelId: string; + field: string; +} + export interface CreatedRecord { resource: string; payload: Record; @@ -91,7 +97,7 @@ export class TestDataService { * * @private */ - private highPriorityEntities = ['order', 'product', 'landing_page']; + private highPriorityEntities = ['order', 'product', 'landing_page', 'sales_channel_currency', 'sales_channel_country']; /** * A registry of all created records. @@ -100,6 +106,13 @@ export class TestDataService { */ private createdRecords: CreatedRecord[] = []; + /** + * A registry of all created sales channel records. + * + * @private + */ + private createdSalesChannelRecords: SalesChannelRecord[] = []; + constructor(AdminApiClient: AdminApiContext, IdProvider: IdProvider, options: DataServiceOptions) { this.AdminApiClient = AdminApiClient; @@ -882,6 +895,30 @@ export class TestDataService { return systemConfigEntry; } + /** + * Creates a random sales channel analytics entity + * + * @param overrides - Specific data overrides that will be applied to the sales channel analytics data struct. + */ + async createSalesChannelAnalytics( + overrides: Partial = {}, + ): Promise { + + const basicSalesChannelAnalyticsStruct = this.getSalesChannelAnalyticsStruct(overrides); + + + const response = await this.AdminApiClient.post('sales-channel-analytics?_response=detail', { + data: basicSalesChannelAnalyticsStruct, + }); + expect(response.ok()).toBeTruthy(); + + const { data: salesChannelAnalytics } = (await response.json()) as { data: SalesChannelAnalytics }; + + this.addCreatedRecord('sales_channel_analytics', salesChannelAnalytics.id); + + return salesChannelAnalytics; + } + /** * Assigns a media resource as the download of a digital product. * @@ -1065,13 +1102,13 @@ export class TestDataService { const syncSalesChannelResponse = await this.AdminApiClient.post('./_action/sync', { data: { - 'write-sales-channel': { - entity: 'sales_channel', + 'write-sales-channel-currency': { + entity: 'sales_channel_currency', action: 'upsert', payload: [ { - id: salesChannelId, - currencies: [{ id: currencyId }], + salesChannelId: salesChannelId, + currencyId: currencyId, }, ], }, @@ -1081,6 +1118,39 @@ export class TestDataService { const { data: salesChannel } = await syncSalesChannelResponse.json(); + this.addCreatedRecord('sales_channel_currency', {salesChannelId: salesChannelId, currencyId: currencyId}) + + return salesChannel; + } + + /** + * Assigns a sales channel analytics entity to a sales channel. + * + * @param salesChannelId - The uuid of the sales channel. + * @param salesChannelAnalyticsId - The uuid of the sales channel analytics entity. + */ + async assignSalesChannelAnalytics(salesChannelId: string, salesChannelAnalyticsId: string) { + + const syncSalesChannelResponse = await this.AdminApiClient.post('./_action/sync', { + data: { + 'write-sales-channel-analytics': { + entity: 'sales_channel_analytics', + action: 'upsert', + payload: [ + { + salesChannel: { id: salesChannelId }, + id: salesChannelAnalyticsId, + }, + ], + }, + }, + }); + expect(syncSalesChannelResponse.ok()).toBeTruthy(); + + const { data: salesChannel } = (await syncSalesChannelResponse.json()) as { data: SalesChannel}; + + this.addCreatedSalesChannelRecord(salesChannelId, 'analyticsId'); + return salesChannel; } @@ -1094,13 +1164,13 @@ export class TestDataService { const syncSalesChannelResponse = await this.AdminApiClient.post('./_action/sync', { data: { - 'write-sales-channel': { - entity: 'sales_channel', + 'write-sales-channel-country': { + entity: 'sales_channel_country', action: 'upsert', payload: [ { - id: salesChannelId, - countries: [{ id: countryId }], + salesChannelId: salesChannelId, + countryId: countryId, }, ], }, @@ -1110,6 +1180,8 @@ export class TestDataService { const { data: salesChannel } = await syncSalesChannelResponse.json(); + this.addCreatedRecord('sales_channel_country', { salesChannelId: salesChannelId, countryId: countryId }); + return salesChannel; } @@ -1414,6 +1486,17 @@ export class TestDataService { } } + /** + * Adds a sales channel related property to the registry of created sales channel records. + * The property added to the registry will be overridden with null value by the cleanup call. + * + * @param salesChannelId - The sales channel id where the property pair is located + * @param field - The database field which has to be overridden + */ + addCreatedSalesChannelRecord(salesChannelId: string, field: string) { + this.createdSalesChannelRecords.push({ salesChannelId: salesChannelId, field: field }); + } + /** * Set the configuration of automated data clean up. * If set to "true" the data service will delete all entities created by it. @@ -1432,8 +1515,20 @@ export class TestDataService { return null; } - const priorityDeleteOperations: Record = {}; const deleteOperations: Record = {}; + const priorityDeleteOperations: Record = {}; + + if(this.createdSalesChannelRecords) { + for (const salesChannelRecord of this.createdSalesChannelRecords) { + const salesChannelResponse = await this.AdminApiClient.patch(`sales-channel/${salesChannelRecord.salesChannelId}`, { + data: { + [salesChannelRecord.field]: null, + }, + }); + expect(salesChannelResponse.ok()).toBeTruthy(); + } + } + this.createdRecords.forEach((record) => { if (this.highPriorityEntities.includes(record.resource)) { @@ -2237,6 +2332,20 @@ export class TestDataService { return Object.assign({}, basicCustomerGroup, overrides); } + getSalesChannelAnalyticsStruct(overrides: Partial = {}): Partial { + const salesChannelAnalyticsUuid = this.IdProvider.getIdPair().uuid; + const trackingId = this.IdProvider.getIdPair().id; + + const basicSalesChannelAnalyticsStruct = { + id: salesChannelAnalyticsUuid, + trackingId: trackingId, + active: true, + trackOrders: false, + anonymizeIp: true, + }; + return Object.assign({}, basicSalesChannelAnalyticsStruct, overrides); + } + async clearCaches() { await this.AdminApiClient.delete('_action/cache'); } diff --git a/src/types/ShopwareTypes.ts b/src/types/ShopwareTypes.ts index e59f628a..bd4b3889 100644 --- a/src/types/ShopwareTypes.ts +++ b/src/types/ShopwareTypes.ts @@ -190,6 +190,10 @@ export type CustomerGroup = components['schemas']['CustomerGroup'] & { id: string, }; +export type SalesChannelAnalytics = components['schemas']['SalesChannelAnalytics'] & { + id: string, +}; + export interface RegistrationData { salutation: string; firstName: string; diff --git a/tests/TestDataService/TestDataService.spec.ts b/tests/TestDataService/TestDataService.spec.ts index a85282f5..750d07ae 100644 --- a/tests/TestDataService/TestDataService.spec.ts +++ b/tests/TestDataService/TestDataService.spec.ts @@ -13,6 +13,7 @@ import { Category, APIResponse, SystemConfig, + SalesChannelAnalytics, } from '../../src'; test('Data Service', async ({ @@ -90,6 +91,9 @@ test('Data Service', async ({ expect(systemConfigEntry.configurationKey).toEqual('test.random.foo'); expect(systemConfigEntry.configurationValue).toEqual(true); + const salesChannelAnalytics = await TestDataService.createSalesChannelAnalytics({ active: false }); + expect(salesChannelAnalytics.active).toEqual(false); + // Test data clean-up with deactivated cleansing process TestDataService.setCleanUp(false); const cleanUpFalseResponse = await TestDataService.cleanUp(); @@ -143,6 +147,10 @@ test('Data Service', async ({ const { data: databaseSystemConfigEntry } = (await systemConfigEntryResponse.json()) as { data: SystemConfig }; expect(databaseSystemConfigEntry.id).toBe(systemConfigEntry.id); + const salesChannelAnalyticsResponse = await AdminApiContext.get(`./sales-channel-analytics/${salesChannelAnalytics.id}?_response=detail`); + const { data: databaseSalesChannelAnalytics } = (await salesChannelAnalyticsResponse.json()) as { data: SalesChannelAnalytics }; + expect(databaseSalesChannelAnalytics.id).toBe(salesChannelAnalytics.id); + // Test data clean-up with activated cleansing process TestDataService.setCleanUp(true); const cleanUpResponse = await TestDataService.cleanUp() as APIResponse; @@ -164,4 +172,5 @@ test('Data Service', async ({ expect(cleanUp['deleted']['product_manufacturer']).toBeDefined(); expect(cleanUp['deleted']['cms_page']).toBeDefined(); expect(cleanUp['deleted']['system_config']).toBeDefined(); + expect(cleanUp['deleted']['sales_channel_analytics']).toBeDefined(); });