@postxl/generator 0.57.1 → 0.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generator.js +7 -3
- package/dist/generators/indices/selectors.generator.d.ts +1 -1
- package/dist/generators/indices/selectors.generator.js +5 -11
- package/dist/generators/models/admin.page.generator.js +1 -1
- package/dist/generators/models/react.generator/library.generator.js +2 -2
- package/dist/generators/models/react.generator/lookup.generator.js +18 -41
- package/dist/generators/models/react.generator/modals.generator.js +8 -8
- package/dist/lib/meta.js +5 -5
- package/dist/lib/schema/schema.d.ts +2 -2
- package/package.json +2 -2
package/dist/generator.js
CHANGED
|
@@ -89,7 +89,7 @@ const CONFIG_SCHEMA = zod_1.z
|
|
|
89
89
|
.object({
|
|
90
90
|
pathToDataLib: zod_1.z.string().optional(),
|
|
91
91
|
pathToDbLib: zod_1.z.string().optional(),
|
|
92
|
-
|
|
92
|
+
pathToPlaywright: zod_1.z.string().optional(),
|
|
93
93
|
pathToE2ELib: zod_1.z.string().optional(),
|
|
94
94
|
pathToImportExport: zod_1.z.string().optional(),
|
|
95
95
|
pathToActions: zod_1.z.string().optional(),
|
|
@@ -114,8 +114,8 @@ const CONFIG_SCHEMA = zod_1.z
|
|
|
114
114
|
return {
|
|
115
115
|
paths: {
|
|
116
116
|
dataLibPath: (0, types_1.toPath)(s.pathToDataLib || './backend/libs/data/src/'),
|
|
117
|
+
playwrightPath: (0, types_1.toPath)(s.pathToPlaywright || './e2e/'),
|
|
117
118
|
dbLibPath: (0, types_1.toPath)(s.pathToDbLib || './backend/libs/db/src/'),
|
|
118
|
-
cypressPath: (0, types_1.toPath)(s.pathToCypress || './e2e/cypress/'),
|
|
119
119
|
e2eLibPath: (0, types_1.toPath)(s.pathToE2ELib || './backend/libs/e2e/src/'),
|
|
120
120
|
importExportPath: (0, types_1.toPath)(s.pathToImportExport || './backend/libs/import-export/src/'),
|
|
121
121
|
actionsPath: (0, types_1.toPath)(s.pathToActions || './backend/libs/actions/src/'),
|
|
@@ -173,6 +173,7 @@ function generate({ models, enums, config, prismaClientPath, logger, }) {
|
|
|
173
173
|
// which files were not generated in the last run.
|
|
174
174
|
opts: { clean: true },
|
|
175
175
|
});
|
|
176
|
+
const gitignore = lock_1.GitIgnoreUtils.getGitignore(root);
|
|
176
177
|
const generated = new vfs_1.ExtendedVirtualFS();
|
|
177
178
|
// Generate Models
|
|
178
179
|
for (const model of models) {
|
|
@@ -333,7 +334,10 @@ function generate({ models, enums, config, prismaClientPath, logger, }) {
|
|
|
333
334
|
if (FORCE_ENV) {
|
|
334
335
|
console.debug('Forcing regeneration of all files due to POSTXL_FORCE_REWRITE=true!');
|
|
335
336
|
}
|
|
336
|
-
const changes = yield vfs.flush(process.cwd(), GENERATOR_NAMESPACE, {
|
|
337
|
+
const changes = yield vfs.flush(process.cwd(), GENERATOR_NAMESPACE, {
|
|
338
|
+
force: config.force || FORCE_ENV,
|
|
339
|
+
gitIgnoredFiles: gitignore === null || gitignore === void 0 ? void 0 : gitignore.entries,
|
|
340
|
+
});
|
|
337
341
|
const log = lock_1.ConsoleUtils.getFilesChangelog(changes.filter((c) => c.status !== 'skipped'));
|
|
338
342
|
console.info(log);
|
|
339
343
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Generates list of component selectors for
|
|
2
|
+
* Generates list of component selectors for E2E tests.
|
|
3
3
|
*
|
|
4
4
|
* Note: This generator does not need the models or meta data passed in.
|
|
5
5
|
* Instead it uses the SelectorCollector singleton that already collected all ids during the generation process of the individual models.
|
|
@@ -11,7 +11,7 @@ const HARDCODED_IDS = [
|
|
|
11
11
|
'confirmationModal-buttons-cancel',
|
|
12
12
|
];
|
|
13
13
|
/**
|
|
14
|
-
* Generates list of component selectors for
|
|
14
|
+
* Generates list of component selectors for E2E tests.
|
|
15
15
|
*
|
|
16
16
|
* Note: This generator does not need the models or meta data passed in.
|
|
17
17
|
* Instead it uses the SelectorCollector singleton that already collected all ids during the generation process of the individual models.
|
|
@@ -22,9 +22,10 @@ function generateSelectors() {
|
|
|
22
22
|
const object = {};
|
|
23
23
|
const ids = [...HARDCODED_IDS, ...collectedIds];
|
|
24
24
|
ids.sort();
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
for (const id of ids) {
|
|
26
|
+
const keys = id.split('-');
|
|
27
|
+
extendObject(object, keys, `[data-test-id=${id}]`);
|
|
28
|
+
}
|
|
28
29
|
const selectors = JSON.stringify(object, null, 2);
|
|
29
30
|
return /* ts */ `
|
|
30
31
|
export const SELECTORS =
|
|
@@ -32,13 +33,6 @@ function generateSelectors() {
|
|
|
32
33
|
`;
|
|
33
34
|
}
|
|
34
35
|
exports.generateSelectors = generateSelectors;
|
|
35
|
-
/**
|
|
36
|
-
* Converts an id like `post-create-name` to a nested object like `{post: {create: {name: '[data-cy=post-create-name]'}}}`.
|
|
37
|
-
*/
|
|
38
|
-
function addCypressSelectorToNestedObject({ object, id, }) {
|
|
39
|
-
const keys = id.split('-');
|
|
40
|
-
extendObject(object, keys, `[data-cy=${id}]`);
|
|
41
|
-
}
|
|
42
36
|
/**
|
|
43
37
|
* Recursively traverses the keys and adds the value to the object in a nested way.
|
|
44
38
|
* E.g. `{object, keys: ['post', 'create', 'name'], value}` will extend `object` with `{post: {create: {name: value}}}`.
|
|
@@ -44,7 +44,7 @@ export default function Admin${meta.internalSingularNameCapitalized}Page() {
|
|
|
44
44
|
<Spacer key="Spacer" />
|
|
45
45
|
|
|
46
46
|
<ActionWrapper key="GlobalFilter">
|
|
47
|
-
<Button label={t['Create']} icon="plus" fill="fill"
|
|
47
|
+
<Button label={t['Create']} icon="plus" fill="fill" __e2e_selector__="indexPage-buttons-create" onClick={() => setIsCreateModalOpen(true)}/>
|
|
48
48
|
</ActionWrapper>
|
|
49
49
|
</ActionsBarWrapper>
|
|
50
50
|
</Header>
|
|
@@ -61,13 +61,13 @@ function generateModelLibraryComponents({ model, meta }) {
|
|
|
61
61
|
label: 'Edit',
|
|
62
62
|
icon: 'pencil-on-paper',
|
|
63
63
|
onClick: () => setIsEditModalOpen(true),
|
|
64
|
-
|
|
64
|
+
__e2e_action_selector__: "${selectorCollector.idFor('edit', { typePrefix: 'actions' })}",
|
|
65
65
|
},
|
|
66
66
|
{
|
|
67
67
|
label: 'Delete',
|
|
68
68
|
icon: 'trash',
|
|
69
69
|
onClick: () => setIsDeleteModalOpen(true),
|
|
70
|
-
|
|
70
|
+
__e2e_action_selector__: "${selectorCollector.idFor('delete', { typePrefix: 'actions' })}",
|
|
71
71
|
},
|
|
72
72
|
]}
|
|
73
73
|
/>
|
|
@@ -3,12 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.generateModelLookupComponents = void 0;
|
|
4
4
|
const id_collector_1 = require("../../../lib/id-collector");
|
|
5
5
|
const imports_1 = require("../../../lib/imports");
|
|
6
|
+
/**
|
|
7
|
+
* Returns a selector string that links the component to the global selectors index.
|
|
8
|
+
*/
|
|
9
|
+
function selector(meta, typePrefix, options) {
|
|
10
|
+
var _a;
|
|
11
|
+
const selectorCollector = id_collector_1.SelectorCollector.from(meta.seed.constantName + '-formComponents');
|
|
12
|
+
return selectorCollector.idFor((_a = options === null || options === void 0 ? void 0 : options.element) !== null && _a !== void 0 ? _a : '', { typePrefix });
|
|
13
|
+
}
|
|
6
14
|
/**
|
|
7
15
|
* Utility generator that generates lookup components for a given model.
|
|
8
16
|
*/
|
|
9
17
|
function generateModelLookupComponents({ model, meta }) {
|
|
10
18
|
const { react: { context, components }, } = meta;
|
|
11
|
-
const selectorCollector = id_collector_1.SelectorCollector.from(meta.seed.constantName + '-formComponents');
|
|
12
19
|
const imports = imports_1.ImportsGenerator.from(meta.react.folderPath)
|
|
13
20
|
.addImport({
|
|
14
21
|
items: [context.hookFnName],
|
|
@@ -54,10 +61,7 @@ export const ${components.forms.selectInputName} = ({
|
|
|
54
61
|
options={list}
|
|
55
62
|
${labelProp}
|
|
56
63
|
loading={!ready}
|
|
57
|
-
|
|
58
|
-
delegated.__cypress_field_selector__
|
|
59
|
-
?? "${selectorCollector.idFor('', { typePrefix: 'selectInput' })}"
|
|
60
|
-
}
|
|
64
|
+
__e2e_field_selector__="${selector(meta, 'selectInput')}"
|
|
61
65
|
{...delegated}
|
|
62
66
|
/>
|
|
63
67
|
}
|
|
@@ -71,10 +75,7 @@ export const ${components.forms.selectFieldName} = ({
|
|
|
71
75
|
options={list}
|
|
72
76
|
${labelProp}
|
|
73
77
|
loading={!ready}
|
|
74
|
-
|
|
75
|
-
delegated.__cypress_field_selector__
|
|
76
|
-
?? "${selectorCollector.idFor('', { typePrefix: 'selectField' })}"
|
|
77
|
-
}
|
|
78
|
+
__e2e_field_selector__="${selector(meta, 'selectField')}"
|
|
78
79
|
{...delegated}
|
|
79
80
|
/>
|
|
80
81
|
}
|
|
@@ -90,10 +91,7 @@ export const ${components.forms.menuSelectInputName} = ({
|
|
|
90
91
|
options={list}
|
|
91
92
|
${labelProp}
|
|
92
93
|
loading={!ready}
|
|
93
|
-
|
|
94
|
-
delegated.__cypress_options_selector__
|
|
95
|
-
?? "${selectorCollector.idFor('', { typePrefix: 'menuSelectInput' })}"
|
|
96
|
-
}
|
|
94
|
+
__e2e_options_selector__="${selector(meta, 'menuSelectInput')}"
|
|
97
95
|
{...delegated}
|
|
98
96
|
/>
|
|
99
97
|
}
|
|
@@ -107,10 +105,7 @@ export const ${components.forms.menuSelectFieldName} = ({
|
|
|
107
105
|
options={list}
|
|
108
106
|
${labelProp}
|
|
109
107
|
loading={!ready}
|
|
110
|
-
|
|
111
|
-
delegated.__cypress_options_selector__
|
|
112
|
-
?? "${selectorCollector.idFor('', { typePrefix: 'menuSelectField' })}"
|
|
113
|
-
}
|
|
108
|
+
__e2e_options_selector__="${selector(meta, 'menuSelectField')}"
|
|
114
109
|
{...delegated}
|
|
115
110
|
/>
|
|
116
111
|
}
|
|
@@ -126,14 +121,8 @@ export const ${components.forms.searchInputName} = ({
|
|
|
126
121
|
options={list}
|
|
127
122
|
${labelProp}
|
|
128
123
|
loading={!ready}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
?? "${selectorCollector.idFor('field', { typePrefix: 'searchInput' })}"
|
|
132
|
-
}
|
|
133
|
-
__cypress_options_selector__={
|
|
134
|
-
delegated.__cypress_options_selector__
|
|
135
|
-
?? "${selectorCollector.idFor('options', { typePrefix: 'searchInput' })}"
|
|
136
|
-
}
|
|
124
|
+
__e2e_combobox_selector__="${selector(meta, 'searchInput', { element: 'field' })}"
|
|
125
|
+
__e2e_options_selector__="${selector(meta, 'searchInput', { element: 'options' })}"
|
|
137
126
|
{...delegated}
|
|
138
127
|
/>
|
|
139
128
|
}
|
|
@@ -147,14 +136,8 @@ export const ${components.forms.searchFieldName} = ({
|
|
|
147
136
|
options={list}
|
|
148
137
|
${labelProp}
|
|
149
138
|
loading={!ready}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
?? "${selectorCollector.idFor('field', { typePrefix: 'searchField' })}"
|
|
153
|
-
}
|
|
154
|
-
__cypress_options_selector__={
|
|
155
|
-
delegated.__cypress_options_selector__
|
|
156
|
-
?? "${selectorCollector.idFor('options', { typePrefix: 'searchField' })}"
|
|
157
|
-
}
|
|
139
|
+
__e2e_combobox_selector__="${selector(meta, 'searchField', { element: 'field' })}"
|
|
140
|
+
__e2e_options_selector__="${selector(meta, 'searchField', { element: 'options' })}"
|
|
158
141
|
{...delegated}
|
|
159
142
|
/>
|
|
160
143
|
}
|
|
@@ -169,10 +152,7 @@ export const ${components.forms.tableSelectInputName} = ({
|
|
|
169
152
|
options={list}
|
|
170
153
|
${labelProp}
|
|
171
154
|
loading={!ready}
|
|
172
|
-
|
|
173
|
-
delegated.__cypress_input_field_selector__
|
|
174
|
-
?? "${selectorCollector.idFor('', { typePrefix: 'tableSelectInput' })}"
|
|
175
|
-
}
|
|
155
|
+
__e2e_input_field_selector__="${selector(meta, 'tableSelectInput')}"
|
|
176
156
|
{...delegated}
|
|
177
157
|
/>
|
|
178
158
|
}
|
|
@@ -186,10 +166,7 @@ export const ${components.forms.tableSelectFieldName} = ({
|
|
|
186
166
|
options={list}
|
|
187
167
|
${labelProp}
|
|
188
168
|
loading={!ready}
|
|
189
|
-
|
|
190
|
-
delegated.__cypress_input_field_selector__
|
|
191
|
-
?? "${selectorCollector.idFor('', { typePrefix: 'tableSelectField' })}"
|
|
192
|
-
}
|
|
169
|
+
__e2e_input_field_selector__="${selector(meta, 'tableSelectField')}"
|
|
193
170
|
{...delegated}
|
|
194
171
|
/>
|
|
195
172
|
}
|
|
@@ -150,7 +150,7 @@ export const ${modals.createComponentName} = ({
|
|
|
150
150
|
fill="fill"
|
|
151
151
|
onClick={submitForm}
|
|
152
152
|
loading={isSubmitting}
|
|
153
|
-
|
|
153
|
+
__e2e_selector__="${selectorCollector.idFor('submit', { typePrefix: 'buttons' })}"
|
|
154
154
|
/>
|
|
155
155
|
}>
|
|
156
156
|
${getFormFieldComponents({ model, selectorCollector })}
|
|
@@ -286,7 +286,7 @@ export const ${components.modals.editComponentName} = ({
|
|
|
286
286
|
color="primary"
|
|
287
287
|
onClick={submitForm}
|
|
288
288
|
loading={isSubmitting}
|
|
289
|
-
|
|
289
|
+
__e2e_selector__="${selectorCollector.idFor('submit', { typePrefix: 'buttons' })}"
|
|
290
290
|
/>
|
|
291
291
|
}
|
|
292
292
|
>
|
|
@@ -584,7 +584,7 @@ function getFormFieldComponents({ model, selectorCollector, }) {
|
|
|
584
584
|
<Typed.TextField
|
|
585
585
|
name="${formikFieldName}"
|
|
586
586
|
placeholder="Type..."
|
|
587
|
-
|
|
587
|
+
__e2e_field_selector__="${selectorCollector.idFor(field.name, { typePrefix: 'fields' })}"
|
|
588
588
|
/>
|
|
589
589
|
</div>
|
|
590
590
|
`);
|
|
@@ -602,7 +602,7 @@ function getFormFieldComponents({ model, selectorCollector, }) {
|
|
|
602
602
|
name="${formikFieldName}"
|
|
603
603
|
placeholder="2511"
|
|
604
604
|
decimals={${decimals}}
|
|
605
|
-
|
|
605
|
+
__e2e_field_selector__="${selectorCollector.idFor(field.name, { typePrefix: 'fields' })}"
|
|
606
606
|
/>
|
|
607
607
|
</div>
|
|
608
608
|
`);
|
|
@@ -615,7 +615,7 @@ function getFormFieldComponents({ model, selectorCollector, }) {
|
|
|
615
615
|
<Typed.CheckBoxField
|
|
616
616
|
name="${formikFieldName}"
|
|
617
617
|
label="${label}"
|
|
618
|
-
|
|
618
|
+
__e2e_field_selector__="${selectorCollector.idFor(field.name, { typePrefix: 'fields' })}"
|
|
619
619
|
/>
|
|
620
620
|
</div>
|
|
621
621
|
`);
|
|
@@ -640,8 +640,8 @@ function getFormFieldComponents({ model, selectorCollector, }) {
|
|
|
640
640
|
<Typed.${refMeta.react.components.forms.searchFieldName}
|
|
641
641
|
name="${formikFieldName}"
|
|
642
642
|
placeholder="Search..."
|
|
643
|
-
|
|
644
|
-
|
|
643
|
+
__e2e_options_selector__="${selectorCollector.idFor(field.name, { typePrefix: 'options' })}"
|
|
644
|
+
__e2e_combobox_selector__="${selectorCollector.idFor(field.name, { typePrefix: 'fields' })}"
|
|
645
645
|
/>
|
|
646
646
|
</div>
|
|
647
647
|
`);
|
|
@@ -655,7 +655,7 @@ function getFormFieldComponents({ model, selectorCollector, }) {
|
|
|
655
655
|
<Typed.${enumMeta.react.selectFieldName}
|
|
656
656
|
name="${formikFieldName}"
|
|
657
657
|
placeholder="Search..."
|
|
658
|
-
|
|
658
|
+
__e2e_field_selector__="${selectorCollector.idFor(field.name, { typePrefix: 'fields' })}"
|
|
659
659
|
/>
|
|
660
660
|
</div>
|
|
661
661
|
`);
|
package/dist/lib/meta.js
CHANGED
|
@@ -154,11 +154,11 @@ function getSchemaMetadata({ config }) {
|
|
|
154
154
|
},
|
|
155
155
|
e2e: {
|
|
156
156
|
dataMocker: {
|
|
157
|
-
filePath: Types.toPath(`${config.paths.
|
|
158
|
-
stubImportPath: Types.toPath(`${config.paths.
|
|
159
|
-
stubIndexFilePath: Types.toPath(`${config.paths.
|
|
157
|
+
filePath: Types.toPath(`${config.paths.playwrightPath}support/data-mocker.class`),
|
|
158
|
+
stubImportPath: Types.toPath(`${config.paths.playwrightPath}support/stubs`),
|
|
159
|
+
stubIndexFilePath: Types.toPath(`${config.paths.playwrightPath}support/stubs/index`),
|
|
160
160
|
},
|
|
161
|
-
selectorsFilePath: Types.toPath(`${config.paths.
|
|
161
|
+
selectorsFilePath: Types.toPath(`${config.paths.playwrightPath}support/selectors`),
|
|
162
162
|
},
|
|
163
163
|
importExport: {
|
|
164
164
|
importPath: Types.toBackendModulePath(`@backend/import-export`),
|
|
@@ -311,7 +311,7 @@ function getModelMetadata({ model }) {
|
|
|
311
311
|
dataServiceIdName: Types.toVariableName(`${uncapitalized}`),
|
|
312
312
|
},
|
|
313
313
|
e2e: {
|
|
314
|
-
dataMockerStubFilePath: Types.toPath(`${config.paths.
|
|
314
|
+
dataMockerStubFilePath: Types.toPath(`${config.paths.playwrightPath}support/stubs/${camelCase}.stub`),
|
|
315
315
|
},
|
|
316
316
|
importExport: {
|
|
317
317
|
exportDataPropertyName: Types.toVariableName(`${capitalizedPlural}`),
|
|
@@ -23,9 +23,9 @@ export type SchemaConfig = {
|
|
|
23
23
|
*/
|
|
24
24
|
businessLogicPath: Types.FilePath;
|
|
25
25
|
/**
|
|
26
|
-
* Path to the directory containing
|
|
26
|
+
* Path to the directory containing Playwright project.
|
|
27
27
|
*/
|
|
28
|
-
|
|
28
|
+
playwrightPath: Types.FilePath;
|
|
29
29
|
/**
|
|
30
30
|
* Path to the directory containing e2e tests.
|
|
31
31
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@postxl/generator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.59.0",
|
|
4
4
|
"main": "./dist/generator.js",
|
|
5
5
|
"typings": "./dist/generator.d.ts",
|
|
6
6
|
"bin": {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"fast-glob": "3.2.12",
|
|
27
27
|
"remeda": "1.9.4",
|
|
28
28
|
"zod": "3.21.4",
|
|
29
|
-
"@postxl/lock": "1.
|
|
29
|
+
"@postxl/lock": "1.3.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@prisma/client": "5.8.1",
|