From f1c41e7079e5b377c900829782266aca993a8c04 Mon Sep 17 00:00:00 2001 From: Albrecht Degering Date: Wed, 2 Sep 2026 13:00:37 +0200 Subject: [PATCH] Release Fixture Tools 0.2.0 --- .gitea/workflows/verify.yml | 39 ++ CHANGELOG.md | 5 + README.md | 16 +- SOURCE.md | 4 +- THIRD_PARTY_NOTICES.md | 8 +- package-lock.json | 38 +- package.json | 10 +- playwright.config.ts | 22 +- public/CHANGELOG.md | 5 + public/LICENSES/npm-runtime-licenses.txt | 6 +- public/README.md | 16 +- public/SOURCE.md | 4 +- public/THIRD_PARTY_NOTICES.md | 8 +- public/sw.js | 2 +- public/toolbox-app.json | 18 +- src/components/Workbench.tsx | 65 ++- src/fixture/model.ts | 674 ++++++++++++++++++++--- src/toolbox/manifest.source.json | 48 +- src/version.ts | 2 +- tests/browser/app.spec.ts | 23 +- tests/browser/responsive.spec.ts | 18 + tests/fixture/model.test.ts | 102 ++++ 22 files changed, 1007 insertions(+), 126 deletions(-) create mode 100644 .gitea/workflows/verify.yml create mode 100644 tests/browser/responsive.spec.ts diff --git a/.gitea/workflows/verify.yml b/.gitea/workflows/verify.yml new file mode 100644 index 0000000..b84a7cb --- /dev/null +++ b/.gitea/workflows/verify.yml @@ -0,0 +1,39 @@ +name: Verify + +on: + push: + branches: [main] + pull_request: + workflow_dispatch: + +concurrency: + group: verify-${{ gitea.repository }}-${{ gitea.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + verify: + runs-on: ubuntu-latest + timeout-minutes: 45 + env: + CI: "true" + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "22" + cache: npm + - name: Select declared npm version + run: npm install --global npm@11.17.0 + - name: Install dependencies + run: npm ci + - name: Audit runtime dependencies + run: npm audit --omit=dev --audit-level=moderate + - name: Check, test, and build + run: npm run check + - name: Install browser engines + run: npx playwright install --with-deps chromium firefox webkit + - name: Browser tests + run: npm run test:browser diff --git a/CHANGELOG.md b/CHANGELOG.md index 7873a33..2f23f27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 0.2.0 - 2026-09-02 + +- Add reusable provider definitions, richer relational constraints and + deterministic cross-table generation with explicit violation evidence. + ## 0.1.0 - 2026-09-01 - Add bounded JSON Schema, SQL DDL, XSD, CSV-heading, and fixture-recipe import diff --git a/README.md b/README.md index 48da292..d7c2b1a 100644 --- a/README.md +++ b/README.md @@ -3,18 +3,25 @@ Generate deterministic, privacy-safe synthetic test fixtures entirely in the browser. Fixture Tools is a local-first module in the add·ideas Toolbox. -## v0.1.0 capabilities +## v0.2.0 capabilities - Import a focused subset of JSON Schema, SQL `CREATE TABLE` DDL, XSD, CSV headings, or the app's portable fixture-model JSON - Review and edit normalized tables, fields, types, required/unique rules, - numeric and length ranges, enumerations, and foreign-key relationships + numeric and length ranges, enumerations, scalar foreign keys, composite + unique constraints, and composite foreign-key relationships - Generate reproducible rows from a text seed with uniform, sequential, normal, and constant distributions - Deliberately exercise boundary values or inject invalid values, with a separate violation ledger so negative-test fixtures cannot be mistaken for valid data - Preserve referential integrity and field uniqueness for valid generated rows +- Generate tables in a deterministic dependency-topological order, with an + explicit error for cyclic references +- Audit positive, boundary and intentional-negative exercise counts in a + constraint coverage matrix +- Select deterministic provider profiles (person, network, commerce), with a + typed extension point for additional local profiles - Export JSON, spreadsheet-safe CSV, NDJSON, XML, SQL `INSERT` statements, or a reusable fixture recipe - Use only reserved example domains for generated email addresses @@ -24,8 +31,9 @@ browser. Fixture Tools is a local-first module in the add·ideas Toolbox. The importers normalize common declarative constructs; they are not complete JSON Schema, SQL, or XML Schema validators. Remote references, schema code, database connections, XML entities, XSD `choice`/identity constraints, SQL -dialects beyond common table/column clauses, and production-scale data loads are -out of scope in v0.1.0. +dialects beyond common table/column clauses, cyclic relational recipes, and +production-scale data loads are out of scope in v0.2.0. Coverage counts describe +generated exercises; they do not prove schema or application coverage. Inputs are capped at 2 MiB. A recipe can contain at most 20 tables and 100 fields per table; generation is capped at 50,000 total rows and 8 MiB per diff --git a/SOURCE.md b/SOURCE.md index 1ee0821..77ee5a1 100644 --- a/SOURCE.md +++ b/SOURCE.md @@ -1,7 +1,7 @@ # Corresponding source -The corresponding source for Fixture Tools 0.1.0 is available at: +The corresponding source for Fixture Tools 0.2.0 is available at: -https://git.add-ideas.de/lotobo/fixture-tools/src/tag/v0.1.0 +https://git.add-ideas.de/lotobo/fixture-tools/src/tag/v0.2.0 Build with Node.js 22, npm 11, `npm ci`, and `npm run release:artifact`. diff --git a/THIRD_PARTY_NOTICES.md b/THIRD_PARTY_NOTICES.md index 840b1e8..0e9815a 100644 --- a/THIRD_PARTY_NOTICES.md +++ b/THIRD_PARTY_NOTICES.md @@ -1,12 +1,12 @@ # Third-party notices -Fixture Tools 0.1.0 directly depends on these runtime packages: +Fixture Tools 0.2.0 directly depends on these runtime packages: | Package | Pinned version | Declared licence | | -------------------------------- | -------------: | ---------------- | -| `@add-ideas/toolbox-contract` | 0.2.3 | Apache-2.0 | -| `@add-ideas/toolbox-helpers` | 0.1.0 | GPL-3.0-or-later | -| `@add-ideas/toolbox-shell-react` | 0.2.3 | Apache-2.0 | +| `@add-ideas/toolbox-contract` | 0.3.0 | Apache-2.0 | +| `@add-ideas/toolbox-helpers` | 0.2.0 | GPL-3.0-or-later | +| `@add-ideas/toolbox-shell-react` | 0.3.0 | Apache-2.0 | | `react` | 19.2.8 | MIT | | `react-dom` | 19.2.8 | MIT | diff --git a/package-lock.json b/package-lock.json index 77adb69..4b6328c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,22 +1,22 @@ { "name": "fixture-tools", - "version": "0.1.0", + "version": "0.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "fixture-tools", - "version": "0.1.0", + "version": "0.2.0", "license": "GPL-3.0-or-later", "dependencies": { - "@add-ideas/toolbox-contract": "0.2.3", - "@add-ideas/toolbox-helpers": "0.1.0", - "@add-ideas/toolbox-shell-react": "0.2.3", + "@add-ideas/toolbox-contract": "0.3.0", + "@add-ideas/toolbox-helpers": "0.2.0", + "@add-ideas/toolbox-shell-react": "0.3.0", "react": "19.2.8", "react-dom": "19.2.8" }, "devDependencies": { - "@add-ideas/toolbox-testkit": "0.2.3", + "@add-ideas/toolbox-testkit": "0.3.0", "@eslint/js": "10.0.1", "@playwright/test": "1.62.1", "@testing-library/jest-dom": "6.9.1", @@ -42,24 +42,25 @@ } }, "node_modules/@add-ideas/toolbox-contract": { - "version": "0.2.3", - "license": "Apache-2.0", - "engines": { - "node": ">=20" - } + "version": "0.3.0", + "resolved": "https://git.add-ideas.de/api/packages/lotobo/npm/%40add-ideas%2Ftoolbox-contract/-/0.3.0/toolbox-contract-0.3.0.tgz", + "integrity": "sha512-dKrK7BjOFwqJaBfJuhKxZKIld4sH0AKjEn6a0yLnbdMUFY+fFv4VSLGV2tNSBD016gumc2iNqOjUj/ld7x4rtA==", + "license": "Apache-2.0" }, "node_modules/@add-ideas/toolbox-helpers": { - "version": "0.1.0", + "version": "0.2.0", "license": "GPL-3.0-or-later", "engines": { "node": ">=22" } }, "node_modules/@add-ideas/toolbox-shell-react": { - "version": "0.2.3", + "version": "0.3.0", + "resolved": "https://git.add-ideas.de/api/packages/lotobo/npm/%40add-ideas%2Ftoolbox-shell-react/-/0.3.0/toolbox-shell-react-0.3.0.tgz", + "integrity": "sha512-74p6JzAOG0YCAKdlc1hLofV4ZIko7vb448S75cIiM88PKm93EHl5VD7g8YVyfM56Ui97UY9dmy+Whiq4sGzpsg==", "license": "Apache-2.0", "dependencies": { - "@add-ideas/toolbox-contract": "0.2.3" + "@add-ideas/toolbox-contract": "0.3.0" }, "peerDependencies": { "react": ">=18 <20", @@ -67,17 +68,16 @@ } }, "node_modules/@add-ideas/toolbox-testkit": { - "version": "0.2.3", + "version": "0.3.0", + "resolved": "https://git.add-ideas.de/api/packages/lotobo/npm/%40add-ideas%2Ftoolbox-testkit/-/0.3.0/toolbox-testkit-0.3.0.tgz", + "integrity": "sha512-4Fk+oSvZFspOMIXr8Xy040nhAaBsIQAzsGyXWSpjn3+k3yBKq7nB1r5zCHhsXzfdLzvPDAx2KcmSNOhM330D9w==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@add-ideas/toolbox-contract": "0.2.3" + "@add-ideas/toolbox-contract": "0.3.0" }, "bin": { "toolbox-check": "dist/cli.js" - }, - "engines": { - "node": ">=20" } }, "node_modules/@adobe/css-tools": { diff --git a/package.json b/package.json index 67b410a..21b9ca4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "fixture-tools", - "version": "0.1.0", + "version": "0.2.0", "description": "Generate deterministic, privacy-safe synthetic test fixtures locally in the browser.", "license": "GPL-3.0-or-later", "author": "Albrecht Degering", @@ -39,14 +39,14 @@ "release:artifact": "npm run check && npm run test:browser && npm run package:release -- --force" }, "dependencies": { - "@add-ideas/toolbox-contract": "0.2.3", - "@add-ideas/toolbox-helpers": "0.1.0", - "@add-ideas/toolbox-shell-react": "0.2.3", + "@add-ideas/toolbox-contract": "0.3.0", + "@add-ideas/toolbox-helpers": "0.2.0", + "@add-ideas/toolbox-shell-react": "0.3.0", "react": "19.2.8", "react-dom": "19.2.8" }, "devDependencies": { - "@add-ideas/toolbox-testkit": "0.2.3", + "@add-ideas/toolbox-testkit": "0.3.0", "@eslint/js": "10.0.1", "@playwright/test": "1.62.1", "@testing-library/jest-dom": "6.9.1", diff --git a/playwright.config.ts b/playwright.config.ts index 2ffeb92..ecc11f8 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -15,7 +15,25 @@ export default defineConfig({ timeout: 180_000, }, projects: [ - { name: "chromium", use: { ...devices["Desktop Chrome"] } }, - { name: "firefox", use: { ...devices["Desktop Firefox"] } }, + { + name: "chromium", + testIgnore: /responsive\.spec\.ts/, + use: { ...devices["Desktop Chrome"] }, + }, + { + name: "firefox", + testIgnore: /responsive\.spec\.ts/, + use: { ...devices["Desktop Firefox"] }, + }, + { + name: "webkit", + testIgnore: /responsive\.spec\.ts/, + use: { ...devices["Desktop Safari"] }, + }, + { + name: "mobile-chromium", + testMatch: /responsive\.spec\.ts/, + use: { ...devices["Pixel 5"] }, + }, ], }); diff --git a/public/CHANGELOG.md b/public/CHANGELOG.md index 7873a33..2f23f27 100644 --- a/public/CHANGELOG.md +++ b/public/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +## 0.2.0 - 2026-09-02 + +- Add reusable provider definitions, richer relational constraints and + deterministic cross-table generation with explicit violation evidence. + ## 0.1.0 - 2026-09-01 - Add bounded JSON Schema, SQL DDL, XSD, CSV-heading, and fixture-recipe import diff --git a/public/LICENSES/npm-runtime-licenses.txt b/public/LICENSES/npm-runtime-licenses.txt index 45a7c95..4f412f1 100644 --- a/public/LICENSES/npm-runtime-licenses.txt +++ b/public/LICENSES/npm-runtime-licenses.txt @@ -1,5 +1,5 @@ ============================================================================== -@add-ideas/toolbox-contract@0.2.3 +@add-ideas/toolbox-contract@0.3.0 Declared licence: Apache-2.0 ============================================================================== --- LICENSE --- @@ -198,7 +198,7 @@ Declared licence: Apache-2.0 ============================================================================== -@add-ideas/toolbox-helpers@0.1.0 +@add-ideas/toolbox-helpers@0.2.0 Declared licence: GPL-3.0-or-later ============================================================================== --- LICENSE --- @@ -879,7 +879,7 @@ Public License instead of this License. But first, please read ============================================================================== -@add-ideas/toolbox-shell-react@0.2.3 +@add-ideas/toolbox-shell-react@0.3.0 Declared licence: Apache-2.0 ============================================================================== --- LICENSE --- diff --git a/public/README.md b/public/README.md index 48da292..d7c2b1a 100644 --- a/public/README.md +++ b/public/README.md @@ -3,18 +3,25 @@ Generate deterministic, privacy-safe synthetic test fixtures entirely in the browser. Fixture Tools is a local-first module in the add·ideas Toolbox. -## v0.1.0 capabilities +## v0.2.0 capabilities - Import a focused subset of JSON Schema, SQL `CREATE TABLE` DDL, XSD, CSV headings, or the app's portable fixture-model JSON - Review and edit normalized tables, fields, types, required/unique rules, - numeric and length ranges, enumerations, and foreign-key relationships + numeric and length ranges, enumerations, scalar foreign keys, composite + unique constraints, and composite foreign-key relationships - Generate reproducible rows from a text seed with uniform, sequential, normal, and constant distributions - Deliberately exercise boundary values or inject invalid values, with a separate violation ledger so negative-test fixtures cannot be mistaken for valid data - Preserve referential integrity and field uniqueness for valid generated rows +- Generate tables in a deterministic dependency-topological order, with an + explicit error for cyclic references +- Audit positive, boundary and intentional-negative exercise counts in a + constraint coverage matrix +- Select deterministic provider profiles (person, network, commerce), with a + typed extension point for additional local profiles - Export JSON, spreadsheet-safe CSV, NDJSON, XML, SQL `INSERT` statements, or a reusable fixture recipe - Use only reserved example domains for generated email addresses @@ -24,8 +31,9 @@ browser. Fixture Tools is a local-first module in the add·ideas Toolbox. The importers normalize common declarative constructs; they are not complete JSON Schema, SQL, or XML Schema validators. Remote references, schema code, database connections, XML entities, XSD `choice`/identity constraints, SQL -dialects beyond common table/column clauses, and production-scale data loads are -out of scope in v0.1.0. +dialects beyond common table/column clauses, cyclic relational recipes, and +production-scale data loads are out of scope in v0.2.0. Coverage counts describe +generated exercises; they do not prove schema or application coverage. Inputs are capped at 2 MiB. A recipe can contain at most 20 tables and 100 fields per table; generation is capped at 50,000 total rows and 8 MiB per diff --git a/public/SOURCE.md b/public/SOURCE.md index 1ee0821..77ee5a1 100644 --- a/public/SOURCE.md +++ b/public/SOURCE.md @@ -1,7 +1,7 @@ # Corresponding source -The corresponding source for Fixture Tools 0.1.0 is available at: +The corresponding source for Fixture Tools 0.2.0 is available at: -https://git.add-ideas.de/lotobo/fixture-tools/src/tag/v0.1.0 +https://git.add-ideas.de/lotobo/fixture-tools/src/tag/v0.2.0 Build with Node.js 22, npm 11, `npm ci`, and `npm run release:artifact`. diff --git a/public/THIRD_PARTY_NOTICES.md b/public/THIRD_PARTY_NOTICES.md index 840b1e8..0e9815a 100644 --- a/public/THIRD_PARTY_NOTICES.md +++ b/public/THIRD_PARTY_NOTICES.md @@ -1,12 +1,12 @@ # Third-party notices -Fixture Tools 0.1.0 directly depends on these runtime packages: +Fixture Tools 0.2.0 directly depends on these runtime packages: | Package | Pinned version | Declared licence | | -------------------------------- | -------------: | ---------------- | -| `@add-ideas/toolbox-contract` | 0.2.3 | Apache-2.0 | -| `@add-ideas/toolbox-helpers` | 0.1.0 | GPL-3.0-or-later | -| `@add-ideas/toolbox-shell-react` | 0.2.3 | Apache-2.0 | +| `@add-ideas/toolbox-contract` | 0.3.0 | Apache-2.0 | +| `@add-ideas/toolbox-helpers` | 0.2.0 | GPL-3.0-or-later | +| `@add-ideas/toolbox-shell-react` | 0.3.0 | Apache-2.0 | | `react` | 19.2.8 | MIT | | `react-dom` | 19.2.8 | MIT | diff --git a/public/sw.js b/public/sw.js index f33bd3f..92cdc9d 100644 --- a/public/sw.js +++ b/public/sw.js @@ -1,5 +1,5 @@ const CACHE_PREFIX = "fixture-tools-shell-"; -const CACHE_NAME = CACHE_PREFIX + "0.1.0"; +const CACHE_NAME = CACHE_PREFIX + "0.2.0"; const CORE = ["./", "./manifest.webmanifest", "./favicon.svg"]; self.addEventListener("install", (event) => { event.waitUntil( diff --git a/public/toolbox-app.json b/public/toolbox-app.json index 8db1252..af49990 100644 --- a/public/toolbox-app.json +++ b/public/toolbox-app.json @@ -3,7 +3,7 @@ "schemaVersion": 1, "id": "de.add-ideas.fixture-tools", "name": "Fixture Tools", - "version": "0.1.0", + "version": "0.2.0", "description": "Generate deterministic synthetic test data locally.", "entry": "./", "icon": "./favicon.svg", @@ -21,6 +21,22 @@ "crossOriginIsolated": false, "topLevelContext": false }, + "io": { + "accepts": [ + { "mediaType": "application/schema+json", "extensions": [".json"] }, + { "mediaType": "application/sql", "extensions": [".sql"] }, + { "mediaType": "application/xml", "extensions": [".xsd", ".xml"] }, + { "mediaType": "text/csv", "extensions": [".csv"] } + ], + "produces": [ + { "mediaType": "application/json", "extensions": [".json"] }, + { "mediaType": "application/x-ndjson", "extensions": [".ndjson"] }, + { "mediaType": "text/csv", "extensions": [".csv"] }, + { "mediaType": "application/xml", "extensions": [".xml"] }, + { "mediaType": "application/sql", "extensions": [".sql"] } + ] + }, + "capabilities": { "required": [], "optional": [] }, "privacy": { "processing": "local", "fileUploads": true, diff --git a/src/components/Workbench.tsx b/src/components/Workbench.tsx index 3589391..9c8fe3d 100644 --- a/src/components/Workbench.tsx +++ b/src/components/Workbench.tsx @@ -38,7 +38,7 @@ const initialDataset = generateFixtures(initialParsed.model, { invalidPercent: 0, }); -type View = "model" | "data" | "violations"; +type View = "model" | "data" | "coverage" | "violations"; const TYPES: FixtureType[] = [ "string", "integer", @@ -334,6 +334,7 @@ export function Workbench() { const [rows, setRows] = useState(8); const [boundaryPercent, setBoundaryPercent] = useState(10); const [invalidPercent, setInvalidPercent] = useState(0); + const [providerProfile, setProviderProfile] = useState("auto"); const [selectedTable, setSelectedTable] = useState(model.tables[0]!.name); const [outputFormat, setOutputFormat] = useState("json"); const [view, setView] = useState("data"); @@ -381,6 +382,7 @@ export function Workbench() { rows, boundaryPercent, invalidPercent, + providerProfile, }); setModel(validated); setDataset(next); @@ -584,6 +586,18 @@ export function Workbench() { } /> + @@ -591,7 +605,7 @@ export function Workbench() {