@ykdz/template 0.0.40 → 0.0.42

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.
Files changed (87) hide show
  1. package/node_modules/@ykdz/template-builtin-presets/dist/src/foundation.js +144 -101
  2. package/node_modules/@ykdz/template-builtin-presets/dist/src/rust-bin/definition.js +29 -4
  3. package/node_modules/@ykdz/template-builtin-presets/dist/src/shared/vue.js +11 -2
  4. package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-cli/definition.js +14 -4
  5. package/node_modules/@ykdz/template-builtin-presets/dist/src/ts-lib/definition.js +13 -0
  6. package/node_modules/@ykdz/template-builtin-presets/dist/src/vike-app/definition.js +44 -10
  7. package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-app/definition.js +4 -1
  8. package/node_modules/@ykdz/template-builtin-presets/dist/src/vue-hono-app/definition.js +19 -8
  9. package/node_modules/@ykdz/template-builtin-presets/package.json +23 -10
  10. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check-deployment-diagnostics.yml +30 -29
  11. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check-deployment.yml +8 -21
  12. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check-diagnostics.yml +21 -5
  13. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/.github/workflows/check.yml +4 -2
  14. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/AGENTS.md.template +9 -1
  15. package/node_modules/@ykdz/template-builtin-presets/templates/{shared/devcontainer/node-pnpm.Dockerfile → foundation/devcontainer/base.Dockerfile} +14 -1
  16. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/gitignore +1 -0
  17. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/pnpm-workspace.yaml +3 -0
  18. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/scripts/node-test-count-reporter.ts +31 -0
  19. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/scripts/run-rust-tests.ts +100 -0
  20. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/scripts/run-turbo-boundaries.ts +74 -0
  21. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/scripts/task-gates.ts +589 -0
  22. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/turbo-projections/database-preparation.json +17 -0
  23. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/turbo-projections/deployment.json +13 -0
  24. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/turbo-projections/rust-toolchain.json +5 -0
  25. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/turbo-projections/vue-hono-joint-e2e.json +13 -0
  26. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/turbo.json +14 -15
  27. package/node_modules/@ykdz/template-builtin-presets/templates/foundation/typescript-config/turbo.json +30 -1
  28. package/node_modules/@ykdz/template-builtin-presets/templates/rust-bin/devcontainer/rust.Dockerfile +1 -5
  29. package/node_modules/@ykdz/template-builtin-presets/templates/rust-bin/tsconfig.scripts.json +12 -0
  30. package/node_modules/@ykdz/template-builtin-presets/templates/rust-bin/turbo.json +19 -4
  31. package/node_modules/@ykdz/template-builtin-presets/templates/shared/devcontainer/github-cli.Dockerfile +1 -3
  32. package/node_modules/@ykdz/template-builtin-presets/templates/shared/vue/TESTING.md +7 -0
  33. package/node_modules/@ykdz/template-builtin-presets/templates/shared/vue/src/components/CounterButton.vue +18 -0
  34. package/node_modules/@ykdz/template-builtin-presets/templates/shared/vue/test/counter.browser.test.ts +16 -0
  35. package/node_modules/@ykdz/template-builtin-presets/templates/shared/vue/test/{app.test.ts → counter.node.test.ts} +1 -0
  36. package/node_modules/@ykdz/template-builtin-presets/templates/shared/vue/tsconfig.test.json +1 -1
  37. package/node_modules/@ykdz/template-builtin-presets/templates/shared/vue/vitest.config.ts +50 -0
  38. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/check-artifact.ts +16 -5
  39. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/release.yml +5 -2
  40. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication/turbo.json +5 -2
  41. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/publication-setup/bridge.ts +1 -1
  42. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/src/cli-command-identity.ts +0 -45
  43. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/test/e2e/run-journeys.test.ts +11 -0
  44. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/test/integration/command.test.ts +43 -39
  45. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/test/unit/cli-command-identity.test.ts +52 -52
  46. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/tsconfig.json +1 -1
  47. package/node_modules/@ykdz/template-builtin-presets/templates/ts-cli/turbo.json +58 -3
  48. package/node_modules/@ykdz/template-builtin-presets/templates/ts-lib/test/greet.test.ts +20 -0
  49. package/node_modules/@ykdz/template-builtin-presets/templates/ts-lib/tsconfig.json +1 -1
  50. package/node_modules/@ykdz/template-builtin-presets/templates/ts-lib/turbo.json +44 -1
  51. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/test/todos.test.ts +8 -11
  52. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db/turbo.json +38 -1
  53. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/db-migrations/turbo.json +44 -1
  54. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/playwright.config.ts +18 -2
  55. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/test/counter.browser.test.ts +14 -0
  56. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/tsconfig.test.json +8 -2
  57. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/turbo.json +61 -1
  58. package/node_modules/@ykdz/template-builtin-presets/templates/vike-app/web/vitest.config.ts +29 -2
  59. package/node_modules/@ykdz/template-builtin-presets/templates/vue-app/src/App.vue +2 -12
  60. package/node_modules/@ykdz/template-builtin-presets/templates/vue-app/turbo.json +60 -2
  61. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/api/test/app.test.ts +7 -6
  62. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/api/tsconfig.json +2 -7
  63. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/api/turbo.json +46 -1
  64. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/web/src/App.vue +2 -11
  65. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/web/turbo.json +57 -1
  66. package/node_modules/@ykdz/template-core/dist/ci-diagnostic-artifact.d.ts +1 -1
  67. package/node_modules/@ykdz/template-core/dist/ci-diagnostic-artifact.js +6 -3
  68. package/node_modules/@ykdz/template-core/dist/dependency-catalog.d.ts +0 -1
  69. package/node_modules/@ykdz/template-core/dist/dependency-catalog.js +0 -19
  70. package/node_modules/@ykdz/template-core/dist/module-graph.d.ts +0 -9
  71. package/node_modules/@ykdz/template-core/dist/module-graph.js +0 -40
  72. package/node_modules/@ykdz/template-core/dist/package-contribution.d.ts +2 -2
  73. package/node_modules/@ykdz/template-core/dist/package-contribution.js +2 -44
  74. package/node_modules/@ykdz/template-core/dist/pnpm-workspace.yaml +4 -1
  75. package/node_modules/@ykdz/template-core/dist/project-github.d.ts +0 -59
  76. package/node_modules/@ykdz/template-core/dist/project-github.js +7 -70
  77. package/node_modules/@ykdz/template-core/dist/renderer.d.ts +1 -0
  78. package/node_modules/@ykdz/template-core/dist/renderer.js +39 -1
  79. package/node_modules/@ykdz/template-core/dist/template-boundary-check.js +34 -16
  80. package/node_modules/@ykdz/template-core/package.json +0 -5
  81. package/package.json +4 -10
  82. package/node_modules/@ykdz/template-builtin-presets/templates/rust-bin/.github/workflows/check.yml +0 -23
  83. package/node_modules/@ykdz/template-builtin-presets/templates/ts-lib/.github/workflows/check.yml +0 -19
  84. package/node_modules/@ykdz/template-builtin-presets/templates/vue-app/.github/workflows/check.yml +0 -20
  85. package/node_modules/@ykdz/template-builtin-presets/templates/vue-app/vitest.config.ts +0 -8
  86. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/api/vitest.config.ts +0 -15
  87. package/node_modules/@ykdz/template-builtin-presets/templates/vue-hono-app/web/vitest.config.ts +0 -10
