@plumbus/ui 0.1.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.
Files changed (49) hide show
  1. package/dist/.tsbuildinfo +1 -0
  2. package/dist/generators/__tests__/auth-generator.test.d.ts +2 -0
  3. package/dist/generators/__tests__/auth-generator.test.d.ts.map +1 -0
  4. package/dist/generators/__tests__/auth-generator.test.js +222 -0
  5. package/dist/generators/__tests__/auth-generator.test.js.map +1 -0
  6. package/dist/generators/__tests__/client-generator.test.d.ts +2 -0
  7. package/dist/generators/__tests__/client-generator.test.d.ts.map +1 -0
  8. package/dist/generators/__tests__/client-generator.test.js +224 -0
  9. package/dist/generators/__tests__/client-generator.test.js.map +1 -0
  10. package/dist/generators/__tests__/form-generator.test.d.ts +2 -0
  11. package/dist/generators/__tests__/form-generator.test.d.ts.map +1 -0
  12. package/dist/generators/__tests__/form-generator.test.js +192 -0
  13. package/dist/generators/__tests__/form-generator.test.js.map +1 -0
  14. package/dist/generators/__tests__/nextjs-template.test.d.ts +2 -0
  15. package/dist/generators/__tests__/nextjs-template.test.d.ts.map +1 -0
  16. package/dist/generators/__tests__/nextjs-template.test.js +214 -0
  17. package/dist/generators/__tests__/nextjs-template.test.js.map +1 -0
  18. package/dist/generators/auth-generator.d.ts +31 -0
  19. package/dist/generators/auth-generator.d.ts.map +1 -0
  20. package/dist/generators/auth-generator.js +292 -0
  21. package/dist/generators/auth-generator.js.map +1 -0
  22. package/dist/generators/client-generator.d.ts +31 -0
  23. package/dist/generators/client-generator.d.ts.map +1 -0
  24. package/dist/generators/client-generator.js +336 -0
  25. package/dist/generators/client-generator.js.map +1 -0
  26. package/dist/generators/form-generator.d.ts +47 -0
  27. package/dist/generators/form-generator.d.ts.map +1 -0
  28. package/dist/generators/form-generator.js +189 -0
  29. package/dist/generators/form-generator.js.map +1 -0
  30. package/dist/generators/index.d.ts +9 -0
  31. package/dist/generators/index.d.ts.map +1 -0
  32. package/dist/generators/index.js +6 -0
  33. package/dist/generators/index.js.map +1 -0
  34. package/dist/generators/nextjs-template.d.ts +44 -0
  35. package/dist/generators/nextjs-template.d.ts.map +1 -0
  36. package/dist/generators/nextjs-template.js +444 -0
  37. package/dist/generators/nextjs-template.js.map +1 -0
  38. package/dist/index.d.ts +9 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +11 -0
  41. package/dist/index.js.map +1 -0
  42. package/instructions/auth-generator.md +154 -0
  43. package/instructions/client-generator.md +149 -0
  44. package/instructions/form-generator.md +157 -0
  45. package/instructions/framework.md +108 -0
  46. package/instructions/nextjs-template.md +160 -0
  47. package/instructions/patterns.md +109 -0
  48. package/instructions/testing.md +211 -0
  49. package/package.json +52 -0
