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

[FEC-38] Fix ProductProjection model reference properties #638

Closed
wants to merge 27 commits into from
Closed
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
9a34027
refactor(product-projection): working on ref attributes
CarlosCortizasCT Aug 19, 2024
260729f
Merge branch 'main' of https://github.com/commercetools/test-data
CarlosCortizasCT Aug 19, 2024
4024e50
refactor(reference): allow obj property customization
CarlosCortizasCT Aug 20, 2024
fd92185
fix(product-projection): fix references properties management
CarlosCortizasCT Aug 20, 2024
1d88aff
refactor(reference): remove debug log
CarlosCortizasCT Aug 20, 2024
7104b7b
refactor: update models which have reference properties
CarlosCortizasCT Aug 20, 2024
2758868
Merge branch 'main' of https://github.com/commercetools/test-data
CarlosCortizasCT Aug 20, 2024
9828bca
Merge branch 'main' into cm-fix-product-projection-model
CarlosCortizasCT Aug 20, 2024
e7846c5
fix(product-projection): fix ts issue
CarlosCortizasCT Aug 20, 2024
5a6b6c6
Merge branch 'main' into cm-fix-product-projection-model
CarlosCortizasCT Aug 21, 2024
c93911c
chore: refresh lock file
CarlosCortizasCT Aug 21, 2024
4fbb51b
fix: fix models with reference properties
CarlosCortizasCT Aug 21, 2024
293ddaf
fix: fix models properties definitions
CarlosCortizasCT Aug 21, 2024
588369a
Merge branch 'main' of https://github.com/commercetools/test-data
CarlosCortizasCT Aug 27, 2024
95a403b
Merge branch 'main' into cm-fix-product-projection-model
CarlosCortizasCT Aug 27, 2024
a3fdb79
chore: refresh lock file
CarlosCortizasCT Aug 27, 2024
01727f5
chore: merge main branch
CarlosCortizasCT Aug 27, 2024
bce128c
fix(product): adjust models properties
CarlosCortizasCT Aug 27, 2024
9b87be5
fix(product): fix presets
CarlosCortizasCT Aug 28, 2024
996f336
fix(product): fix product-data transformer
CarlosCortizasCT Aug 28, 2024
ebd6718
fix(product-projection): fix test
CarlosCortizasCT Aug 28, 2024
32b8b40
fix(prouct): fix import
CarlosCortizasCT Aug 29, 2024
ab89bf4
Merge branch 'main' into cm-fix-product-projection-model
CarlosCortizasCT Sep 5, 2024
374d67b
chore: typescript config update
CarlosCortizasCT Sep 5, 2024
9f9a684
Merge branch 'main' into cm-fix-product-projection-model
CarlosCortizasCT Sep 23, 2024
defe86c
refactor(product-discount): add missing model
CarlosCortizasCT Sep 23, 2024
5c69a97
Merge branch 'main' into cm-fix-product-projection-model
CarlosCortizasCT Jan 7, 2025
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
8 changes: 6 additions & 2 deletions models/business-unit/src/associate/builder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ describe('builder', () => {
]),
customer: expect.objectContaining({
id: expect.any(String),
typeId: 'customer',
obj: expect.objectContaining({
id: expect.any(String),
}),
}),
})
)
Expand All @@ -66,10 +70,10 @@ describe('builder', () => {
]),
customer: expect.objectContaining({
id: expect.any(String),
typeId: 'customer',
__typename: 'Reference',
email: expect.any(String),
}),
customerRef: expect.objectContaining({
id: expect.any(String),
typeId: 'customer',
__typename: 'Reference',
}),
Expand Down
36 changes: 20 additions & 16 deletions models/business-unit/src/associate/transformers.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {
type TReference,
type TReferenceGraphql,
Reference,
} from '@commercetools-test-data/commons';
import { Transformer } from '@commercetools-test-data/core';
import { buildField, Transformer } from '@commercetools-test-data/core';
import { Customer, TCustomerGraphql } from '@commercetools-test-data/customer';
import type {
TAssociateDefault,
TAssociateRest,
Expand All @@ -16,26 +16,30 @@ const transformers = {
}),
rest: Transformer<TAssociateDefault, TAssociateRest>('rest', {
buildFields: ['associateRoleAssignments', 'customer'],
replaceFields: ({ fields }) => {
const customer: TReference<'customer'> = Reference.presets
.customerReference()
.id(fields.customer.id)
.build();
return {
...fields,
customer,
};
},
}),
graphql: Transformer<TAssociateDefault, TAssociateGraphql>('graphql', {
buildFields: ['associateRoleAssignments', 'customer'],
buildFields: ['associateRoleAssignments'],
replaceFields: ({ fields }) => {
const customerRef: TReferenceGraphql = Reference.presets
const restCustomerRef = buildField(fields.customer, 'rest');

const customerRef = Reference.presets
.customerReference()
.id(fields.customer.id)
.buildGraphql();
.id(restCustomerRef.id)
.buildGraphql<TReferenceGraphql>();

const customer = Customer.random()
.id(restCustomerRef.id)
.firstName(restCustomerRef.obj?.firstName)
.lastName(restCustomerRef.obj?.lastName)
.key(restCustomerRef.obj?.key)
.customerNumber(restCustomerRef.obj?.customerNumber)
.externalId(restCustomerRef.obj?.externalId)
.email(restCustomerRef.obj?.email || '')
.buildGraphql<TCustomerGraphql>();

return {
...fields,
customer,
customerRef,
__typename: 'Associate',
};
Expand Down
16 changes: 7 additions & 9 deletions models/business-unit/src/associate/types.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
import type {
Associate,
AssociateDraft,
Customer,
} from '@commercetools/platform-sdk';
import type { Associate, AssociateDraft } from '@commercetools/platform-sdk';
import { TReferenceGraphql } from '@commercetools-test-data/commons';
import type { TBuilder } from '@commercetools-test-data/core';
import { TCustomerGraphql } from '@commercetools-test-data/customer';

export type TAssociateDefault = Associate;

export type TAssociateDraft = AssociateDraft;
export type TAssociateDraftGraphql = TAssociateDraft;

export type TAssociateDefault = Omit<Associate, 'customer'> & {
customer: Customer;
};
export type TAssociateRest = Associate;
export type TAssociateGraphql = TAssociateDefault & {

export type TAssociateGraphql = Omit<TAssociateDefault, 'customer'> & {
customer: TCustomerGraphql;
customerRef: TReferenceGraphql | null;
__typename: 'Associate';
};
Expand Down
1 change: 1 addition & 0 deletions models/channel/src/builder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ describe('builder', () => {
),
expect.objectContaining({
__typename: 'Channel',
name: 'Food Store',
nameAllLocales: expect.arrayContaining([
expect.objectContaining({
__typename: 'LocalizedString',
Expand Down
16 changes: 14 additions & 2 deletions models/channel/src/transformers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import { LocalizedString } from '@commercetools-test-data/commons';
import {
LocalizedString,
TClientLoggingGraphql,
} from '@commercetools-test-data/commons';
import { Transformer } from '@commercetools-test-data/core';
import type { TChannel, TChannelGraphql } from './types';

Expand All @@ -23,16 +26,25 @@ const transformers = {
}),
graphql: Transformer<TChannel, TChannelGraphql>('graphql', {
buildFields: ['address', 'createdBy', 'lastModifiedBy'],
addFields: ({ fields }) => {
replaceFields: ({ fields }) => {
const nameAllLocales = LocalizedString.toLocalizedField(fields.name);
const descriptionAllLocales = LocalizedString.toLocalizedField(
fields.description
);

return {
...fields,
__typename: 'Channel',
createdBy: fields.createdBy as TClientLoggingGraphql | undefined,
lastModifiedBy: fields.lastModifiedBy as
| TClientLoggingGraphql
| undefined,
nameAllLocales,
name: LocalizedString.resolveGraphqlDefaultLocaleValue(nameAllLocales),
descriptionAllLocales,
description: LocalizedString.resolveGraphqlDefaultLocaleValue(
descriptionAllLocales
),
};
},
}),
Expand Down
16 changes: 6 additions & 10 deletions models/channel/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,15 @@ export type TChannelDraftGraphql = Omit<

export type TChannelGraphql = Omit<
TChannel,
// In GraphQL, we prefer to use `nameAllLocales` instead of `name`.
| 'name'
// In GraphQL, we prefer to use `descriptionAllLocales` instead of `description`.
| 'description'
// In GraphQL, the object shape is different.
| 'createdBy'
// In GraphQL, the object shape is different.
| 'lastModifiedBy'
// In GraphQL, these properties have different shapes.
'name' | 'description' | 'createdBy' | 'lastModifiedBy'
> & {
__typename: 'Channel';
createdBy: TClientLoggingGraphql;
lastModifiedBy: TClientLoggingGraphql;
createdBy?: TClientLoggingGraphql;
lastModifiedBy?: TClientLoggingGraphql;
name?: string;
nameAllLocales?: TLocalizedStringGraphql | null;
description?: string;
descriptionAllLocales?: TLocalizedStringGraphql | null;
};

Expand Down
2 changes: 1 addition & 1 deletion models/commons/src/localized-string/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const resolveGraphqlDefaultLocaleValue = (
const defaultLocaleName = allLocales.find(
(name) => name.locale === DEFAULT_LOCALE
);
return defaultLocaleName ? defaultLocaleName.value : allLocales[0].value;
return defaultLocaleName ? defaultLocaleName.value : allLocales[0]?.value;
};

export { resolveGraphqlDefaultLocaleValue, toLocalizedField };
58 changes: 58 additions & 0 deletions models/commons/src/reference/builder.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,32 @@
/* eslint-disable jest/no-disabled-tests */
/* eslint-disable jest/valid-title */
import {
Builder,
fake,
Generator,
Transformer,
} from '@commercetools-test-data/core';
import { createBuilderSpec } from '@commercetools-test-data/core/test-utils';
import type { TReference, TReferenceGraphql, TReferenceRest } from './types';
import * as Reference from './index';

// We use this dummy model in the customization tests.
// It is a simple model so we don't need to depend on other models.
const DummyModel = () =>
Builder<{ id: string; name: string }>({
generator: Generator<{ id: string; name: string }>({
fields: {
id: fake((f) => f.string.uuid()),
name: fake((f) => f.person.fullName()),
},
}),
transformers: {
default: Transformer('default', {}),
rest: Transformer('rest', {}),
graphql: Transformer('graphql', {}),
},
});

describe('builder', () => {
it(
...createBuilderSpec<TReference, TReference>(
Expand Down Expand Up @@ -39,4 +62,39 @@ describe('builder', () => {
}
)
);

describe('when customizing the model', () => {
const referenceMock = Reference.random()
.typeId('dummy-type')
.obj(DummyModel().id('dummy-id').name('dummy-name'));

it('should build the right rest model', () => {
const restReference = referenceMock.buildRest<TReferenceRest>();

expect(restReference).toEqual(
expect.objectContaining({
id: 'dummy-id',
typeId: 'dummy-type',
obj: {
id: 'dummy-id',
name: 'dummy-name',
},
})
);
});
it('should build the right graphql model', () => {
const graphqlReference = referenceMock.buildGraphql<TReferenceGraphql>();

expect(graphqlReference).toEqual(
expect.objectContaining({
__typename: 'Reference',
id: 'dummy-id',
typeId: 'dummy-type',
})
);
// @ts-expect-error "obj" is not defined in the graphql model
// but we want to make sure the built model does not include it
expect(graphqlReference.obj).toBeUndefined();
});
});
});
1 change: 1 addition & 0 deletions models/commons/src/reference/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const generator = Generator<TReference>({
fields: {
id: fake((f) => f.string.uuid()),
typeId: null,
obj: undefined,
},
});

Expand Down
43 changes: 33 additions & 10 deletions models/commons/src/reference/transformers.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,45 @@
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', {}),
default: Transformer<TReference, TReference>('default', {
buildFields: ['obj'],
}),
rest: Transformer<TReference, TReferenceRest>('rest', {
replaceFields: ({ fields }) => ({
...fields,
obj: omit(fields, ['typeId']),
}),
replaceFields: ({ fields }) => {
const obj = fields.obj
? fields.obj.buildRest<TExpandedReferenceObject>()
: {
id: fields.id,
};

return {
...fields,
id: obj.id,
obj,
};
},
}),
// we do not add the expanded object ourselves
// since some fields are pure `*Ref`, e.g `channelsRef`
// with no option to expand.
graphql: Transformer<TReference, TReferenceGraphql>('graphql', {
addFields: () => ({
__typename: 'Reference',
}),
replaceFields: ({ fields }) => {
const id = fields.obj
? fields.obj.buildGraphql<TExpandedReferenceObject>().id
: fields.id;

return {
id,
typeId: fields.typeId,
__typename: 'Reference',
};
},
}),
};

Expand Down
35 changes: 16 additions & 19 deletions models/commons/src/reference/types.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,37 @@
import type { TBuilder } from '@commercetools-test-data/core';

export type TReferenceBuilder<TypeId = string> = TBuilder<TReference<TypeId>>;
export type TExpandedReferenceObject = {
id: string;
version?: number;
};

export interface TReference<TypeId = string> {
typeId: TypeId;
id: string;
obj?: TBuilder<TExpandedReferenceObject>;
}

export type TExpandedReferenceObject<TypeId = string> = {
id: TReference<TypeId>['id'];
version?: number;
};

export type TCreateReferenceBuilder<TypeId = string> =
() => TReferenceBuilder<TypeId>;

export type TReferenceRest<
TypeId = string,
ExpandedObject extends TExpandedReferenceObject<TypeId> = TExpandedReferenceObject<TypeId>
> = TReference<TypeId> & {
obj: ExpandedObject;
ExpandedObject extends TExpandedReferenceObject = TExpandedReferenceObject,
> = Omit<TReference, 'obj'> & {
obj?: ExpandedObject;
};

export type TReferenceGraphql<TypeId = string> =
TExpandedReferenceObject<TypeId> & {
__typename: 'Reference';
};
export type TReferenceGraphql = Omit<TReference, 'obj'> & {
__typename: 'Reference';
};

// Draft representation
export interface TReferenceDraft<TypeId = string> {
typeId: TypeId;
id: string;
}

export type TReferenceDraftGraphql<TypeId = string> =
TExpandedReferenceObject<TypeId>;
export type TReferenceDraftGraphql = TExpandedReferenceObject;

export type TReferenceBuilder<TypeId = string> = TBuilder<TReference<TypeId>>;
export type TCreateReferenceBuilder<TypeId = string> =
() => TReferenceBuilder<TypeId>;

export type TReferenceDraftBuilder<TypeId = string> = TBuilder<
TReferenceDraft<TypeId>
Expand Down
Loading
Loading