@@ -1,12 +1,13 @@
1
- import { describe, expect, it } from "vitest";
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
2
3
 
3
4
  import {
4
5
  cliCommandIdentity,
5
6
  validateCliCommandName,
6
7
  } from "../../src/cli-command-identity.ts";
7
8
 
8
- describe("CLI command identity", () => {
9
- it.each([
9
+ void describe("CLI command identity", () => {
10
+ for (const { name, command, message } of [
10
11
  { name: "path separator", command: "tools/release", message: "path" },
11
12
  { name: "backslash path", command: "tools\\release", message: "path" },
12
13
  { name: "whitespace", command: "release tool", message: "whitespace" },
@@ -14,63 +15,62 @@ describe("CLI command identity", () => {
14
15
  { name: "leading hyphen", command: "-release", message: "leading hyphen" },
15
16
  { name: "uppercase ASCII", command: "Release", message: "lowercase ASCII" },
16
17
  { name: "non-ASCII", command: "发布", message: "lowercase ASCII" },
17
- { name: "system tool", command: "node", message: "reserved system tool" },
18
- { name: "Windows device", command: "con", message: "reserved system tool" },
19
- {
20
- name: "Windows null device",
21
- command: "nul",
22
- message: "reserved system tool",
23
- },
24
- {
25
- name: "Windows serial device",
26
- command: "com1",
27
- message: "reserved system tool",
28
- },
29
- {
30
- name: "Windows printer device",
31
- command: "lpt9",
32
- message: "reserved system tool",
33
- },
34
- ])("rejects an unsafe command name: $name", ({ command, message }) => {
35
- expect(() => validateCliCommandName(command)).toThrow(message);
36
- });
18
+ ]) {
19
+ void it(`拒绝格式不合法的命令名:${name}`, () => {
20
+ assert.throws(
21
+ () => validateCliCommandName(command),
22
+ (error: unknown) => {
23
+ assert.ok(error instanceof Error);
24
+ assert.ok(error.message.includes(message));
25
+ return true;
26
+ },
27
+ );
28
+ });
29
+ }
37
30
 
38
- it("accepts a portable name unless another workspace command occupies it", () => {
39
- expect(validateCliCommandName("release-tool", [])).toBe("release-tool");
40
- expect(() =>
41
- validateCliCommandName("release-tool", ["release-tool"]),
42
- ).toThrow("already used by another workspace package");
31
+ void it("接受符合格式的命令名,并拒绝工作区中已使用的名称", () => {
32
+ assert.equal(validateCliCommandName("release-tool", []), "release-tool");
33
+ assert.throws(
34
+ () => validateCliCommandName("release-tool", ["release-tool"]),
35
+ /already used by another workspace package/,
36
+ );
43
37
  });
44
38
 
45
- it("derives command and unpublished version only from manifest facts", () => {
46
- expect(cliCommandIdentity({ bin: { release: "./dist/cli.js" } })).toEqual({
47
- commandName: "release",
48
- version: "unpublished",
49
- });
50
- expect(
39
+ void it("derives command and unpublished version only from manifest facts", () => {
40
+ assert.deepStrictEqual(
41
+ cliCommandIdentity({ bin: { release: "./dist/cli.js" } }),
42
+ { commandName: "release", version: "unpublished" },
43
+ );
44
+ assert.deepStrictEqual(
51
45
  cliCommandIdentity({
52
46
  bin: { ship: "./dist/cli.js" },
53
47
  version: "2.3.4",
54
48
  }),
55
- ).toEqual({ commandName: "ship", version: "2.3.4" });
49
+ { commandName: "ship", version: "2.3.4" },
50
+ );
56
51
  });
57
52
 
58
- it("rejects malformed manifest identity facts", () => {
59
- expect(() => cliCommandIdentity(null)).toThrow("must be an object");
60
- expect(() => cliCommandIdentity({ bin: {} })).toThrow("exactly one bin");
61
- expect(() =>
62
- cliCommandIdentity({
63
- bin: { release: "./dist/cli.js", ship: "./dist/cli.js" },
64
- }),
65
- ).toThrow("exactly one bin");
66
- expect(() =>
67
- cliCommandIdentity({ bin: { release: "./src/cli.ts" } }),
68
- ).toThrow('must execute "./dist/cli.js"');
69
- expect(() =>
70
- cliCommandIdentity({
71
- bin: { release: "./dist/cli.js" },
72
- version: 1,
73
- }),
74
- ).toThrow("version must be a non-empty string");
53
+ void it("rejects malformed manifest identity facts", () => {
54
+ assert.throws(() => cliCommandIdentity(null), /must be an object/);
55
+ assert.throws(() => cliCommandIdentity({ bin: {} }), /exactly one bin/);
56
+ assert.throws(
57
+ () =>
58
+ cliCommandIdentity({
59
+ bin: { release: "./dist/cli.js", ship: "./dist/cli.js" },
60
+ }),
61
+ /exactly one bin/,
62
+ );
63
+ assert.throws(
64
+ () => cliCommandIdentity({ bin: { release: "./src/cli.ts" } }),
65
+ /must execute ".\/dist\/cli\.js"/,
66
+ );
67
+ assert.throws(
68
+ () =>
69
+ cliCommandIdentity({
70
+ bin: { release: "./dist/cli.js" },
71
+ version: 1,
72
+ }),
73
+ /version must be a non-empty string/,
74
+ );
75
75
  });
76
76
  });
@@ -8,7 +8,7 @@
8
8
  "moduleResolution": "nodenext",
9
9
  "rewriteRelativeImportExtensions": true,
10
10
  "target": "es2024",
11
- "types": ["node", "vitest/globals"]
11
+ "types": ["node"]
12
12
  },
13
13
  "include": ["src/**/*.ts", "test/**/*.ts", "scripts/**/*.ts"]
14
14
  }
@@ -2,8 +2,63 @@
2
2
  "extends": ["//"],
3
3
  "tags": ["app"],
4
4
  "tasks": {
5
- "build": { "outputs": ["dist/**"] },
6
- "test": { "dependsOn": [] },
7
- "test:e2e": { "dependsOn": ["build"], "cache": false }
5
+ "build": {
6
+ "dependsOn": ["^build"],
7
+ "inputs": [],
8
+ "outputs": ["dist/**"],
9
+ "tags": ["quality:light"]
10
+ },
11
+ "format:check": {
12
+ "inputs": [],
13
+ "outputs": [],
14
+ "tags": ["quality:light"]
15
+ },
16
+ "format:write": {
17
+ "dependsOn": ["lint:fix"],
18
+ "inputs": [],
19
+ "outputs": [],
20
+ "cache": false,
21
+ "tags": ["work:repair"]
22
+ },
23
+ "lint": {
24
+ "inputs": [],
25
+ "outputs": [],
26
+ "tags": ["quality:light"]
27
+ },
28
+ "lint:fix": {
29
+ "inputs": [],
30
+ "outputs": [],
31
+ "cache": false,
32
+ "tags": ["work:repair"]
33
+ },
34
+ "postbuild": {
35
+ "inputs": [],
36
+ "outputs": [],
37
+ "tags": ["work:lifecycle"]
38
+ },
39
+ "prepack": {
40
+ "inputs": [],
41
+ "outputs": [],
42
+ "tags": ["work:release"]
43
+ },
44
+ "test": {
45
+ "dependsOn": [],
46
+ "inputs": [],
47
+ "outputs": [],
48
+ "tags": ["quality:light"]
49
+ },
50
+ "test:e2e": {
51
+ "dependsOn": ["build"],
52
+ "inputs": [],
53
+ "outputs": [],
54
+ "cache": false,
55
+ "tags": ["quality:heavy"]
56
+ },
57
+ "typecheck": {
58
+ "dependsOn": ["^typecheck"],
59
+ "inputs": [],
60
+ "outputs": [],
61
+ "tags": ["quality:light"]
62
+ }
8
63
  }
9
64
  }
@@ -0,0 +1,20 @@
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
3
+
4
+ import { greet } from "../src/index.ts";
5
+
6
+ void describe("greet", () => {
7
+ void it("returns a greeting for a valid name", () => {
8
+ assert.deepStrictEqual(greet("Ada"), { message: "Hello, Ada" });
9
+ });
10
+
11
+ void it("trims surrounding whitespace from a name", () => {
12
+ assert.deepStrictEqual(greet(" Ada Lovelace "), {
13
+ message: "Hello, Ada Lovelace",
14
+ });
15
+ });
16
+
17
+ void it("rejects a name that is empty after trimming", () => {
18
+ assert.throws(() => greet(" \t\n "));
19
+ });
20
+ });
@@ -10,5 +10,5 @@
10
10
  "target": "es2024",
11
11
  "types": ["node"]
12
12
  },
13
- "include": ["src/**/*.ts", "scripts/**/*.ts"]
13
+ "include": ["src/**/*.ts", "scripts/**/*.ts", "test/**/*.ts"]
14
14
  }
@@ -1,4 +1,47 @@
1
1
  {
2
2
  "extends": ["//"],
3
- "tags": ["library"]
3
+ "tags": ["library"],
4
+ "tasks": {
5
+ "build": {
6
+ "dependsOn": ["^build"],
7
+ "inputs": [],
8
+ "outputs": [],
9
+ "tags": ["quality:light"]
10
+ },
11
+ "format:check": {
12
+ "inputs": [],
13
+ "outputs": [],
14
+ "tags": ["quality:light"]
15
+ },
16
+ "format:write": {
17
+ "dependsOn": ["lint:fix"],
18
+ "inputs": [],
19
+ "outputs": [],
20
+ "cache": false,
21
+ "tags": ["work:repair"]
22
+ },
23
+ "lint": {
24
+ "inputs": [],
25
+ "outputs": [],
26
+ "tags": ["quality:light"]
27
+ },
28
+ "lint:fix": {
29
+ "inputs": [],
30
+ "outputs": [],
31
+ "cache": false,
32
+ "tags": ["work:repair"]
33
+ },
34
+ "test": {
35
+ "dependsOn": [],
36
+ "inputs": [],
37
+ "outputs": [],
38
+ "tags": ["quality:light"]
39
+ },
40
+ "typecheck": {
41
+ "dependsOn": ["^typecheck"],
42
+ "inputs": [],
43
+ "outputs": [],
44
+ "tags": ["quality:light"]
45
+ }
46
+ }
4
47
  }
@@ -1,23 +1,20 @@
1
- import { describe, expect, it } from "vitest";
1
+ import assert from "node:assert/strict";
2
+ import { describe, it } from "node:test";
2
3
 
3
4
  import { createDatabase } from "#db/db";
4
5
  import { createTodo, listTodos } from "#db/queries/todos";
5
6
  import { assertDatabaseReady } from "#db/readiness";
6
7
 
7
- describe("todo queries", () => {
8
- it("creates and lists todos through Drizzle SQLite", async () => {
8
+ void describe("todo queries", () => {
9
+ void it("creates and lists todos through Drizzle SQLite", async () => {
9
10
  const db = createDatabase();
10
11
  assertDatabaseReady(db);
11
12
  const title = `发布模板 ${Date.now()}`;
12
13
 
13
- await expect(createTodo(db, { title })).resolves.toMatchObject({
14
- title,
15
- });
16
- await expect(listTodos(db)).resolves.toEqual(
17
- expect.arrayContaining([expect.objectContaining({ title })]),
18
- );
19
- await expect(db.query.todos.findMany()).resolves.toEqual(
20
- expect.arrayContaining([expect.objectContaining({ title })]),
14
+ assert.equal((await createTodo(db, { title })).title, title);
15
+ assert.ok((await listTodos(db)).some((todo) => todo.title === title));
16
+ assert.ok(
17
+ (await db.query.todos.findMany()).some((todo) => todo.title === title),
21
18
  );
22
19
  });
23
20
  });
@@ -3,7 +3,44 @@
3
3
  "tags": ["library"],
4
4
  "tasks": {
5
5
  "build": {
6
- "outputs": ["dist/**"]
6
+ "dependsOn": ["^build"],
7
+ "outputs": ["dist/**"],
8
+ "tags": ["quality:light"]
9
+ },
10
+ "db:seed:example": {
11
+ "cache": false,
12
+ "tags": ["work:preparation"]
13
+ },
14
+ "db:reset": {
15
+ "cache": false,
16
+ "tags": ["work:preparation"]
17
+ },
18
+ "format:check": {
19
+ "outputs": [],
20
+ "tags": ["quality:light"]
21
+ },
22
+ "format:write": {
23
+ "dependsOn": ["lint:fix"],
24
+ "cache": false,
25
+ "tags": ["work:repair"]
26
+ },
27
+ "lint": {
28
+ "outputs": [],
29
+ "tags": ["quality:light"]
30
+ },
31
+ "lint:fix": {
32
+ "cache": false,
33
+ "tags": ["work:repair"]
34
+ },
35
+ "test": {
36
+ "dependsOn": ["//#database:prepare:test"],
37
+ "outputs": [],
38
+ "tags": ["quality:light"]
39
+ },
40
+ "typecheck": {
41
+ "dependsOn": ["^typecheck"],
42
+ "outputs": [],
43
+ "tags": ["quality:light"]
7
44
  }
8
45
  }
9
46
  }
@@ -4,7 +4,50 @@
4
4
  "tasks": {
5
5
  "build": {
6
6
  "dependsOn": ["^build"],
7
- "outputs": []
7
+ "outputs": [],
8
+ "tags": ["quality:light"]
9
+ },
10
+ "db:generate": {
11
+ "cache": false,
12
+ "tags": ["work:development"]
13
+ },
14
+ "db:migrate": {
15
+ "cache": false,
16
+ "tags": ["work:lifecycle"]
17
+ },
18
+ "db:prepare:deploy": {
19
+ "cache": false,
20
+ "tags": ["work:lifecycle"]
21
+ },
22
+ "db:push": {
23
+ "cache": false,
24
+ "tags": ["work:preparation"]
25
+ },
26
+ "db:studio": {
27
+ "cache": false,
28
+ "tags": ["work:development"]
29
+ },
30
+ "format:check": {
31
+ "outputs": [],
32
+ "tags": ["quality:light"]
33
+ },
34
+ "format:write": {
35
+ "dependsOn": ["lint:fix"],
36
+ "cache": false,
37
+ "tags": ["work:repair"]
38
+ },
39
+ "lint": {
40
+ "outputs": [],
41
+ "tags": ["quality:light"]
42
+ },
43
+ "lint:fix": {
44
+ "cache": false,
45
+ "tags": ["work:repair"]
46
+ },
47
+ "typecheck": {
48
+ "dependsOn": ["{{DATABASE_PACKAGE_NAME}}#build"],
49
+ "outputs": [],
50
+ "tags": ["quality:light"]
8
51
  }
9
52
  }
10
53
  }
@@ -101,6 +101,7 @@ async function sharedPort(envName: string): Promise<string> {
101
101
  }
102
102
 
103
103
  const externalServiceUrl = externalBaseUrl();
104
+ const usesExternalService = externalServiceUrl !== undefined;
104
105
  let previewUrl: string;
105
106
 
106
107
  if (externalServiceUrl === undefined) {
@@ -115,12 +116,27 @@ if (externalServiceUrl === undefined) {
115
116
  export default defineConfig({
116
117
  testDir: "./test/e2e",
117
118
  timeout: 60_000,
119
+ outputDir: usesExternalService
120
+ ? "test-results/deployment"
121
+ : "test-results/e2e",
118
122
  use: {
119
123
  baseURL: previewUrl,
120
124
  trace: "retain-on-failure",
121
125
  },
122
- reporter: [["list"], ["html"]],
123
- globalTeardown: "./test/playwright-teardown.ts",
126
+ reporter: [
127
+ ["list"],
128
+ [
129
+ "html",
130
+ {
131
+ outputFolder: usesExternalService
132
+ ? "playwright-report/deployment"
133
+ : "playwright-report/e2e",
134
+ },
135
+ ],
136
+ ],
137
+ ...(usesExternalService
138
+ ? {}
139
+ : { globalTeardown: "./test/playwright-teardown.ts" }),
124
140
  ...(externalServiceUrl === undefined
125
141
  ? {
126
142
  webServer: {
@@ -0,0 +1,14 @@
1
+ import { expect, it } from "vitest";
2
+ import { render } from "vitest-browser-vue";
3
+
4
+ import CounterButton from "../components/CounterButton.vue";
5
+
6
+ it("enables the counter after mounting and increments it", async () => {
7
+ const screen = await render(CounterButton);
8
+ const button = screen.getByRole("button", { name: /计数/ });
9
+
10
+ await expect.element(button).toBeEnabled();
11
+ await expect.element(button).toHaveTextContent("计数:0");
12
+ await button.click();
13
+ await expect.element(button).toHaveTextContent("计数:1");
14
+ });
@@ -3,7 +3,13 @@
3
3
  "compilerOptions": {
4
4
  "lib": ["ESNext", "DOM", "DOM.Iterable"],
5
5
  "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.test.tsbuildinfo",
6
- "types": ["node", "vitest/globals"]
6
+ "types": ["node"]
7
7
  },
8
- "include": ["test/**/*.ts", "vitest.config.ts"]
8
+ "include": [
9
+ "assets/**/*.svg",
10
+ "components/**/*.vue",
11
+ "test/**/*.ts",
12
+ "types/**/*.d.ts",
13
+ "vitest.config.ts"
14
+ ]
9
15
  }
@@ -3,7 +3,67 @@
3
3
  "tags": ["app"],
4
4
  "tasks": {
5
5
  "build": {
6
- "outputs": ["dist/**"]
6
+ "dependsOn": ["^build"],
7
+ "outputs": ["dist/**"],
8
+ "tags": ["quality:light"]
9
+ },
10
+ "dev": {
11
+ "dependsOn": ["{{DATABASE_PACKAGE_NAME}}#build"],
12
+ "cache": false,
13
+ "persistent": true,
14
+ "tags": ["work:development"]
15
+ },
16
+ "format:check": {
17
+ "outputs": [],
18
+ "tags": ["quality:light"]
19
+ },
20
+ "format:write": {
21
+ "dependsOn": ["lint:fix"],
22
+ "cache": false,
23
+ "tags": ["work:repair"]
24
+ },
25
+ "lint": {
26
+ "outputs": [],
27
+ "tags": ["quality:light"]
28
+ },
29
+ "lint:fix": {
30
+ "cache": false,
31
+ "tags": ["work:repair"]
32
+ },
33
+ "preview": {
34
+ "cache": false,
35
+ "tags": ["work:development"]
36
+ },
37
+ "start": {
38
+ "cache": false,
39
+ "tags": ["work:development"]
40
+ },
41
+ "browser:prepare": {
42
+ "cache": false,
43
+ "tags": ["work:preparation"]
44
+ },
45
+ "test": {
46
+ "outputs": [],
47
+ "tags": ["quality:light"]
48
+ },
49
+ "test:browser": {
50
+ "dependsOn": ["browser:prepare"],
51
+ "tags": ["quality:heavy"]
52
+ },
53
+ "test:e2e": {
54
+ "dependsOn": [
55
+ "//#database:prepare:e2e",
56
+ "{{DATABASE_PACKAGE_NAME}}#build",
57
+ "build",
58
+ "browser:prepare"
59
+ ],
60
+ "cache": false,
61
+ "tags": ["quality:heavy"]
62
+ },
63
+ "typecheck": {
64
+ "dependsOn": ["{{DATABASE_PACKAGE_NAME}}#build"],
65
+ "outputs": [],
66
+ "tags": ["quality:light"]
7
67
  }
8
68
  }
9
69
  }
@@ -1,8 +1,35 @@
1
+ import vue from "@vitejs/plugin-vue";
2
+ import { playwright } from "@vitest/browser-playwright";
1
3
  import { defineConfig } from "vitest/config";
2
4
 
3
5
  export default defineConfig({
6
+ plugins: [vue()],
4
7
  test: {
5
- globals: true,
6
- include: ["test/**/*.test.ts"],
8
+ attachmentsDir: ".vitest/attachments",
9
+ exclude: ["test/e2e/**", "node_modules/**", "dist/**"],
10
+ projects: [
11
+ {
12
+ extends: true,
13
+ test: {
14
+ name: "node",
15
+ include: ["test/**/*.node.test.ts"],
16
+ environment: "node",
17
+ },
18
+ },
19
+ {
20
+ extends: true,
21
+ test: {
22
+ name: "browser",
23
+ include: ["test/**/*.browser.test.ts"],
24
+ browser: {
25
+ enabled: true,
26
+ provider: playwright(),
27
+ headless: true,
28
+ screenshotFailures: true,
29
+ instances: [{ browser: "chromium" }],
30
+ },
31
+ },
32
+ },
33
+ ],
7
34
  },
8
35
  });
@@ -1,11 +1,7 @@
1
1
  <script setup lang="ts">
2
- import { storeToRefs } from "pinia";
3
2
  import { onMounted, onUnmounted, ref } from "vue";
4
3
 
5
- import { useCounterStore } from "#/stores/counter";
6
-
7
- const counter = useCounterStore();
8
- const { count } = storeToRefs(counter);
4
+ import CounterButton from "./components/CounterButton.vue";
9
5
  const themeLabel = ref<"深色" | "浅色">("浅色");
10
6
 
11
7
  let preferredThemeQuery: MediaQueryList | undefined;
@@ -39,13 +35,7 @@ onUnmounted(() => {
39
35
  端到端测试。
40
36
  </p>
41
37
  <div class="mt-8 flex items-center gap-4">
42
- <button
43
- class="rounded bg-cyan-300 px-4 py-2 font-semibold text-slate-950 hover:bg-cyan-200"
44
- type="button"
45
- @click="counter.increment()"
46
- >
47
- 计数:{{ count }}
48
- </button>
38
+ <CounterButton />
49
39
  <span class="text-sm text-slate-400">系统主题:{{ themeLabel }}</span>
50
40
  </div>
51
41
  </section>