graphics-debug 0.0.21 → 0.0.23
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/README.md +104 -16
- package/dist/lib/matcher.d.ts +5 -0
- package/dist/lib/matcher.js +60 -0
- package/dist/lib/matcher.js.map +1 -0
- package/package.json +8 -3
package/README.md
CHANGED
|
@@ -36,23 +36,52 @@ https://github.com/user-attachments/assets/9f3f41e6-b0fe-416a-a551-ba5c5b920cad
|
|
|
36
36
|
The `graphics` json object is very simple, here's the basic schema:
|
|
37
37
|
|
|
38
38
|
```typescript
|
|
39
|
+
interface Point {
|
|
40
|
+
x: number
|
|
41
|
+
y: number
|
|
42
|
+
color?: string
|
|
43
|
+
label?: string
|
|
44
|
+
layer?: string
|
|
45
|
+
step?: number
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface Line {
|
|
49
|
+
points: { x: number; y: number }[]
|
|
50
|
+
strokeWidth?: number
|
|
51
|
+
strokeColor?: string
|
|
52
|
+
strokeDash?: string
|
|
53
|
+
layer?: string
|
|
54
|
+
step?: number
|
|
55
|
+
label?: string
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
interface Rect {
|
|
59
|
+
center: { x: number; y: number }
|
|
60
|
+
width: number
|
|
61
|
+
height: number
|
|
62
|
+
fill?: string
|
|
63
|
+
stroke?: string
|
|
64
|
+
color?: string
|
|
65
|
+
layer?: string
|
|
66
|
+
step?: number
|
|
67
|
+
label?: string
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
interface Circle {
|
|
71
|
+
center: { x: number; y: number }
|
|
72
|
+
radius: number
|
|
73
|
+
fill?: string
|
|
74
|
+
stroke?: string
|
|
75
|
+
layer?: string
|
|
76
|
+
step?: number
|
|
77
|
+
label?: string
|
|
78
|
+
}
|
|
79
|
+
|
|
39
80
|
interface GraphicsObject {
|
|
40
|
-
points?:
|
|
41
|
-
lines?:
|
|
42
|
-
rects?:
|
|
43
|
-
|
|
44
|
-
width: number
|
|
45
|
-
height: number
|
|
46
|
-
fill?: string
|
|
47
|
-
stroke?: string
|
|
48
|
-
}>
|
|
49
|
-
circles?: Array<{
|
|
50
|
-
center: { x: number; y: number }
|
|
51
|
-
radius: number
|
|
52
|
-
fill?: string
|
|
53
|
-
stroke?: string
|
|
54
|
-
}>
|
|
55
|
-
grid?: { cellSize: number; label?: boolean }
|
|
81
|
+
points?: Point[]
|
|
82
|
+
lines?: Line[]
|
|
83
|
+
rects?: Rect[]
|
|
84
|
+
circles?: Circle[]
|
|
56
85
|
coordinateSystem?: "cartesian" | "screen"
|
|
57
86
|
title?: string
|
|
58
87
|
}
|
|
@@ -131,6 +160,65 @@ const graphicsObjects = getGraphicsObjectsFromLogString(logString)
|
|
|
131
160
|
// Array<GraphicsObject>
|
|
132
161
|
```
|
|
133
162
|
|
|
163
|
+
### Generate SVG directly from a GraphicsObject
|
|
164
|
+
|
|
165
|
+
```tsx
|
|
166
|
+
import { getSvgFromGraphicsObject } from "graphics-debug"
|
|
167
|
+
|
|
168
|
+
// Create your graphics object
|
|
169
|
+
const graphicsObject = {
|
|
170
|
+
points: [{ x: 0, y: 0, label: "Origin" }, { x: 100, y: 100, color: "red" }],
|
|
171
|
+
lines: [{ points: [{ x: 0, y: 0 }, { x: 100, y: 100 }], strokeColor: "blue" }],
|
|
172
|
+
title: "My Graph"
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Generate SVG string directly from the object
|
|
176
|
+
const svg = getSvgFromGraphicsObject(graphicsObject)
|
|
177
|
+
// Returns a formatted SVG string ready to be written to a file or embedded in HTML
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Testing GraphicsObjects with Bun's Test Framework
|
|
181
|
+
|
|
182
|
+
If you're using Bun for testing, you can use the `toMatchGraphicsSvg` matcher to compare graphics objects against saved snapshots.
|
|
183
|
+
|
|
184
|
+
First, install the required peer dependencies:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
bun add -d bun-match-svg looksSame
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Then use the matcher in your tests:
|
|
191
|
+
|
|
192
|
+
```tsx
|
|
193
|
+
import { expect, test } from "bun:test"
|
|
194
|
+
import "graphics-debug/matcher"
|
|
195
|
+
import type { GraphicsObject } from "graphics-debug"
|
|
196
|
+
|
|
197
|
+
// Your test graphics object
|
|
198
|
+
const graphicsObject: GraphicsObject = {
|
|
199
|
+
points: [{ x: 0, y: 0, label: "Origin" }, { x: 100, y: 100, color: "red" }],
|
|
200
|
+
lines: [{ points: [{ x: 0, y: 0 }, { x: 100, y: 100 }], strokeColor: "blue" }],
|
|
201
|
+
title: "My Test Graphics"
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
test("should match the expected visualization", async () => {
|
|
205
|
+
// First run creates the snapshot
|
|
206
|
+
// Subsequent runs will compare against saved snapshot
|
|
207
|
+
await expect(graphicsObject).toMatchGraphicsSvg(import.meta.path)
|
|
208
|
+
|
|
209
|
+
// You can also provide a custom name for the snapshot:
|
|
210
|
+
await expect(graphicsObject).toMatchGraphicsSvg(import.meta.path, "custom-name")
|
|
211
|
+
})
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Snapshots are stored as SVG files in an `__snapshots__` directory next to your test file. To update snapshots, run your tests with the `-u` or `--update-snapshots` flag:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
bun test -u
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
This is powered by the same technology as bun-match-svg but integrated specifically for GraphicsObject testing.
|
|
221
|
+
|
|
134
222
|
### Example Graphics JSON
|
|
135
223
|
|
|
136
224
|
An example graphics JSON file is provided in the repository to help you get started quickly.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getSvgFromGraphicsObject
|
|
3
|
+
} from "../chunk-5FZF67ET.js";
|
|
4
|
+
|
|
5
|
+
// lib/matcher.ts
|
|
6
|
+
import { expect } from "bun:test";
|
|
7
|
+
import * as fs from "node:fs";
|
|
8
|
+
import * as path from "node:path";
|
|
9
|
+
import looksSame from "looks-same";
|
|
10
|
+
async function toMatchGraphicsSvg(receivedMaybePromise, testPathOriginal, svgName) {
|
|
11
|
+
const received = await receivedMaybePromise;
|
|
12
|
+
const testPath = testPathOriginal.replace(/\.test\.tsx?$/, "");
|
|
13
|
+
const snapshotDir = path.join(path.dirname(testPath), "__snapshots__");
|
|
14
|
+
const snapshotName = svgName ? `${svgName}.snap.svg` : `${path.basename(testPath)}.snap.svg`;
|
|
15
|
+
const filePath = path.join(snapshotDir, snapshotName);
|
|
16
|
+
if (!fs.existsSync(snapshotDir)) {
|
|
17
|
+
fs.mkdirSync(snapshotDir, { recursive: true });
|
|
18
|
+
}
|
|
19
|
+
const receivedSvg = getSvgFromGraphicsObject(received);
|
|
20
|
+
const updateSnapshot = process.argv.includes("--update-snapshots") || process.argv.includes("-u") || Boolean(process.env["BUN_UPDATE_SNAPSHOTS"]);
|
|
21
|
+
if (!fs.existsSync(filePath) || updateSnapshot) {
|
|
22
|
+
console.log("Writing snapshot to", filePath);
|
|
23
|
+
fs.writeFileSync(filePath, receivedSvg);
|
|
24
|
+
return {
|
|
25
|
+
message: () => `Snapshot created at ${filePath}`,
|
|
26
|
+
pass: true
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
const existingSnapshot = fs.readFileSync(filePath, "utf-8");
|
|
30
|
+
const result = await looksSame(
|
|
31
|
+
Buffer.from(receivedSvg),
|
|
32
|
+
Buffer.from(existingSnapshot),
|
|
33
|
+
{
|
|
34
|
+
strict: false,
|
|
35
|
+
tolerance: 2
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
if (result.equal) {
|
|
39
|
+
return {
|
|
40
|
+
message: () => "Snapshot matches",
|
|
41
|
+
pass: true
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
const diffPath = filePath.replace(".snap.svg", ".diff.png");
|
|
45
|
+
await looksSame.createDiff({
|
|
46
|
+
reference: Buffer.from(existingSnapshot),
|
|
47
|
+
current: Buffer.from(receivedSvg),
|
|
48
|
+
diff: diffPath,
|
|
49
|
+
highlightColor: "#ff00ff"
|
|
50
|
+
});
|
|
51
|
+
return {
|
|
52
|
+
message: () => `Snapshot does not match. Diff saved at ${diffPath}`,
|
|
53
|
+
pass: false
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
expect.extend({
|
|
57
|
+
// biome-ignore lint/suspicious/noExplicitAny: bun's types don't expose matcher type
|
|
58
|
+
toMatchGraphicsSvg
|
|
59
|
+
});
|
|
60
|
+
//# sourceMappingURL=matcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../lib/matcher.ts"],"sourcesContent":["import { expect, type MatcherResult } from \"bun:test\"\nimport * as fs from \"node:fs\"\nimport * as path from \"node:path\"\nimport looksSame from \"looks-same\"\nimport { GraphicsObject } from \"./types\"\nimport { getSvgFromGraphicsObject } from \"./getSvgFromGraphicsObject\"\n\n/**\n * Custom matcher for Bun tests to compare GraphicsObjects as SVGs\n * \n * @param this Matcher context\n * @param receivedMaybePromise GraphicsObject or Promise<GraphicsObject> to test\n * @param testPathOriginal Path to the test file\n * @param svgName Optional name for the snapshot\n * @returns Matcher result\n */\nasync function toMatchGraphicsSvg(\n // biome-ignore lint/suspicious/noExplicitAny: bun doesn't expose matcher type\n this: any,\n receivedMaybePromise: GraphicsObject | Promise<GraphicsObject>,\n testPathOriginal: string,\n svgName?: string,\n): Promise<MatcherResult> {\n const received = await receivedMaybePromise\n const testPath = testPathOriginal.replace(/\\.test\\.tsx?$/, \"\")\n const snapshotDir = path.join(path.dirname(testPath), \"__snapshots__\")\n const snapshotName = svgName\n ? `${svgName}.snap.svg`\n : `${path.basename(testPath)}.snap.svg`\n const filePath = path.join(snapshotDir, snapshotName)\n\n if (!fs.existsSync(snapshotDir)) {\n fs.mkdirSync(snapshotDir, { recursive: true })\n }\n\n // Convert GraphicsObject to SVG\n const receivedSvg = getSvgFromGraphicsObject(received)\n\n const updateSnapshot =\n process.argv.includes(\"--update-snapshots\") ||\n process.argv.includes(\"-u\") ||\n Boolean(process.env[\"BUN_UPDATE_SNAPSHOTS\"])\n\n if (!fs.existsSync(filePath) || updateSnapshot) {\n console.log(\"Writing snapshot to\", filePath)\n fs.writeFileSync(filePath, receivedSvg)\n return {\n message: () => `Snapshot created at ${filePath}`,\n pass: true,\n }\n }\n\n const existingSnapshot = fs.readFileSync(filePath, \"utf-8\")\n\n const result: any = await looksSame(\n Buffer.from(receivedSvg),\n Buffer.from(existingSnapshot),\n {\n strict: false,\n tolerance: 2,\n },\n )\n\n if (result.equal) {\n return {\n message: () => \"Snapshot matches\",\n pass: true,\n }\n }\n\n const diffPath = filePath.replace(\".snap.svg\", \".diff.png\")\n await looksSame.createDiff({\n reference: Buffer.from(existingSnapshot),\n current: Buffer.from(receivedSvg),\n diff: diffPath,\n highlightColor: \"#ff00ff\",\n })\n\n return {\n message: () => `Snapshot does not match. Diff saved at ${diffPath}`,\n pass: false,\n }\n}\n\n// Add the custom matcher to the expect object\nexpect.extend({\n // biome-ignore lint/suspicious/noExplicitAny: bun's types don't expose matcher type\n toMatchGraphicsSvg: toMatchGraphicsSvg as any,\n})\n\n// Extend the TypeScript interface for the matcher\ndeclare module \"bun:test\" {\n interface Matchers<T = unknown> {\n toMatchGraphicsSvg(\n testPath: string,\n svgName?: string,\n ): Promise<MatcherResult>\n }\n}"],"mappings":";;;;;AAAA,SAAS,cAAkC;AAC3C,YAAY,QAAQ;AACpB,YAAY,UAAU;AACtB,OAAO,eAAe;AAatB,eAAe,mBAGb,sBACA,kBACA,SACwB;AACxB,QAAM,WAAW,MAAM;AACvB,QAAM,WAAW,iBAAiB,QAAQ,iBAAiB,EAAE;AAC7D,QAAM,cAAmB,UAAU,aAAQ,QAAQ,GAAG,eAAe;AACrE,QAAM,eAAe,UACjB,GAAG,OAAO,cACV,GAAQ,cAAS,QAAQ,CAAC;AAC9B,QAAM,WAAgB,UAAK,aAAa,YAAY;AAEpD,MAAI,CAAI,cAAW,WAAW,GAAG;AAC/B,IAAG,aAAU,aAAa,EAAE,WAAW,KAAK,CAAC;AAAA,EAC/C;AAGA,QAAM,cAAc,yBAAyB,QAAQ;AAErD,QAAM,iBACJ,QAAQ,KAAK,SAAS,oBAAoB,KAC1C,QAAQ,KAAK,SAAS,IAAI,KAC1B,QAAQ,QAAQ,IAAI,sBAAsB,CAAC;AAE7C,MAAI,CAAI,cAAW,QAAQ,KAAK,gBAAgB;AAC9C,YAAQ,IAAI,uBAAuB,QAAQ;AAC3C,IAAG,iBAAc,UAAU,WAAW;AACtC,WAAO;AAAA,MACL,SAAS,MAAM,uBAAuB,QAAQ;AAAA,MAC9C,MAAM;AAAA,IACR;AAAA,EACF;AAEA,QAAM,mBAAsB,gBAAa,UAAU,OAAO;AAE1D,QAAM,SAAc,MAAM;AAAA,IACxB,OAAO,KAAK,WAAW;AAAA,IACvB,OAAO,KAAK,gBAAgB;AAAA,IAC5B;AAAA,MACE,QAAQ;AAAA,MACR,WAAW;AAAA,IACb;AAAA,EACF;AAEA,MAAI,OAAO,OAAO;AAChB,WAAO;AAAA,MACL,SAAS,MAAM;AAAA,MACf,MAAM;AAAA,IACR;AAAA,EACF;AAEA,QAAM,WAAW,SAAS,QAAQ,aAAa,WAAW;AAC1D,QAAM,UAAU,WAAW;AAAA,IACzB,WAAW,OAAO,KAAK,gBAAgB;AAAA,IACvC,SAAS,OAAO,KAAK,WAAW;AAAA,IAChC,MAAM;AAAA,IACN,gBAAgB;AAAA,EAClB,CAAC;AAED,SAAO;AAAA,IACL,SAAS,MAAM,0CAA0C,QAAQ;AAAA,IACjE,MAAM;AAAA,EACR;AACF;AAGA,OAAO,OAAO;AAAA;AAAA,EAEZ;AACF,CAAC;","names":[]}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "graphics-debug",
|
|
3
3
|
"main": "dist/lib/index.js",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.23",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist"
|
|
8
8
|
],
|
|
@@ -14,6 +14,10 @@
|
|
|
14
14
|
"./react": {
|
|
15
15
|
"types": "./dist/lib/react.d.ts",
|
|
16
16
|
"import": "./dist/lib/react.js"
|
|
17
|
+
},
|
|
18
|
+
"./matcher": {
|
|
19
|
+
"types": "./dist/lib/matcher.d.ts",
|
|
20
|
+
"import": "./dist/lib/matcher.js"
|
|
17
21
|
}
|
|
18
22
|
},
|
|
19
23
|
"bin": {
|
|
@@ -38,7 +42,6 @@
|
|
|
38
42
|
"@types/react": "^18.3.12",
|
|
39
43
|
"@types/react-dom": "^18.3.1",
|
|
40
44
|
"@vitejs/plugin-react": "^4.3.3",
|
|
41
|
-
"bun-match-svg": "^0.0.8",
|
|
42
45
|
"commander": "^12.1.0",
|
|
43
46
|
"debug": "^4.3.7",
|
|
44
47
|
"jsdom": "^25.0.1",
|
|
@@ -51,7 +54,9 @@
|
|
|
51
54
|
"vite-tsconfig-paths": "^5.1.4"
|
|
52
55
|
},
|
|
53
56
|
"peerDependencies": {
|
|
54
|
-
"typescript": "^5.0.0"
|
|
57
|
+
"typescript": "^5.0.0",
|
|
58
|
+
"bun-match-svg": "^0.0.9",
|
|
59
|
+
"looks-same": "^9.0.1"
|
|
55
60
|
},
|
|
56
61
|
"dependencies": {
|
|
57
62
|
"@types/react-router-dom": "^5.3.3",
|