@@ -0,0 +1,211 @@
1
+ # Testing
2
+
3
+ The UI package uses Vitest for unit tests and optionally Playwright via `@vitest/browser` for browser-based tests.
4
+
5
+ ## Test Setup
6
+
7
+ ```bash
8
+ # Unit tests (Node)
9
+ pnpm --filter @plumbus/ui test
10
+
11
+ # Browser tests (Playwright + Chromium)
12
+ pnpm --filter @plumbus/ui test:browser
13
+ ```
14
+
15
+ Config files:
16
+ - Unit tests: uses default Vitest config from workspace root
17
+ - Browser tests: `vitest.config.browser.ts` — runs in Chromium via `@vitest/browser`
18
+
19
+ ## Test Files
20
+
21
+ ```
22
+ src/generators/__tests__/
23
+ client-generator.test.ts # 200+ lines — client/hook/flow generation
24
+ auth-generator.test.ts # 160+ lines — auth types/functions/hooks
25
+ form-generator.test.ts # 220+ lines — Zod schema introspection
26
+ nextjs-template.test.ts # 180+ lines — project scaffold
27
+ ```
28
+
29
+ ## Testing Strategy
30
+
31
+ All generators produce **strings of source code**. Tests verify the generated code by:
32
+ 1. Checking string contents with `toContain()` for expected patterns.
33
+ 2. Validating JSON outputs with `JSON.parse()` (e.g. package.json).
34
+ 3. Verifying structural properties (function names, type names, imports).
35
+
36
+ ## Writing Tests for Generators
37
+
38
+ ### Test a Capability-Based Generator
39
+
40
+ Create a mock `CapabilityContract` and pass it to the generator:
41
+
42
+ ```ts
43
+ import { describe, it, expect } from "vitest";
44
+ import { generateTypedClient } from "../client-generator.js";
45
+ import type { CapabilityContract } from "@plumbus/core";
46
+
47
+ const mockCap: CapabilityContract = {
48
+ name: "getUser",
49
+ kind: "query",
50
+ domain: "users",
51
+ description: "Get a user by ID",
52
+ input: {} as any,
53
+ output: {} as any,
54
+ access: { roles: ["admin"] },
55
+ effects: [],
56
+ };
57
+
58
+ describe("generateTypedClient", () => {
59
+ it("generates a GET client for query capabilities", () => {
60
+ const code = generateTypedClient(mockCap);
61
+ expect(code).toContain("export async function getUser");
62
+ expect(code).toContain('method: "GET"');
63
+ expect(code).toContain("/api/users/get-user");
64
+ });
65
+
66
+ it("includes JSDoc when configured", () => {
67
+ const code = generateTypedClient(mockCap, { includeJsDoc: true });
68
+ expect(code).toContain("/** Get a user by ID */");
69
+ });
70
+
71
+ it("uses custom base URL", () => {
72
+ const code = generateTypedClient(mockCap, { baseUrl: "https://api.example.com" });
73
+ expect(code).toContain("https://api.example.com/api/users/get-user");
74
+ });
75
+ });
76
+ ```
77
+
78
+ ### Test a Config-Based Generator
79
+
80
+ ```ts
81
+ import { generateAuthModule } from "../auth-generator.js";
82
+
83
+ describe("generateAuthModule", () => {
84
+ it("includes all auth sections", () => {
85
+ const code = generateAuthModule({ provider: "jwt" });
86
+ expect(code).toContain("interface AuthUser");
87
+ expect(code).toContain("function login");
88
+ expect(code).toContain("function useAuth");
89
+ expect(code).toContain("function RouteGuard");
90
+ });
91
+
92
+ it("includes tenant context when multiTenant enabled", () => {
93
+ const code = generateAuthModule({ provider: "jwt", multiTenant: true });
94
+ expect(code).toContain("function useTenant");
95
+ });
96
+
97
+ it("excludes tenant context by default", () => {
98
+ const code = generateAuthModule({ provider: "jwt" });
99
+ expect(code).not.toContain("useTenant");
100
+ });
101
+ });
102
+ ```
103
+
104
+ ### Test Form Hint Extraction with Zod
105
+
106
+ ```ts
107
+ import { z } from "zod";
108
+ import { extractFieldHint, extractFormHints } from "../form-generator.js";
109
+ import type { CapabilityContract } from "@plumbus/core";
110
+
111
+ describe("extractFieldHint", () => {
112
+ it("extracts string field", () => {
113
+ const hint = extractFieldHint("name", z.string().min(1).max(100));
114
+ expect(hint.fieldType).toBe("text");
115
+ expect(hint.required).toBe(true);
116
+ expect(hint.validation.minLength).toBe(1);
117
+ expect(hint.validation.maxLength).toBe(100);
118
+ });
119
+
120
+ it("extracts enum field with options", () => {
121
+ const hint = extractFieldHint("role", z.enum(["admin", "user", "guest"]));
122
+ expect(hint.fieldType).toBe("select");
123
+ expect(hint.options).toEqual(["admin", "user", "guest"]);
124
+ });
125
+
126
+ it("handles optional fields", () => {
127
+ const hint = extractFieldHint("nickname", z.string().optional());
128
+ expect(hint.required).toBe(false);
129
+ });
130
+
131
+ it("extracts default values", () => {
132
+ const hint = extractFieldHint("active", z.boolean().default(true));
133
+ expect(hint.required).toBe(false);
134
+ expect(hint.defaultValue).toBe(true);
135
+ });
136
+ });
137
+
138
+ describe("extractFormHints", () => {
139
+ it("extracts all fields from a capability", () => {
140
+ const cap = {
141
+ name: "createUser",
142
+ kind: "action",
143
+ domain: "users",
144
+ input: z.object({
145
+ name: z.string(),
146
+ email: z.string().email(),
147
+ role: z.enum(["admin", "user"]),
148
+ }),
149
+ } as unknown as CapabilityContract;
150
+
151
+ const hints = extractFormHints(cap);
152
+ expect(hints.fields).toHaveLength(3);
153
+ expect(hints.fields[0]!.name).toBe("name");
154
+ expect(hints.fields[1]!.validation.pattern).toBe("email");
155
+ expect(hints.fields[2]!.fieldType).toBe("select");
156
+ });
157
+ });
158
+ ```
159
+
160
+ ### Test Next.js Template Generation
161
+
162
+ ```ts
163
+ import { generateNextjsTemplate, generatePackageJson } from "../nextjs-template.js";
164
+
165
+ describe("generateNextjsTemplate", () => {
166
+ it("generates valid package.json", () => {
167
+ const file = generatePackageJson({ appName: "My App" });
168
+ const parsed = JSON.parse(file.content);
169
+ expect(parsed.name).toBe("my-app");
170
+ expect(parsed.dependencies.next).toBeDefined();
171
+ });
172
+
173
+ it("includes auth files when auth enabled", () => {
174
+ const files = generateNextjsTemplate({ appName: "Test", auth: true });
175
+ const paths = files.map((f) => f.path);
176
+ expect(paths).toContain("components/AuthProvider.tsx");
177
+ });
178
+
179
+ it("generates capability pages", () => {
180
+ const cap = { name: "getUser", kind: "query", domain: "users" } as any;
181
+ const files = generateNextjsTemplate({ appName: "Test" }, [cap]);
182
+ const paths = files.map((f) => f.path);
183
+ expect(paths).toContain("app/get-user/page.tsx");
184
+ });
185
+ });
186
+ ```
187
+
188
+ ## Test Patterns Summary
189
+
190
+ | Pattern | When to Use |
191
+ |---------|-------------|
192
+ | `toContain(string)` | Verify specific code appears in output |
193
+ | `not.toContain(string)` | Verify code is excluded (e.g. optional features) |
194
+ | `JSON.parse(output)` | Validate JSON file content (package.json, tsconfig) |
195
+ | `files.map(f => f.path)` | Check generated file paths in multi-file output |
196
+ | Mock `CapabilityContract` | Any generator that takes a capability |
197
+ | Mock Zod schemas | Form hint extraction tests |
198
+ | Config variations | Test generator options (auth, baseUrl, multiTenant) |
199
+
200
+ ## Running Specific Tests
201
+
202
+ ```bash
203
+ # Run all UI tests
204
+ pnpm --filter @plumbus/ui test
205
+
206
+ # Run a specific test file
207
+ pnpm --filter @plumbus/ui test -- client-generator
208
+
209
+ # Run with watch mode
210
+ pnpm --filter @plumbus/ui test -- --watch
211
+ ```
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@plumbus/ui",
3
+ "version": "0.1.0",
4
+ "description": "Plumbus UI — client generation and frontend templates",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.js"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "instructions"
17
+ ],
18
+ "keywords": [
19
+ "plumbus",
20
+ "ui",
21
+ "frontend"
22
+ ],
23
+ "license": "MIT",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "https://github.com/plumbus-framework/plumbus.git",
27
+ "directory": "packages/ui"
28
+ },
29
+ "publishConfig": {
30
+ "access": "public"
31
+ },
32
+ "dependencies": {
33
+ "zod": "^3.24.0",
34
+ "@plumbus/core": "0.1.0"
35
+ },
36
+ "devDependencies": {
37
+ "@vitest/browser": "^3.0.0",
38
+ "playwright": "^1.52.0",
39
+ "typescript": "^5.7.0",
40
+ "vitest": "^3.0.0"
41
+ },
42
+ "scripts": {
43
+ "build": "tsc -b",
44
+ "dev": "tsc -b --watch",
45
+ "test": "vitest run --passWithNoTests",
46
+ "test:browser": "vitest run --config vitest.config.browser.ts --passWithNoTests",
47
+ "lint": "biome lint ./src",
48
+ "format": "biome format --write ./src",
49
+ "format:check": "biome format ./src",
50
+ "typecheck": "tsc --noEmit"
51
+ }
52
+ }