cabloy 5.1.141 → 5.1.142
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/.cabloy-version +1 -1
- package/.github/workflows/playwright-e2e.yml +2 -2
- package/CHANGELOG.md +21 -0
- package/cabloy-docs/frontend/form-guide.md +47 -0
- package/cabloy-docs/frontend/markdown-guide.md +50 -17
- package/cabloy-docs/frontend/route-alias-guide.md +20 -0
- package/cabloy-docs/frontend/scripts.md +9 -11
- package/cabloy-docs/frontend/zova-form-under-the-hood.md +25 -0
- package/cabloy-docs/fullstack/parallel-worktree-environment.md +1 -1
- package/cabloy-docs/fullstack/quickstart.md +5 -4
- package/cabloy-docs/reference/repo-scripts.md +29 -42
- package/e2e/config/playwright.config.ts +34 -0
- package/e2e/scripts/e2e.ts +2 -27
- package/e2e/scripts/runE2e.ts +62 -0
- package/e2e/scripts/runE2eArgs.test.ts +75 -0
- package/e2e/scripts/runE2eArgs.ts +158 -0
- package/e2e/specs/{a-commerce/commerce.spec.ts → a-commerce.spec.ts} +361 -30
- package/e2e/specs/{cabloy-basic/account.spec.ts → account.spec.ts} +1 -2
- package/oxlint.config.ts +3 -0
- package/package.json +3 -9
- package/scripts/upgrade.ts +63 -68
- package/vona/packages-utils/lint/package.json +1 -1
- package/vona/packages-utils/lint/src/oxc/lint.ts +1 -1
- package/vona/packages-utils/lint/src/oxc/lintVue.ts +1 -1
- package/vona/pnpm-lock.yaml +41 -41
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/dto/refundRecoveryView.tsx +7 -2
- package/vona/src/suite/a-commerce/modules/commerce-trade/src/service/order.ts +31 -15
- package/vona/src/suite/a-home/modules/home-user/package.json +1 -0
- package/vona/src/suite/a-home/modules/home-user/src/service/account.ts +15 -2
- package/vona/src/suite/a-home/modules/home-user/test/accountActivation.test.ts +34 -4
- package/vona/src/suite-vendor/a-cabloy/modules/a-markdown/package.json +2 -1
- package/vona/src/suite-vendor/a-cabloy/modules/a-markdown/src/.metadata/index.ts +26 -0
- package/vona/src/suite-vendor/a-cabloy/modules/a-markdown/src/bean/imageScene.markdown.ts +13 -0
- package/vona/src/suite-vendor/a-cabloy/package.json +2 -2
- package/vona/src/suite-vendor/a-pay/modules/a-pay/package.json +1 -1
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/providerOperation.ts +23 -0
- package/vona/src/suite-vendor/a-pay/modules/a-pay/src/service/refundOperation.ts +7 -0
- package/vona/src/suite-vendor/a-pay/modules/pay-mock/package.json +1 -1
- package/vona/src/suite-vendor/a-pay/modules/pay-paypal/package.json +1 -1
- package/vona/src/suite-vendor/a-pay/modules/pay-stripe/package.json +1 -1
- package/vona/src/suite-vendor/a-pay/package.json +5 -5
- package/zova/packages-utils/zova-jsx/package.json +2 -2
- package/zova/packages-zova/zova/package.json +3 -3
- package/zova/packages-zova/zova-core/package.json +1 -1
- package/zova/packages-zova/zova-core/src/bean/resource/locale/type.ts +1 -0
- package/zova/pnpm-lock.yaml +63 -18
- package/zova/src/front/config/config/config.cabloyBasicWeb.ts +3 -1
- package/zova/src/front/config/config/config.cabloyCommerce.ts +4 -2
- package/zova/src/suite/a-commerce/modules/commerce-member/src/page/address/controller.tsx +64 -63
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/api/openapi/types.ts +6 -1
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/component/tableCellActionRefund/controller.tsx +413 -134
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/config/locale/en-us.ts +76 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/config/locale/zh-cn.ts +67 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/model/order.ts +1 -0
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/cart/controller.tsx +1 -1
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/checkout/controller.tsx +7 -7
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/order/controller.tsx +46 -9
- package/zova/src/suite/a-commerce/modules/commerce-trade/src/page/payment/controller.tsx +50 -30
- package/zova/src/suite/cabloy-basic/modules/basic-captcha/src/component/formFieldCaptcha/controller.tsx +6 -2
- package/zova/src/suite/cabloy-basic/modules/basic-image/src/component/formFieldImage/controller.tsx +9 -15
- package/zova/src/suite/cabloy-basic/modules/basic-markdown/package.json +10 -2
- package/zova/src/suite/cabloy-basic/modules/basic-markdown/src/.metadata/index.ts +11 -2
- package/zova/src/suite/cabloy-basic/modules/basic-markdown/src/.metadata/locales.ts +7 -0
- package/zova/src/suite/cabloy-basic/modules/basic-markdown/src/component/formFieldMarkdown/controller.tsx +723 -5
- package/zova/src/suite/cabloy-basic/modules/basic-markdown/src/component/formFieldMarkdown/render.tsx +461 -2
- package/zova/src/suite/cabloy-basic/modules/basic-markdown/src/config/locale/en-us.ts +59 -0
- package/zova/src/suite/cabloy-basic/modules/basic-markdown/src/config/locale/zh-cn.ts +59 -0
- package/zova/src/suite/cabloy-basic/modules/basic-markdown/src/index.ts +1 -0
- package/zova/src/suite/cabloy-basic/modules/basic-markdown/src/lib/codeBlockLanguages.ts +42 -0
- package/zova/src/suite/cabloy-basic/modules/basic-markdown/src/lib/richTextContentStyle.ts +20 -0
- package/zova/src/suite/cabloy-basic/modules/basic-markdown/test/lib/codeBlockLanguages.test.ts +25 -0
- package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/package.json +1 -1
- package/zova/src/suite-vendor/a-cabloy/modules/rest-resource/src/model/resource.ts +1 -0
- package/zova/src/suite-vendor/a-cabloy/package.json +2 -2
- package/zova/src/suite-vendor/a-pay/modules/a-pay/package.json +1 -1
- package/zova/src/suite-vendor/a-pay/modules/a-pay/src/component/paymentNextAction/controller.tsx +26 -12
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/cli/openapi.config.ts +1 -1
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/package.json +1 -1
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/api/payMockMockPayment.ts +26 -0
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/apiSchema/payMockMockPayment.ts +8 -1
- package/zova/src/suite-vendor/a-pay/modules/pay-mock/src/model/payMockPayment.ts +13 -1
- package/zova/src/suite-vendor/a-pay/package.json +3 -3
- package/zova/src/suite-vendor/a-zova/modules/a-form/package.json +1 -1
- package/zova/src/suite-vendor/a-zova/modules/a-form/src/component/formField/controller.tsx +2 -0
- package/zova/src/suite-vendor/a-zova/modules/a-form/src/types/formField.ts +7 -6
- package/zova/src/suite-vendor/a-zova/modules/a-zova/package.json +2 -2
- package/zova/src/suite-vendor/a-zova/package.json +3 -3
- package/e2e/config/playwright.basic.config.ts +0 -3
- package/e2e/config/playwright.commerce.config.ts +0 -3
- package/e2e/config/playwright.shared.config.ts +0 -38
- package/e2e/scripts/testE2eClean.ts +0 -56
- /package/e2e/specs/{cabloy-basic/basic.spec.ts → cabloy-basic.spec.ts} +0 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { mkdtempSync, mkdirSync, writeFileSync, rmSync } from 'node:fs';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { resolve } from 'node:path';
|
|
5
|
+
import test from 'node:test';
|
|
6
|
+
|
|
7
|
+
import { buildTagGrep, combineGreps, parseE2eArgs } from './runE2eArgs.ts';
|
|
8
|
+
|
|
9
|
+
function withSpecs(callback: (specsDir: string) => void): void {
|
|
10
|
+
const tempDir = mkdtempSync(resolve(tmpdir(), 'cabloy-e2e-args-'));
|
|
11
|
+
try {
|
|
12
|
+
const specsDir = resolve(tempDir, 'specs');
|
|
13
|
+
mkdirSync(specsDir);
|
|
14
|
+
for (const name of ['account', 'a-commerce', 'cabloy-basic']) {
|
|
15
|
+
writeFileSync(resolve(specsDir, `${name}.spec.ts`), '');
|
|
16
|
+
}
|
|
17
|
+
callback(specsDir);
|
|
18
|
+
} finally {
|
|
19
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
test('parses mode, multiple specs, and repeatable tags', () => {
|
|
24
|
+
withSpecs(specsDir => {
|
|
25
|
+
assert.deepEqual(
|
|
26
|
+
parseE2eArgs(
|
|
27
|
+
['--clean', 'cabloy-basic', 'account', '--tag', '@web', '--tag=@smoke'],
|
|
28
|
+
specsDir,
|
|
29
|
+
),
|
|
30
|
+
{
|
|
31
|
+
mode: 'clean',
|
|
32
|
+
specNames: ['cabloy-basic', 'account'],
|
|
33
|
+
playwrightArgs: [],
|
|
34
|
+
tags: ['@web', '@smoke'],
|
|
35
|
+
},
|
|
36
|
+
);
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('allows no spec names and forwards Playwright filters', () => {
|
|
41
|
+
withSpecs(specsDir => {
|
|
42
|
+
assert.deepEqual(parseE2eArgs(['--fast', '--grep', '@flow'], specsDir), {
|
|
43
|
+
mode: 'fast',
|
|
44
|
+
specNames: [],
|
|
45
|
+
playwrightArgs: ['--grep', '@flow'],
|
|
46
|
+
tags: [],
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test('rejects invalid or unknown specs and managed config overrides', () => {
|
|
52
|
+
withSpecs(specsDir => {
|
|
53
|
+
assert.throws(() => parseE2eArgs(['--fast', '../account'], specsDir), /Invalid E2E spec name/);
|
|
54
|
+
assert.throws(() => parseE2eArgs(['--fast', 'missing'], specsDir), /Unknown E2E spec/);
|
|
55
|
+
assert.throws(
|
|
56
|
+
() => parseE2eArgs(['--fast', '--config', 'other.ts'], specsDir),
|
|
57
|
+
/manages --config/,
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test('requires exactly one run mode', () => {
|
|
63
|
+
withSpecs(specsDir => {
|
|
64
|
+
assert.throws(() => parseE2eArgs(['account'], specsDir), /Missing E2E mode/);
|
|
65
|
+
assert.throws(() => parseE2eArgs(['--clean', '--fast'], specsDir), /exactly one/);
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test('combines tags with an existing grep expression', () => {
|
|
70
|
+
assert.equal(buildTagGrep(['@web', '@smoke']), '(?=.*@web)(?=.*@smoke)');
|
|
71
|
+
assert.deepEqual(combineGreps(['--grep', '@flow'], ['@web', '@smoke']), [
|
|
72
|
+
'--grep',
|
|
73
|
+
'(?=.*(?:@flow))(?=.*@web)(?=.*@smoke)',
|
|
74
|
+
]);
|
|
75
|
+
});
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
|
|
4
|
+
export type E2eRunMode = 'clean' | 'fast';
|
|
5
|
+
|
|
6
|
+
export type ParsedE2eArgs = {
|
|
7
|
+
mode: E2eRunMode;
|
|
8
|
+
specNames: string[];
|
|
9
|
+
playwrightArgs: string[];
|
|
10
|
+
tags: string[];
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const SPEC_NAME_PATTERN = /^[a-z0-9][\w-]*$/i;
|
|
14
|
+
const VALUE_OPTIONS = new Set([
|
|
15
|
+
'--browser',
|
|
16
|
+
'--config',
|
|
17
|
+
'--grep',
|
|
18
|
+
'--grep-invert',
|
|
19
|
+
'--global-timeout',
|
|
20
|
+
'--ignore-snapshots',
|
|
21
|
+
'--last-failed',
|
|
22
|
+
'--max-failures',
|
|
23
|
+
'--output',
|
|
24
|
+
'--pass-with-no-tests',
|
|
25
|
+
'--project',
|
|
26
|
+
'--repeat-each',
|
|
27
|
+
'--reporter',
|
|
28
|
+
'--shard',
|
|
29
|
+
'--timeout',
|
|
30
|
+
'--trace',
|
|
31
|
+
'--workers',
|
|
32
|
+
]);
|
|
33
|
+
|
|
34
|
+
function optionName(arg: string): string {
|
|
35
|
+
const equalsIndex = arg.indexOf('=');
|
|
36
|
+
return equalsIndex === -1 ? arg : arg.slice(0, equalsIndex);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function escapeRegExp(value: string): string {
|
|
40
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function buildTagGrep(tags: string[]): string | undefined {
|
|
44
|
+
if (tags.length === 0) return undefined;
|
|
45
|
+
return tags.map(tag => `(?=.*${escapeRegExp(tag)})`).join('');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function parseE2eArgs(args: string[], specsDir: string): ParsedE2eArgs {
|
|
49
|
+
let mode: E2eRunMode | undefined;
|
|
50
|
+
const remainingArgs: string[] = [];
|
|
51
|
+
|
|
52
|
+
for (const arg of args) {
|
|
53
|
+
if (arg === '--clean' || arg === '--fast') {
|
|
54
|
+
if (mode && mode !== arg.slice(2)) {
|
|
55
|
+
throw new Error('Choose exactly one E2E mode: --clean or --fast.');
|
|
56
|
+
}
|
|
57
|
+
if (mode === arg.slice(2)) {
|
|
58
|
+
throw new Error(`E2E mode ${arg} was provided more than once.`);
|
|
59
|
+
}
|
|
60
|
+
mode = arg.slice(2) as E2eRunMode;
|
|
61
|
+
} else {
|
|
62
|
+
remainingArgs.push(arg);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!mode) {
|
|
67
|
+
throw new Error('Missing E2E mode. Use --clean or --fast.');
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const specNames: string[] = [];
|
|
71
|
+
const playwrightArgs: string[] = [];
|
|
72
|
+
const tags: string[] = [];
|
|
73
|
+
let optionStarted = false;
|
|
74
|
+
let pendingValueFor: string | undefined;
|
|
75
|
+
|
|
76
|
+
for (let index = 0; index < remainingArgs.length; index++) {
|
|
77
|
+
const arg = remainingArgs[index];
|
|
78
|
+
|
|
79
|
+
if (pendingValueFor) {
|
|
80
|
+
if (!arg || arg.startsWith('--')) {
|
|
81
|
+
throw new Error(`Missing value for ${pendingValueFor}.`);
|
|
82
|
+
}
|
|
83
|
+
if (pendingValueFor === '--tag') {
|
|
84
|
+
tags.push(arg);
|
|
85
|
+
} else {
|
|
86
|
+
playwrightArgs.push(arg);
|
|
87
|
+
}
|
|
88
|
+
pendingValueFor = undefined;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (arg === '--tag' || arg.startsWith('--tag=')) {
|
|
93
|
+
optionStarted = true;
|
|
94
|
+
const value = arg.slice('--tag'.length).replace(/^=/, '');
|
|
95
|
+
if (value) {
|
|
96
|
+
tags.push(value);
|
|
97
|
+
} else {
|
|
98
|
+
pendingValueFor = '--tag';
|
|
99
|
+
}
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (arg === '--config' || arg.startsWith('--config=')) {
|
|
104
|
+
throw new Error('The E2E runner manages --config; do not provide it.');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
if (!optionStarted && !arg.startsWith('-')) {
|
|
108
|
+
if (!SPEC_NAME_PATTERN.test(arg)) {
|
|
109
|
+
throw new Error(`Invalid E2E spec name: ${arg}`);
|
|
110
|
+
}
|
|
111
|
+
const specPath = resolve(specsDir, `${arg}.spec.ts`);
|
|
112
|
+
if (!existsSync(specPath)) {
|
|
113
|
+
throw new Error(`Unknown E2E spec: ${arg} (expected ${specPath}).`);
|
|
114
|
+
}
|
|
115
|
+
specNames.push(arg);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (arg.startsWith('-')) {
|
|
120
|
+
optionStarted = true;
|
|
121
|
+
const name = optionName(arg);
|
|
122
|
+
if (VALUE_OPTIONS.has(name) && !arg.includes('=')) {
|
|
123
|
+
pendingValueFor = name;
|
|
124
|
+
}
|
|
125
|
+
playwrightArgs.push(arg);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
playwrightArgs.push(arg);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (pendingValueFor) {
|
|
133
|
+
throw new Error(`Missing value for ${pendingValueFor}.`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return { mode, specNames, playwrightArgs, tags };
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function combineGreps(args: string[], tags: string[]): string[] {
|
|
140
|
+
const tagGrep = buildTagGrep(tags);
|
|
141
|
+
if (!tagGrep) return args;
|
|
142
|
+
|
|
143
|
+
const result = [...args];
|
|
144
|
+
const grepIndex = result.findIndex(arg => arg === '--grep' || arg.startsWith('--grep='));
|
|
145
|
+
if (grepIndex === -1) {
|
|
146
|
+
result.push('--grep', tagGrep);
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (result[grepIndex].includes('=')) {
|
|
151
|
+
const [name, value] = result[grepIndex].split(/=(.*)/s, 2);
|
|
152
|
+
result[grepIndex] = `${name}=(?=.*(?:${value}))${tagGrep}`;
|
|
153
|
+
} else {
|
|
154
|
+
const value = result[grepIndex + 1];
|
|
155
|
+
result[grepIndex + 1] = `(?=.*(?:${value}))${tagGrep}`;
|
|
156
|
+
}
|
|
157
|
+
return result;
|
|
158
|
+
}
|