Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# Dev Docs

> Below docs sections describes how xyd works under the hood: concepts, architecture or conventions.
> Below docs sections describes how xyd works under the hood: concepts, architecture and conventions.

- @docs/DEVELOPMENT.md (**IMPORTANT**)
- @docs/Overview.md
- @docs/GettingStarted.md
- @docs/InstallationAndCli.md
Expand Down
1 change: 1 addition & 0 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -247,3 +247,4 @@ When developing documents, you can use the following environment flags:
- `XYD_VERBOSE=1`: Enables verbose output and debug logging
- `XYD_NODE_PM=pnpm|bun|npm`: Specifies which package manager to use (auto-detects if not set)

### Read More
85 changes: 85 additions & 0 deletions docs/DEVELOPMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# DEVELOPMENT

## Tests and Fixtures

### Directory layout

Tests live in `__tests__/` and fixtures in `__fixtures__/` at the package root (or under `src/` for some packages).

```
packages/xyd-<name>/
├── __tests__/
│ ├── <feature>.test.ts # Test file
│ └── utils.ts # Shared test helpers
└── __fixtures__/
├── 1.basic/ # Positive fixture (runs in CI)
├── 2.circular/
├── -1.opendocs.flat/ # Negative-numbered (advanced/optional, may be disabled)
└── -2.complex.openai/
```

### Fixture naming convention

Each fixture is a numbered directory: `<order>.<descriptive-name>`.

| Prefix | Meaning | Example |
|--------|---------|---------|
| `1.`, `2.`, `3.` ... | Standard test cases, run in CI | `1.basic`, `3.multiple-responses` |
| `-1.`, `-2.`, `-3.` ... | Advanced/optional cases, may be commented out or sorted first | `-1.opendocs.flat`, `-2.complex.openai` |

Use dots to add sub-categories: `5.xdocs.sidebar`, `-1.opendocs.sort+group`.

### Input / output pattern

Every fixture contains an **input** and an expected **output**. The format depends on what's being tested:

| Package | Input | Output |
|---------|-------|--------|
| `xyd-gql` | `input.graphql` | `output.json` |
| `xyd-openapi` | `input.yaml` | `output.json` |
| `xyd-opencli-remark` | `input.md` | `output.md` |
| `xyd-source-react-babel-runtime` | `input/` (folder with `src/`, `package.json`, `tsconfig.json`) | `output.js` |

For simple converters (OpenAPI, GraphQL, remark), input and output are single files. For more complex scenarios (Vite builds, multi-file projects), `input/` is a folder containing the full project source.

### Test structure

Tests are data-driven. A test file defines an array of cases and iterates through them using a shared utility:

```ts
// __tests__/<feature>.test.ts
import { testMyFeature } from './utils';

const tests = [
{ name: '1.basic', description: 'Basic example' },
{ name: '2.more', description: 'Extended example' },
];

describe('my-feature', () => {
for (const t of tests) {
it(t.description, async () => {
await testMyFeature(t.name);
});
}
});
```

The utility function in `utils.ts` handles:
1. Loading input from `__fixtures__/<name>/`
2. Running the transformation
3. Saving result to `output.*` (for snapshot regeneration)
4. Comparing result against expected `output.*`

### Running tests

```bash
# Run all unit tests
pnpm test:unit

# Run tests for a specific package
cd packages/xyd-<name>
pnpm test

# Run with vitest watch mode
pnpm vitest
```
13 changes: 0 additions & 13 deletions packages/xyd-components/output.txt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "xyd-fixture-1-user-card",
"private": true,
"type": "module",
"main": "dist/index.js"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from 'react';

/**
* Props for the UserCard component
*/
export interface UserCardProps {
/** Full name of the user */
name: string;

/** Email address of the user */
email: string;

/** URL to the user's avatar image */
avatarUrl?: string;

/** Role or title of the user */
role?: string;

/** Whether the card is in a loading state */
loading?: boolean;
}

/**
* A card component that displays user information with avatar, name, and role.
*
* @category Component
*/
export function UserCard(props: UserCardProps) {
return (
<div>
{props.avatarUrl && <img src={props.avatarUrl} alt={props.name} />}
<h3>{props.name}</h3>
<p>{props.email}</p>
{props.role && <span>{props.role}</span>}
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"compilerOptions": {
"outDir": "./dist",
"jsx": "react-jsx",
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"target": "ES2020"
},
"include": ["src/**/*.ts", "src/**/*.tsx"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { jsxDEV } from "react/jsx-dev-runtime";
function UserCard(props) {
return /* @__PURE__ */ jsxDEV("div", { children: [
props.avatarUrl && /* @__PURE__ */ jsxDEV("img", { src: props.avatarUrl, alt: props.name }, void 0, false, {
fileName: "<ROOT>/src/UserCard.tsx",
lineNumber: 31,
columnNumber: 33
}, this),
/* @__PURE__ */ jsxDEV("h3", { children: props.name }, void 0, false, {
fileName: "<ROOT>/src/UserCard.tsx",
lineNumber: 32,
columnNumber: 13
}, this),
/* @__PURE__ */ jsxDEV("p", { children: props.email }, void 0, false, {
fileName: "<ROOT>/src/UserCard.tsx",
lineNumber: 33,
columnNumber: 13
}, this),
props.role && /* @__PURE__ */ jsxDEV("span", { children: props.role }, void 0, false, {
fileName: "<ROOT>/src/UserCard.tsx",
lineNumber: 34,
columnNumber: 28
}, this)
] }, void 0, true, {
fileName: "<ROOT>/src/UserCard.tsx",
lineNumber: 30,
columnNumber: 9
}, this);
}
UserCard.__xydUniform = JSON.parse(`{"title":"UserCard","canonical":"xyd-fixture-1-user-card/components/UserCard","description":"A card component that displays user information with avatar, name, and role.\\n","context":{"symbolId":"1","symbolName":"UserCard","symbolKind":64,"packageName":"xyd-fixture-1-user-card","fileName":"UserCard.tsx","fileFullPath":"src/UserCard.tsx","line":28,"col":16,"signatureText":{"code":"export function UserCard(props: UserCardProps);","lang":"ts"},"sourcecode":{"code":"export function UserCard(props: UserCardProps) {\\n return (\\n <div>\\n {props.avatarUrl && <img src={props.avatarUrl} alt={props.name} />}\\n <h3>{props.name}</h3>\\n <p>{props.email}</p>\\n {props.role && <span>{props.role}</span>}\\n </div>\\n );\\n}","lang":"ts"},"meta":[],"category":"Component","group":["xyd-fixture-1-user-card","Component"]},"examples":{"groups":[]},"definitions":[{"title":"Props","properties":[{"name":"name","type":"string","description":"Full name of the user\\n","meta":[{"name":"required","value":"true"}]},{"name":"email","type":"string","description":"Email address of the user\\n","meta":[{"name":"required","value":"true"}]},{"name":"avatarUrl","type":"string","description":"URL to the user's avatar image\\n","meta":[]},{"name":"role","type":"string","description":"Role or title of the user\\n","meta":[]},{"name":"loading","type":"boolean","description":"Whether the card is in a loading state\\n","meta":[]}],"meta":[{"name":"type","value":"parameters"}]}]}`);
export {
UserCard
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "xyd-fixture-2-sample-app",
"private": true,
"type": "module",
"main": "dist/index.js"
}
Loading
Loading