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

Update Core helpers to support the new proposed way of writing test data models #688

Merged
merged 7 commits into from
Oct 8, 2024

Conversation

CarlosCortizasCT
Copy link
Contributor

Based on the agreements achieved in this RFC, we're now implementing (step by step) the changes required in the repository in order to support them.

We already have this PR when we add documentation about this new patterns to follow when writing test data models.

In this PR we're actually updating the core helpers so they can support the current versions of the test data models as well as the new one and also a compatibility mode where some data models need to support both at the same time.

Copy link

changeset-bot bot commented Oct 3, 2024

🦋 Changeset detected

Latest commit: 76f492e

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 46 packages
Name Type
@commercetools-test-data/standalone-price Minor
@commercetools-test-data/customer-group Minor
@commercetools-test-data/product-type Minor
@commercetools-test-data/channel Minor
@commercetools-test-data/commons Minor
@commercetools-test-data/core Minor
@commercetools-test-data/cart-discount Minor
@commercetools-test-data/customer Minor
@commercetools-test-data/order Minor
@commercetools-test-data/quote-request Minor
@commercetools-test-data/quote Minor
@commercetools-test-data/staged-quote Minor
@commercetools-test-data/product-discount Minor
@commercetools-test-data/product-projection Minor
@commercetools-test-data/product Minor
@commercetools-test-data/cart Minor
@commercetools-test-data/inventory-entry Minor
@commercetools-test-data/store Minor
@commercetools-test-data/associate-role Minor
@commercetools-test-data/attribute-group Minor
@commercetools-test-data/business-unit Minor
@commercetools-test-data/category Minor
@commercetools-test-data/custom-application Minor
@commercetools-test-data/custom-object Minor
@commercetools-test-data/custom-view Minor
@commercetools-test-data/customers-search-list-my-view Minor
@commercetools-test-data/discount-code Minor
@commercetools-test-data/discounts-custom-view Minor
@commercetools-test-data/organization Minor
@commercetools-test-data/payment Minor
@commercetools-test-data/platform-limits Minor
@commercetools-test-data/product-selection Minor
@commercetools-test-data/review Minor
@commercetools-test-data/shipping-method Minor
@commercetools-test-data/shopping-list Minor
@commercetools-test-data/state Minor
@commercetools-test-data/tax-category Minor
@commercetools-test-data/type Minor
@commercetools-test-data/user Minor
@commercetools-test-data/zone Minor
@commercetools-test-data/filter-values Minor
@commercetools-test-data/organization-extension Minor
@commercetools-test-data/project-extension Minor
@commercetools-test-data/project Minor
@commercetools-test-data/graphql-types Minor
@commercetools-test-data/utils Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@CarlosCortizasCT CarlosCortizasCT added 🚧 Status: WIP fe-chapter-rotation Tasks coming from frontend chapter work labels Oct 3, 2024
@CarlosCortizasCT CarlosCortizasCT self-assigned this Oct 3, 2024
@@ -34,8 +30,12 @@ const createState = <Model>({

return {
get: () => state,
merge: (update: Partial<Model>) => {
state = { ...state, ...update };
merge: (update: Partial<Model>, overwrite = true) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changes in this object are required so we can initialize the state with the generator result after the builder is actually built.

We need a state in the builder so chained calls to its properties can be registered but we cannot set the initial state at builder instantiation time as we don't know yet which version of the builder we're going to use at that point (this is because the compatibility mode).

This solution allows to update the state with the generator result later during the actual build call.

@@ -77,13 +86,27 @@ function PropertyBuilder<Model>(initialProps?: Partial<Model>) {
function Builder<Model>({
generator,
transformers,
type,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the new pattern, we will be receiving which representation this builder is for: rest | graphql

@@ -77,13 +86,27 @@ function PropertyBuilder<Model>(initialProps?: Partial<Model>) {
function Builder<Model>({
generator,
transformers,
type,
postBuild,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the new pattern, this is a callback used to manipulate the output of the build before it's returned to the consumer. This allows to resolve dependent properties of the data model.

@@ -77,13 +86,27 @@ function PropertyBuilder<Model>(initialProps?: Partial<Model>) {
function Builder<Model>({
generator,
transformers,
type,
postBuild,
name = 'Unknown Builder',
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 helps debugging a lot.

type,
postBuild,
name = 'Unknown Builder',
compatConfig,
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 for the compatibility mode of the new pattern where a single builder needs to support both representations.

return modelBuilder as TBuilder<TModel>;
};

const createCompatibilityBuilder = <TModel>(params: {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Helper to create the compatibility builder so current data models can be migrated to the new patterns but still (temporary) expose the same external API (backwards compatibility).

@@ -36,6 +43,21 @@ function Transformer<Model, TransformedModel>(
};
}
});
} else if (fieldsToBuild !== false) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We now build all buildable data model properties by default so we don't need to specify an array of those ones at the data model level.

Copy link
Member

Choose a reason for hiding this comment

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

Nit: Would it make sense to "invert" the logic? If some fields are NOT supposed to be built, we would need to explicitly define them.

If so, we can replace the property fieldsToBuild with something like omitFieldsToBuild.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for the suggestion 👍

I understand having this type dual is not very conventional but I found it to be the simplest solution that fulfills the requirement.
Places where we need this you would need to declare a new property with all models fields so that's why I think the current proposal is a good compromise.

Anyway, I see all the changes implemented here to be temporary. Once we migrate all the models to use the new patterns I believe we will be able to simplify things a lot. For instance, fieldsToBuild is only needed for the (now) legacy data models; new ones does not use it.

args?: TFieldBuilderArgs<OriginalModel>
): TransformedModel;
buildGraphql<TransformedModel>(
buildGraphql<TransformedModel = OriginalModel>(
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 allows for the function to return the expected type by default which works very handy with the new patterns.

@@ -6,6 +6,7 @@ import type { TCreateChannelBuilder } from './types';

const Model: TCreateChannelBuilder = () =>
Builder<Channel>({
name: 'Channel',
Copy link
Contributor Author

Choose a reason for hiding this comment

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

There are a bunch of models where I added the name in order to help debugging.

I think is better to keep them.

@@ -12,6 +12,7 @@ const transformers = {
buildFields: ['customer'],
}),
graphql: Transformer<TClientLogging, TClientLoggingGraphql>('graphql', {
buildFields: false,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since previously we needed to provide the buildFields array in order to specify which data models properties should be automatically built, omitting that property meant build no property at all.

Now that this field is not even needed, for those current cases where we don't actually want to build any property we need to explicitly return false.

@@ -287,71 +277,6 @@ describe('building', () => {
);
});

it('should build all build upon properties with callbacks', () => {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We had a feature that allowed properties updaters to provide a value based on the previous one.
Keeping this feature with the new proposal is quite hard so, since I haven't found any model in this repo using this feature, I'd like to remove it by now.

If we find any MC applications tests actually using this feature, then I'll get back to it if necessary but I would like to forget about it by now if possible.

@CarlosCortizasCT CarlosCortizasCT marked this pull request as ready for review October 3, 2024 16:29
@CarlosCortizasCT CarlosCortizasCT requested review from a team as code owners October 3, 2024 16:29
@CarlosCortizasCT CarlosCortizasCT requested review from emmenko, tdeekens and a team October 3, 2024 16:29
Copy link
Member

@emmenko emmenko left a comment

Choose a reason for hiding this comment

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

Thanks again for tackling this beast! 🙌

I think I was able to follow along with the core changes but I trust you know what you are doing 😉

Overall it looks good to me 🤗

@@ -49,12 +51,17 @@ export type TTransformerOptions<Model, TransformedModel> = {
addFields?: (args: { fields: Model }) => Partial<TransformedModel>;
removeFields?: (keyof Model)[];
replaceFields?: (args: { fields: Model }) => TransformedModel;
buildFields?: (keyof Model)[];
buildFields?: (keyof Model)[] | false;
Copy link
Member

Choose a reason for hiding this comment

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

Nit: let's add a comment to explain what false refers to and when it's supposed to be used.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added here: af759da

@@ -36,6 +43,21 @@ function Transformer<Model, TransformedModel>(
};
}
});
} else if (fieldsToBuild !== false) {
Copy link
Member

Choose a reason for hiding this comment

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

Nit: Would it make sense to "invert" the logic? If some fields are NOT supposed to be built, we would need to explicitly define them.

If so, we can replace the property fieldsToBuild with something like omitFieldsToBuild.


The main change is about the `core` package where we are introducing support for writing test data models using new implementation patterns which makes the process simpler. Also, the resulting code will be more maintainable.

You can head over [here]() for updated documentation about those new patterns.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'll update this link once the docs PR is merged.

Copy link
Contributor

@Sarah4VT Sarah4VT left a comment

Choose a reason for hiding this comment

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

This is not my area of expertise, but I didn't notice anything I would obviously change.

@CarlosCortizasCT CarlosCortizasCT merged commit 6bdcbe6 into main Oct 8, 2024
4 checks passed
@CarlosCortizasCT CarlosCortizasCT deleted the cm-fec-91 branch October 8, 2024 13:43
@ct-changesets ct-changesets bot mentioned this pull request Oct 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fe-chapter-rotation Tasks coming from frontend chapter work
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants