Skip to content

Commit 64f8c1a

Browse files
committed
adding test stuff
1 parent 047b496 commit 64f8c1a

68 files changed

Lines changed: 12036 additions & 1555 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/settings.local.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
"allow": [
44
"Bash(npm run build:*)",
55
"WebFetch(domain:localhost)",
6-
"Bash(npx tsc:*)"
6+
"Bash(npx tsc:*)",
7+
"Bash(npm run test:run:*)"
78
]
89
}
910
}

.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,12 @@ dist-ssr
2222
*.njsproj
2323
*.sln
2424
*.sw?
25+
26+
*storybook.log
27+
storybook-static
28+
29+
# Playwright BDD
30+
.features-gen
31+
test-results
32+
playwright-report
33+
playwright/.cache

.storybook/main.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import type { StorybookConfig } from '@storybook/react-vite';
2+
3+
const config: StorybookConfig = {
4+
"stories": [
5+
"../src/**/*.mdx",
6+
"../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"
7+
],
8+
"addons": [
9+
"@chromatic-com/storybook",
10+
"@storybook/addon-vitest",
11+
"@storybook/addon-a11y",
12+
"@storybook/addon-docs",
13+
"@storybook/addon-onboarding"
14+
],
15+
"framework": "@storybook/react-vite"
16+
};
17+
export default config;

.storybook/preview.tsx

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import React from 'react'
2+
import type { Preview, Decorator } from '@storybook/react-vite'
3+
import { createStore, createIndexes, Store, Indexes } from 'tinybase'
4+
import { Provider } from 'tinybase/ui-react'
5+
import { FOAF, VCARD } from '@inrupt/vocab-common-rdf'
6+
7+
// Create sample store with test data for stories
8+
function createSampleStore(): { store: Store; indexes: Indexes } {
9+
const store = createStore()
10+
const indexes = createIndexes(store)
11+
12+
// Initialize tables
13+
store.setTables({
14+
resources: {},
15+
personas: {},
16+
contacts: {},
17+
groups: {},
18+
typeIndexes: {},
19+
})
20+
21+
// Add sample personas
22+
store.setRow('personas', 'persona-1', {
23+
'@id': 'https://pod.example.com/profiles/alice#me',
24+
'@type': FOAF.Person,
25+
[FOAF.name]: 'Alice Smith',
26+
[FOAF.nick]: 'alice',
27+
[VCARD.hasEmail]: 'mailto:alice@example.com',
28+
})
29+
30+
store.setRow('personas', 'persona-2', {
31+
'@id': 'https://pod.example.com/profiles/bob#me',
32+
'@type': FOAF.Person,
33+
[FOAF.name]: 'Bob Developer',
34+
[VCARD.hasEmail]: 'mailto:bob@work.com',
35+
})
36+
37+
// Add sample contacts
38+
store.setRow('contacts', 'contact-1', {
39+
'@id': 'https://pod.example.com/contacts/john#',
40+
'@type': VCARD.Individual,
41+
[VCARD.fn]: 'John Doe',
42+
[VCARD.nickname]: 'johnny',
43+
[VCARD.hasEmail]: 'mailto:john@example.com',
44+
[VCARD.hasOrganizationName]: 'Acme Corp',
45+
})
46+
47+
store.setRow('contacts', 'contact-2', {
48+
'@id': 'https://pod.example.com/contacts/jane#',
49+
'@type': VCARD.Individual,
50+
[VCARD.fn]: 'Jane Smith',
51+
[VCARD.hasEmail]: 'mailto:jane@example.com',
52+
})
53+
54+
store.setRow('contacts', 'contact-3', {
55+
'@id': 'https://pod.example.com/contacts/ai-bot#',
56+
'@type': 'https://schema.org/SoftwareApplication',
57+
[VCARD.fn]: 'AI Assistant',
58+
[VCARD.note]: 'A helpful AI chatbot',
59+
})
60+
61+
// Add sample groups
62+
store.setRow('groups', 'group-1', {
63+
'@id': 'https://pod.example.com/groups/acme#org',
64+
'@type': 'http://www.w3.org/ns/org#Organization',
65+
[VCARD.fn]: 'Acme Corporation',
66+
'http://purl.org/dc/terms/description': 'A sample organization',
67+
})
68+
69+
store.setRow('groups', 'group-2', {
70+
'@id': 'https://pod.example.com/groups/team-alpha#team',
71+
'@type': VCARD.Group,
72+
[VCARD.fn]: 'Team Alpha',
73+
'http://purl.org/dc/terms/description': 'The best team',
74+
})
75+
76+
// Set default persona
77+
store.setValue('defaultPersonaId', 'persona-1')
78+
79+
return { store, indexes }
80+
}
81+
82+
// Global decorator that wraps all stories in TinyBase Provider
83+
const withTinyBase: Decorator = (Story, context) => {
84+
// Allow stories to provide their own store via parameters
85+
const customStore = context.parameters.store
86+
const { store, indexes } = customStore || createSampleStore()
87+
88+
return (
89+
<Provider store={store} indexes={indexes}>
90+
<Story />
91+
</Provider>
92+
)
93+
}
94+
95+
const preview: Preview = {
96+
parameters: {
97+
controls: {
98+
matchers: {
99+
color: /(background|color)$/i,
100+
date: /Date$/i,
101+
},
102+
},
103+
// Default background
104+
backgrounds: {
105+
default: 'light',
106+
values: [
107+
{ name: 'light', value: '#f5f5f5' },
108+
{ name: 'dark', value: '#1a1a1a' },
109+
],
110+
},
111+
},
112+
decorators: [withTinyBase],
113+
}
114+
115+
export default preview

