mirror of
https://github.com/penpot/penpot.git
synced 2026-07-24 23:18:06 +00:00
* ✨ Add plugin with composable test framework and component tests The plugin provides a framework for writing composable tests against the Plugin API, and applies it to systematic end-to-end testing of component semantics. The framework's core ideas: a test is written once as a composition of operations over a starting configuration; choice points among the operations (optional steps, alternatives) expand the composition into a full sweep of test variants, so a single case definition yields broad combinatorial coverage; and the operations drive the real Plugin API with real change propagation, testing the full production implementation. The initial application is a suite of component test cases covering synchronization, overrides, swap slots and variants — the TypeScript/e2e continuation of the ClojureScript composable test suite (frontend_tests.composable_tests). Several cases originate from reproducing real defects (e.g. #10109 and the swap-slot corruptions). Tests run from an interactive panel in Penpot: cases are listed with plain-language descriptions, tests can be run selectively, results stream in live, and every checkbox carries a stable DOM id — so the panel can equally be driven programmatically (the basis for running the suite in CI), as documented in the plugin's README. Lives at plugins/apps/composable-test-suite as a regular member of the plugins workspace (init script, start:plugin:composable-test-suite, shared dev port 4202, covered by build:plugins via the new ./apps/*-test-suite filter). Related to #10584. AI-assisted-by: claude-fable-5 * ✨ Run the composable test suite headlessly in CI Adds a headless run mode for the composable test suite, following the plugin-api-test-suite's CI architecture, and a workflow that runs it as a per-PR gate. An in-sandbox entry (src/ci/headless.ts) runs the suite without the panel UI — the framework's runner was UI-free by construction, so no refactoring was needed — and streams each result through console markers, addressed by the same composite identifiers the panel uses (e.g. MainEditSyncs-2), with durations and, on failure, the error and the applied-steps transcript. It is built as a single self-executing bundle and evaluated directly inside a real Penpot plugin sandbox by the driver (ci/run-ci.ts), so no plugin dev server or port is involved. The driver needs no backend and no login: it serves the prebuilt frontend bundle via the frontend e2e static server and intercepts every backend RPC with Playwright fixtures. The mocked backend is not a limitation for this suite — everything it asserts is frontend store logic executed in memory — which the full run confirms: all 48 tests behave identically to the interactive panel, including variants and swap slots, with the single (currently expected) failure of MainEditSyncs-2 reproducing bug #10109 under the mock. TEST_FILTER selects tests by identifier substring; CI_TIMEOUT_MS bounds the run. The mock harness mirrors the frontend e2e harness (see the provenance note in the driver). Related to #10584. AI-assisted-by: claude-fable-5 * 📚 Restructure the composable-tests memory around both suites Present the composable component tests top-down: the shared framework principles upfront, then the two implementations — the ClojureScript suite in the frontend test tree and the TypeScript suite in the plugin, which tests fully end-to-end with a slightly more elaborate set of abstractions — and the plugin's headless CI run, pointing to the plugin's README for operational details. Also records this session's additions (geometry operations, case N, the CI harness). AI-assisted-by: claude-fable-5 * 📎 Refine the PR-description conventions in the creating-prs memory Encourage digestible descriptions: bullet items over prose (grouped by area with bold lead-ins for larger PRs) and no manual line wraps, since the rendered markdown adapts to the viewport. Also drop the outdated 'MCP' from the standard Note line. AI-assisted-by: claude-fable-5 * 🔧 Set Prettier endOfLine to auto in plugins workspace Prettier defaults to endOfLine "lf", which is incompatible with checkouts on Windows that use core.autocrlf=true * 🐛 Fix problems with suite --------- Co-authored-by: alonso.torres <alonso.torres@kaleidos.net>
99 lines
4.2 KiB
JSON
99 lines
4.2 KiB
JSON
{
|
|
"name": "penpot-plugins",
|
|
"version": "0.6.0",
|
|
"type": "module",
|
|
"license": "MIT",
|
|
"packageManager": "pnpm@11.9.0+sha512.bd682d5d03fe525ef7c9fd6780c6884d1e756ac4c9c9fe00c538782824310dcf90e3ddc4f53835f06dfaebd5085e41855e0bcbb3b60de2ac5bbab89e5036f03b",
|
|
"scripts": {
|
|
"start": "pnpm run start:app:runtime",
|
|
"start:app:runtime": "concurrently --kill-others --names build,server \"pnpm --filter @penpot/plugins-runtime run build:watch\" \"pnpm --filter @penpot/plugins-runtime run preview\"",
|
|
"start:app:styles-example": "pnpm --filter example-styles dev",
|
|
"start:plugin:poc-state": "pnpm --filter poc-state-plugin run init",
|
|
"start:plugin:contrast": "pnpm --filter contrast-plugin run init",
|
|
"start:plugin:icons": "pnpm --filter icons-plugin run init",
|
|
"start:plugin:loremipsum": "pnpm --filter lorem-ipsum-plugin run init",
|
|
"start:plugin:palette": "pnpm --filter create-palette-plugin run init",
|
|
"start:plugin:table": "pnpm --filter table-plugin run init",
|
|
"start:plugin:renamelayers": "pnpm --filter rename-layers-plugin run init",
|
|
"start:plugin:colors-to-tokens": "pnpm --filter colors-to-tokens-plugin run init",
|
|
"start:plugin:poc-tokens": "pnpm --filter poc-tokens-plugin run init",
|
|
"start:plugin:api-test-suite": "pnpm --filter plugin-api-test-suite run init",
|
|
"start:plugin:composable-test-suite": "pnpm --filter composable-test-suite run init",
|
|
"build:runtime": "pnpm --filter @penpot/plugins-runtime build",
|
|
"build:plugins": "pnpm --parallel --filter './apps/*-plugin' --filter './apps/*-test-suite' --filter '!poc-state-plugin' build",
|
|
"build:styles-example": "pnpm --filter example-styles build",
|
|
"lint": "pnpm -r --parallel lint",
|
|
"format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md,html,css}\"",
|
|
"format:check": "prettier --check \"**/*.{ts,tsx,js,jsx,json,md,html,css}\"",
|
|
"test": "pnpm --filter @penpot/plugins-runtime --filter lorem-ipsum-plugin --filter colors-to-tokens-plugin test",
|
|
"test:e2e": "pnpm --filter e2e test",
|
|
"build:doc": "typedoc --tsconfig libs/plugins-runtime/tsconfig.lib.json --customCss ./tools/typedoc.css --out dist/doc",
|
|
"release": "tsx ./tools/scripts/publish.ts"
|
|
},
|
|
"private": true,
|
|
"devDependencies": {
|
|
"@angular-devkit/core": "22.0.4",
|
|
"@angular-devkit/schematics": "22.0.4",
|
|
"@angular-eslint/eslint-plugin": "22.0.0",
|
|
"@angular-eslint/eslint-plugin-template": "22.0.0",
|
|
"@angular-eslint/template-parser": "22.0.0",
|
|
"@angular/build": "22.0.4",
|
|
"@angular/cli": "22.0.4",
|
|
"@angular/compiler-cli": "22.0.4",
|
|
"@angular/language-service": "22.0.4",
|
|
"@eslint/js": "10.0.1",
|
|
"@schematics/angular": "22.0.4",
|
|
"@types/feather-icons": "^4.29.4",
|
|
"@types/node": "26.0.1",
|
|
"@types/yargs": "^17.0.35",
|
|
"@typescript-eslint/eslint-plugin": "8.62.1",
|
|
"@typescript-eslint/parser": "8.62.1",
|
|
"@typescript-eslint/utils": "^8.62.1",
|
|
"@vitest/coverage-v8": "4.1.9",
|
|
"@vitest/ui": "4.1.9",
|
|
"concurrently": "^10.0.3",
|
|
"dotenv": "^17.4.2",
|
|
"esbuild": "^0.28.1",
|
|
"eslint": "10.6.0",
|
|
"eslint-config-prettier": "10.1.8",
|
|
"eslint-plugin-import": "2.32.0",
|
|
"eslint-plugin-jsx-a11y": "6.10.2",
|
|
"eslint-plugin-react": "7.37.5",
|
|
"eslint-plugin-react-hooks": "7.1.1",
|
|
"eslint-plugin-unused-imports": "^4.4.1",
|
|
"fs-extra": "^11.3.6",
|
|
"globals": "^17.7.0",
|
|
"happy-dom": "^20.10.6",
|
|
"jiti": "2.7.0",
|
|
"jsdom": "~29.1.1",
|
|
"jsonc-eslint-parser": "^3.1.0",
|
|
"prettier": "^3.9.4",
|
|
"tsx": "^4.22.4",
|
|
"typedoc": "^0.28.19",
|
|
"typescript": "6.0.3",
|
|
"typescript-eslint": "^8.62.1",
|
|
"vite": "8.1.1",
|
|
"vite-plugin-checker": "^0.14.4",
|
|
"vite-plugin-dts": "5.0.3",
|
|
"vite-plugin-static-copy": "^4.1.1",
|
|
"vitest": "4.1.9",
|
|
"yargs": "^18.0.0"
|
|
},
|
|
"dependencies": {
|
|
"@angular/common": "22.0.4",
|
|
"@angular/compiler": "22.0.4",
|
|
"@angular/core": "22.0.4",
|
|
"@angular/forms": "22.0.4",
|
|
"@angular/platform-browser": "22.0.4",
|
|
"@angular/router": "22.0.4",
|
|
"axios": "^1.18.1",
|
|
"feather-icons": "^4.29.2",
|
|
"puppeteer": "^25.2.1",
|
|
"rxjs": "~7.8.2",
|
|
"ses": "^2.2.0",
|
|
"tslib": "^2.8.1",
|
|
"zod": "^4.4.3",
|
|
"zone.js": "0.16.2"
|
|
}
|
|
}
|