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

Migrate ProductProjection model #738

Merged
merged 6 commits into from
Jan 14, 2025
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
5 changes: 5 additions & 0 deletions .changeset/cuddly-pillows-smash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@commercetools-test-data/product': patch
---

Added missing `obj` property to category references in the `ProductData` REST model.
5 changes: 5 additions & 0 deletions .changeset/fresh-boats-crash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@commercetools-test-data/commons': patch
---

When providing a model to the `obj` property of the `Reference` model, that one was not used at build time in the REST representation.
5 changes: 5 additions & 0 deletions .changeset/shiny-poets-cheer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@commercetools-test-data/product-projection': patch
---

Migrated the `ProductProjection` model to the new implementation patterns.
19 changes: 14 additions & 5 deletions models/commons/src/reference/transformers.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
import { Transformer } from '@commercetools-test-data/core';
import omit from 'lodash/omit';
import type { TReference, TReferenceGraphql, TReferenceRest } from './types';
import type {
TExpandedReferenceObject,
TReference,
TReferenceGraphql,
TReferenceRest,
} from './types';

const transformers = {
default: Transformer<TReference, TReference>('default', {}),
rest: Transformer<TReference, TReferenceRest>('rest', {
replaceFields: ({ fields }) => ({
...fields,
obj: omit(fields, ['typeId']),
}),
buildFields: ['obj'],
replaceFields: ({ fields }) => {
return {
...fields,
obj:
(fields.obj as TExpandedReferenceObject) || omit(fields, ['typeId']),
};
},
Comment on lines +13 to +20
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is so we can forward to the obj object all the properties we potentially have received so, in case the model was populated with a reference object, the model instance has its properties.

}),
// we do not add the expanded object ourselves
// since some fields are pure `*Ref`, e.g `channelsRef`
Expand Down
4 changes: 4 additions & 0 deletions models/commons/src/reference/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ export type TReferenceBuilder<TypeId = string> = TBuilder<TReference<TypeId>>;
export interface TReference<TypeId = string> {
typeId: TypeId;
id: string;
// This is a temporary think. We will be migrating this model to the
// new implementation patterns as a follow-up whih will make this unncecessary.
// eslint-disable-next-line @typescript-eslint/no-explicit-any
obj?: any;
}

export type TExpandedReferenceObject<TypeId = string> = {
Expand Down
23 changes: 10 additions & 13 deletions models/product-projection/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,21 @@ $ pnpm add -D @commercetools-test-data/product-projection

```ts
import {
ProductProjection,
type TProductProjection,
type TProductProjectionRest,
type TProductProjectionGraphql,
ProductProjectionRest,
ProductProjectionGraphql,
} from '@commercetools-test-data/product-projection';

const productProjection =
ProductProjection.random().build<TProductProjection>();

// For REST entities
const productProjectionRest =
ProductProjection.random().buildRest<TProductProjectionRest>();
const productProjectionRest = ProductProjectionRest.random().build();

// For Graphql entities
const productProjectionGraphql =
ProductProjection.random().buildGraphql<TProductProjectionGraphql>();
const productProjectionGraphql = ProductProjectionGraphql.random().build();

// Presets
const happyCowProductProjection = ProductProjection.presets;
happyCowMilkProductProjection().build<TProductProjection>();
const happyCowProductProjectionRest = ProductProjectionRest.presets
.happyCowMilk()
.build();
const happyCowProductProjectionGraphql = ProductProjectionGraphql.presets
.happyCowMilk()
.build();
```
1 change: 1 addition & 0 deletions models/product-projection/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"@commercetools-test-data/category": "10.11.2",
"@commercetools-test-data/commons": "10.11.2",
"@commercetools-test-data/core": "10.11.2",
"@commercetools-test-data/graphql-types": "10.11.2",
"@commercetools-test-data/product": "10.11.2",
"@commercetools-test-data/product-type": "10.11.2",
"@commercetools-test-data/state": "10.11.2",
Expand Down
197 changes: 59 additions & 138 deletions models/product-projection/src/builder.spec.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
/* eslint-disable jest/no-disabled-tests */
/* eslint-disable jest/valid-title */
import { Category } from '@commercetools-test-data/category';
import { LocalizedString, Reference } from '@commercetools-test-data/commons';
import { LocalizedString } from '@commercetools-test-data/commons';
import { createBuilderSpec } from '@commercetools-test-data/core/test-utils';
import { ProductVariant } from '@commercetools-test-data/product';
import { ProductType } from '@commercetools-test-data/product-type';
import {
TProductProjection,
TProductProjectionGraphql,
TProductProjectionRest,
} from './types';
import { State } from '@commercetools-test-data/state';
import { TaxCategory } from '@commercetools-test-data/tax-category';
import { TProductProjectionGraphql, TProductProjectionRest } from './types';
import * as ProductProjection from './index';

describe('builder', () => {
Expand All @@ -27,99 +25,9 @@ describe('builder', () => {
]);

it(
...createBuilderSpec<TProductProjection, TProductProjection>(
'default',
ProductProjection.random(),
expect.objectContaining({
id: expect.any(String),
version: expect.any(Number),
key: expect.any(String),
productType: expect.objectContaining({
id: expect.any(String),
key: expect.any(String),
version: expect.any(Number),
createdAt: expect.any(String),
createdBy: expect.objectContaining({
customer: expect.objectContaining({ typeId: 'customer' }),
}),
lastModifiedAt: expect.any(String),
lastModifiedBy: expect.objectContaining({
customer: expect.objectContaining({ typeId: 'customer' }),
}),
name: expect.any(String),
description: expect.any(String),
attributes: expect.arrayContaining([
expect.objectContaining({
type: expect.objectContaining({ name: expect.any(String) }),
name: expect.any(String),
label: expect.objectContaining({
de: expect.any(String),
en: expect.any(String),
fr: expect.any(String),
}),
isRequired: expect.any(Boolean),
attributeConstraint: expect.any(String),
inputTip: expect.objectContaining({
de: expect.any(String),
en: expect.any(String),
fr: expect.any(String),
}),
inputHint: expect.any(String),
isSearchable: expect.any(Boolean),
}),
]),
}),
name: expectedGeneralLocalizedString,
description: expectedGeneralLocalizedString,
slug: expectedGeneralLocalizedString,
categories: [],
categoryOrderHints: null,
metaTitle: null,
metaDescription: null,
metaKeywords: null,
searchKeywords: [],
hasStagedChanges: expect.any(Boolean),
published: expect.any(Boolean),
masterVariant: expect.objectContaining({
key: expect.any(String),
sku: expect.any(String),
prices: expect.arrayContaining([
expect.objectContaining({
value: expect.any(Object),
}),
]),
price: null,
images: expect.arrayContaining([
expect.objectContaining({
url: expect.any(String),
}),
]),
attributes: expect.arrayContaining([
expect.objectContaining({
name: expect.any(String),
}),
]),
assets: expect.arrayContaining([]),
availability: null,
isMatchingVariant: expect.any(Boolean),
scopedPrice: null,
scopedPriceDiscounted: null,
}),
variants: [],
taxCategory: null,
state: null,
createdAt: expect.any(String),
lastModifiedAt: expect.any(String),
reviewRatingStatistics: null,
priceMode: null,
})
)
);

it(
...createBuilderSpec<TProductProjection, TProductProjectionRest>(
...createBuilderSpec<TProductProjectionRest, TProductProjectionRest>(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the default type test as we don't have it anymore.

'rest',
ProductProjection.random(),
ProductProjection.ProductProjectionRest.random(),
expect.objectContaining({
id: expect.any(String),
version: expect.any(Number),
Expand Down Expand Up @@ -199,9 +107,9 @@ describe('builder', () => {
);

it(
...createBuilderSpec<TProductProjection, TProductProjectionGraphql>(
...createBuilderSpec<TProductProjectionGraphql, TProductProjectionGraphql>(
'graphql',
ProductProjection.random(),
ProductProjection.ProductProjectionGraphql.random(),
expect.objectContaining({
id: expect.any(String),
version: expect.any(Number),
Expand All @@ -225,8 +133,11 @@ describe('builder', () => {
categories: [],
categoryOrderHints: [],
metaTitle: null,
metaTitleAllLocales: null,
metaDescription: null,
metaDescriptionAllLocales: null,
metaKeywords: null,
metaKeywordsAllLocales: null,
searchKeywords: [],
hasStagedChanges: expect.any(Boolean),
published: expect.any(Boolean),
Expand All @@ -236,47 +147,55 @@ describe('builder', () => {
sku: expect.any(String),
}),
variants: [],
taxCategory: undefined,
state: undefined,
taxCategory: null,
state: null,
createdAt: expect.any(String),
lastModifiedAt: expect.any(String),
reviewRatingStatistics: undefined,
priceMode: null,
reviewRatingStatistics: null,
})
)
);

it('should allow customization', () => {
const productProjectionMock = ProductProjection.presets
.happyCowMilkProductProjection()
.categories([
Category.random()
.id('category-id')
.name(LocalizedString.presets.empty().en('category-name')),
])
.categoryOrderHints({
'category-1': '0.4',
})
.id('happy-cow-milk-id')
.key('happy-cow-milk-key')
.metaKeywords(LocalizedString.presets.empty().en('happy'))
.priceMode('Embedded')
.productType(ProductType.presets.milk().id('product-type-id'))
.reviewRatingStatistics({
averageRating: 3.12345,
highestRating: 4.9,
lowestRating: 2.1,
count: 25,
ratingsDistribution: {},
})
.searchKeywords({
en: [{ text: 'product search keyword' }],
})
.state(Reference.presets.stateReference())
.taxCategory(Reference.presets.taxCategoryReference())
.variants([ProductVariant.random().key('alternative-variant-key')])
.version(222)
.buildGraphql<TProductProjectionGraphql>();
const productProjectionMock =
ProductProjection.ProductProjectionGraphql.presets
.happyCowMilk()
.categories([
Category.random()
.id('category-id')
.name(LocalizedString.presets.empty().en('category-name')),
])
.categoryOrderHints([
{
__typename: 'CategoryOrderHintProductSearch',
categoryId: 'category-1',
orderHint: '0.4',
},
])
.id('happy-cow-milk-id')
.key('happy-cow-milk-key')
.metaKeywordsAllLocales(LocalizedString.presets.empty().en('happy'))
.productType(ProductType.presets.milk().id('product-type-id'))
.reviewRatingStatistics({
averageRating: 3.12345,
highestRating: 4.9,
lowestRating: 2.1,
count: 25,
ratingsDistribution: {},
__typename: 'ReviewRatingStatistics',
})
.searchKeywords([
{
__typename: 'SearchKeywordsProductSearch',
locale: 'en',
searchKeywords: [{ text: 'product search keyword' }],
},
])
.state(State.random().id('state-id'))
.taxCategory(TaxCategory.random().id('tax-category-id'))
.variants([ProductVariant.random().key('alternative-variant-key')])
.version(222)
.buildGraphql<TProductProjectionGraphql>();

const expectedLocalizedName = expect.arrayContaining([
expect.objectContaining({
Expand Down Expand Up @@ -312,7 +231,7 @@ describe('builder', () => {
{
categoryId: 'category-1',
orderHint: '0.4',
__typename: 'CategoryOrderHint',
__typename: 'CategoryOrderHintProductSearch',
},
]),
categoriesRef: expect.arrayContaining([
Expand All @@ -339,13 +258,13 @@ describe('builder', () => {
expect.objectContaining({
locale: 'en',
value: 'happy',
__typename: 'LocalizedString',
}),
]),
metaTitle: 'Happy Cow Milk',
metaTitleAllLocales: expectedLocalizedName,
name: 'Happy Cow Milk',
nameAllLocales: expectedLocalizedName,
priceMode: 'Embedded',
productType: expect.objectContaining({
__typename: 'ProductTypeDefinition',
name: 'Milk Product Type',
Expand Down Expand Up @@ -384,18 +303,20 @@ describe('builder', () => {
}),
]),
state: expect.objectContaining({
id: 'product-type-id',
id: 'state-id',
__typename: 'State',
}),
stateRef: expect.objectContaining({
id: 'state-id',
typeId: 'state',
__typename: 'Reference',
}),
taxCategory: expect.objectContaining({
id: 'product-type-id',
id: 'tax-category-id',
__typename: 'TaxCategory',
}),
taxCategoryRef: expect.objectContaining({
id: 'tax-category-id',
typeId: 'tax-category',
__typename: 'Reference',
}),
Expand Down
15 changes: 0 additions & 15 deletions models/product-projection/src/builder.ts

This file was deleted.

Loading
Loading