AGENTS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Context for AI assistants working on this repo.
2121
| `src/utils/` | settings, storeExport, typeIndex helpers, validation. |
2222
| `src/cli/` | CliTerminal, command registry, parse-args, types. |
2323
| `src/components/` | PersonaList/Form, ContactList/Form, GroupList/Form, MembershipManager, FileMetadataPanel. |
24-
| `docs/` | DESIGN.md, IMPLEMENTATION_PLAN.md. |
24+
| `docs/` | CODING_GUIDELINES.md, DESIGN.md, IMPLEMENTATION_PLAN.md, testing/. |
2525

2626
## What’s done so far
2727

@@ -71,5 +71,6 @@ When someone wants to use this in an app they’re working on, point them to the
7171
## Useful docs
7272

7373
- **README.md** – Overview, limitations, Use as a library (Zod + JSON Schema), Integration Guide (copy-paste vs install-from-GitHub), Getting Started (Node note, Live demo + 404 troubleshooting), CLI command list.
74+
- **docs/CODING_GUIDELINES.md** – TypeScript (strict types, no sloppy types), short functions, simple React components, naming, file length.
7475
- **docs/IMPLEMENTATION_PLAN.md** – Feature/phases.
7576
- **DESIGN.md** – Design notes.

README.md

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,54 @@ export|import Data portability
438438
clear Clear terminal
439439
```
440440

441+
## Testing
442+
443+
- **Unit tests (Vitest):** `npm test` or `npm run test:run`; coverage: `npm run test:coverage`
444+
- **BDD / E2E (Playwright):** Generate specs from Gherkin, then run Playwright:
445+
```bash
446+
npx bddgen && npx playwright test
447+
```
448+
Or use the scripts: `npm run test:e2e` or `npm run test:bdd` (same thing). With browser visible: `npm run test:e2e:headed`.
449+
450+
**Start the server manually (recommended if E2E hangs):** In one terminal start the app; in another run the tests. Playwright will reuse the existing server on port 5173 (`reuseExistingServer` when not in CI).
451+
1. **Terminal 1:** `npm run dev` — leave it running (app at http://localhost:5173).
452+
2. **Terminal 2:** `npx bddgen && npx playwright test` (or `npm run test:e2e`).
453+
454+
If you use a different port for the app, set `E2E_BASE_URL` so Playwright hits the right URL (e.g. `E2E_BASE_URL=http://localhost:3000 npx playwright test` after starting the app on 3000).
455+
456+
### Try the BDD steps manually
457+
458+
You can run through the BDD scenarios by hand to verify behavior without Playwright:
459+
460+
1. **App shell**
461+
- Open the app (`npm run dev`, then http://localhost:5173).
462+
- Check the browser tab title contains `tb-solid-pod`.
463+
- Click the **Terminal** tab and confirm you see the CLI welcome message or prompt.
464+
465+
2. **CLI contacts**
466+
- Go to the **Terminal** tab.
467+
- Run: `contact add JohnDoe --email=john@example.com` → you should see **Added contact: JohnDoe**.
468+
- Run: `contact add JaneSmith` then `contact list` → you should see **JaneSmith** in the list.
469+
- Run: `contact` → you should see **Usage: contact**, **Subcommands**, **add**, and **list** in the help.
470+
471+
3. **CLI personas**
472+
- In the Terminal, run: `persona create TestUser --email=test@example.com` → you should see **Created persona: TestUser**.
473+
- Run: `persona list` → you should see **Persona** (or personas list / empty message).
474+
- Run: `persona` → you should see **Usage: persona**, **Subcommands**, and **create** in the help.
475+
476+
4. **CLI navigation**
477+
- Run: `help` → you should see **help**, **contact**, **persona** in the output.
478+
- Run: `contact list` then `clear` → terminal output should clear.
479+
480+
5. **UI tabs**
481+
- Click **Contacts** → you should see the contacts view (list or empty state).
482+
- Click **Personas** → you should see the personas view.
483+
- Confirm **Personas**, **Contacts**, and **Terminal** tabs are visible.
484+
485+
Feature files live under `tests/features/` (e.g. `cli-contacts.feature`, `app.feature`). Step definitions are in `tests/features/steps/`. After changing `.feature` or steps, run `npx bddgen` before `npx playwright test`.
486+
487+
For more detail (where results are stored, unit/BDD/Storybook guidelines), see **[docs/testing/](docs/testing/README.md)**. For coding standards (strict TypeScript, short functions, simple components), see **[docs/CODING_GUIDELINES.md](docs/CODING_GUIDELINES.md)**.
488+
441489
## License
442490

443491
AGPL-3.0-or-later. See [LICENSE](LICENSE).

docs/CODING_GUIDELINES.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Coding guidelines
2+
3+
Keep the codebase maintainable: strict types, small units of work, and simple React components.
4+
5+
## TypeScript
6+
7+
- **Strict types only.** The project uses `strict: true` in `tsconfig.json`. Do not relax it.
8+
- **Avoid `any`.** Use `unknown` and narrow with type guards, or define proper interfaces. If you must escape types, use a minimal cast and comment why.
9+
- **Prefer explicit types** for function parameters and return values in public APIs (exports, component props). Let inference do the work inside small, local functions when it’s obvious.
10+
- **Model data with interfaces or types.** Use Zod schemas as the source of truth for domain shapes; align TypeScript types with them (e.g. `z.infer<typeof MySchema>`).
11+
- **No sloppy object types.** Avoid `Record<string, unknown>` in public APIs unless you’re truly handling arbitrary data; prefer named properties and interfaces.
12+
13+
## Functions
14+
15+
- **Keep functions short.** Aim for a single level of abstraction and one clear responsibility. If a function is long or doing several things, split it.
16+
- **Extract helpers** for repeated logic or non-trivial calculations. Put them in a small, testable function or a shared util.
17+
- **Limit parameters.** If a function takes more than a few arguments, consider an options object or a small typed config.
18+
19+
## React components
20+
21+
- **Keep components small.** If a component is long or has many branches, extract subcomponents or custom hooks.
22+
- **Avoid overly complex components.** Prefer many small components over one large one. Use composition.
23+
- **Custom hooks for stateful logic.** If a component has non-trivial state or effects, move that logic into a `useSomething` hook and keep the component mostly presentational.
24+
- **Props: typed and minimal.** Define a clear props interface; avoid spreading large objects “just in case.”
25+
26+
## General
27+
28+
- **Naming:** Use clear, consistent names. Prefer `handleSubmit` over `onClick` for handlers passed as props; keep event handlers and callbacks obvious.
29+
- **File length:** If a file grows past roughly 200–300 lines, consider splitting (e.g. by component, by feature, or into a small folder).
30+
- **Comments:** Comment *why* when it’s not obvious from the code; avoid restating what the code does.
31+
- **Tests:** New behavior should have unit tests where practical. Follow existing patterns in `tests/unit/` and use the test helpers (e.g. `renderWithProviders`, `createTestStore`).
32+
33+
## Dependencies
34+
35+
- **When picking a library, prefer ones written in TypeScript with strict typing conventions.** Good type definitions (or first-party TypeScript) reduce runtime bugs and make refactors safer; avoid libraries that rely on loose or hand-maintained `@types` if a better-typed alternative exists.
36+
37+
## Process
38+
39+
- **When a refactor or code change breaks a test, do not automatically fix the test.** The developer who made the change is responsible for resolving the failure: either update the code so the test passes again, or change the test only after deciding that the new behavior is correct and the test’s expectations were wrong. Do not silently adjust tests to match new behavior without that decision.
40+
41+
These guidelines apply to `src/` and `tests/`; tooling and config can be more permissive where needed.

0 commit comments

Comments
 (0)