feat(CI): modular testing and linting system + cursor rule

This commit is contained in:
2026-06-27 15:20:52 +09:30
parent 3213d0ca28
commit bdb1911e74
14 changed files with 114 additions and 69 deletions
+2 -8
View File
@@ -33,14 +33,8 @@ outputs:
runs: runs:
using: composite using: composite
steps: steps:
- name: Use Node.js 22.x - name: Setup Node and dependencies
uses: actions/setup-node@v4 uses: ./.github/actions/setup-node-deps
with:
node-version: 22.x
- name: Install dependencies
shell: bash
run: npm install --legacy-peer-deps
- name: Read version - name: Read version
id: version id: version
+11
View File
@@ -0,0 +1,11 @@
name: Run lint
description: Run ESLint on src.
runs:
using: composite
steps:
- name: Lint
shell: bash
run: npm run lint
env:
ESLINT_USE_FLAT_CONFIG: "false"
@@ -0,0 +1,9 @@
name: Run smoke tests
description: Verify built extension dist output.
runs:
using: composite
steps:
- name: Smoke tests
shell: bash
run: npm run test:smoke
@@ -0,0 +1,9 @@
name: Run unit tests
description: Run Jest unit tests.
runs:
using: composite
steps:
- name: Unit tests
shell: bash
run: npm run test:unit
@@ -0,0 +1,14 @@
name: Setup Node and dependencies
description: Install Node.js 22.x and npm dependencies.
runs:
using: composite
steps:
- name: Use Node.js 22.x
uses: actions/setup-node@v4
with:
node-version: 22.x
- name: Install dependencies
shell: bash
run: npm install --legacy-peer-deps
-36
View File
@@ -1,36 +0,0 @@
name: NodeJS Build
on:
push:
branches: ["main"]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [20.x]
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- name: Build
run: |
npm install --legacy-peer-deps
npm run build
- name: Zip dist folder
run: |
zip -r dist.zip dist
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: dist-zip
path: dist.zip
+31 -16
View File
@@ -1,11 +1,13 @@
name: PR CI name: CI
on: on:
pull_request: pull_request:
branches: ["main"] branches: ["main"]
push:
branches: ["main"]
jobs: jobs:
ci: lint:
# windows-latest: Vite/Svelte build fails on Linux CI for layerchart vendor .svelte (see nightly.yml). # windows-latest: Vite/Svelte build fails on Linux CI for layerchart vendor .svelte (see nightly.yml).
runs-on: windows-latest runs-on: windows-latest
defaults: defaults:
@@ -14,21 +16,34 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Use Node.js 22.x - name: Setup Node and dependencies
uses: actions/setup-node@v4 uses: ./.github/actions/setup-node-deps
with:
node-version: 22.x
- name: Install dependencies - name: Run lint
run: npm install --legacy-peer-deps uses: ./.github/actions/run-lint
- name: Lint unit-tests:
run: npm run lint runs-on: windows-latest
env: defaults:
ESLINT_USE_FLAT_CONFIG: "false" run:
shell: bash
steps:
- uses: actions/checkout@v4
- name: Unit tests - name: Setup Node and dependencies
run: npm test uses: ./.github/actions/setup-node-deps
- name: Run unit tests
uses: ./.github/actions/run-unit-tests
build-and-smoke:
needs: [lint, unit-tests]
runs-on: windows-latest
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
- name: Build extension - name: Build extension
id: build id: build
@@ -44,5 +59,5 @@ jobs:
${{ steps.build.outputs.chrome_zip }} ${{ steps.build.outputs.chrome_zip }}
${{ steps.build.outputs.firefox_zip }} ${{ steps.build.outputs.firefox_zip }}
- name: Smoke tests - name: Run smoke tests
run: npm run test:smoke uses: ./.github/actions/run-smoke-tests
+1
View File
@@ -17,6 +17,7 @@ export default {
'^@/(.*)$': '<rootDir>/src/$1', '^@/(.*)$': '<rootDir>/src/$1',
'^webextension-polyfill$': '<rootDir>/src/test/mocks/webextension-polyfill.ts', '^webextension-polyfill$': '<rootDir>/src/test/mocks/webextension-polyfill.ts',
}, },
setupFilesAfterEnv: ['<rootDir>/src/test/jest.setup.ts'],
moduleFileExtensions: ['ts', 'js', 'json'], moduleFileExtensions: ['ts', 'js', 'json'],
collectCoverageFrom: [ collectCoverageFrom: [
'src/**/*.ts', 'src/**/*.ts',
+4 -1
View File
@@ -19,8 +19,10 @@
"convert:safari": "xcrun safari-web-extension-converter dist/safari --project-location . --app-name $npm_package_name-safari", "convert:safari": "xcrun safari-web-extension-converter dist/safari --project-location . --app-name $npm_package_name-safari",
"dependency-graph": "depcruise src --include-only \"^src\" --output-type dot | dot -T svg > dependency-graph.svg", "dependency-graph": "depcruise src --include-only \"^src\" --output-type dot | dot -T svg > dependency-graph.svg",
"lint": "cross-env ESLINT_USE_FLAT_CONFIG=false eslint \"src/**/*.{js,ts}\"", "lint": "cross-env ESLINT_USE_FLAT_CONFIG=false eslint \"src/**/*.{js,ts}\"",
"test": "jest", "test": "npm run test:unit",
"test:unit": "jest",
"test:smoke": "node scripts/smoke-test.mjs", "test:smoke": "node scripts/smoke-test.mjs",
"test:ci": "npm run test:unit && npm run build && npm run test:smoke",
"release": "gh release create $npm_package_version --repo BetterSEQTA/BetterSEQTA-Plus ./dist/*.zip --generate-notes", "release": "gh release create $npm_package_version --repo BetterSEQTA/BetterSEQTA-Plus ./dist/*.zip --generate-notes",
"publish": "bun lib/publish.js --b", "publish": "bun lib/publish.js --b",
"zip": "bedframe zip" "zip": "bedframe zip"
@@ -58,6 +60,7 @@
"eslint-plugin-import": "^2.31.0", "eslint-plugin-import": "^2.31.0",
"glob": "^11.0.1", "glob": "^11.0.1",
"jest": "^30.4.2", "jest": "^30.4.2",
"jest-environment-jsdom": "^30.4.1",
"mime-types": "^3.0.1", "mime-types": "^3.0.1",
"prettier": "^3.5.3", "prettier": "^3.5.3",
"process": "^0.11.10", "process": "^0.11.10",
@@ -0,0 +1,12 @@
/**
* @jest-environment jsdom
*/
import { runGlobalSearchSelfTests } from "./selfTests";
describe("globalSearch selfTests", () => {
it("all in-process cases pass", async () => {
const report = await runGlobalSearchSelfTests();
expect(report.failed).toBe(0);
expect(report.failures).toEqual([]);
});
});
@@ -22,12 +22,10 @@ import {
/** /**
* Lightweight in-process self-tests for the global-search overhaul. * Lightweight in-process self-tests for the global-search overhaul.
* *
* The repository does not (yet) ship with a test runner, so we instead * Exposes a deterministic suite of assertions over the pure helpers that
* expose a deterministic suite of assertions over the pure helpers that * back active jobs and the passive observer. Runs in Jest via
* back active jobs and the passive observer. This is intentionally * `selfTests.test.ts`, and inside the extension page via
* dependency-free so it can run inside the extension page (`window. * `window.globalSearchDebug.runSelfTests()`.
* globalSearchDebug.runSelfTests()`) and from any future Vitest harness
* without modification.
*/ */
interface TestCase { interface TestCase {
@@ -141,7 +141,7 @@ export function htmlToPlainText(rawHtml: string): string {
} }
}); });
let text = body.innerText || ""; let text = body.textContent || body.innerText || "";
text = text text = text
.replace(/\u00A0/g, " ") .replace(/\u00A0/g, " ")
+5
View File
@@ -0,0 +1,5 @@
import { __resetBrowserStorageMock } from "./mocks/webextension-polyfill";
afterEach(() => {
__resetBrowserStorageMock();
});
+11 -1
View File
@@ -23,8 +23,16 @@ const local = {
}), }),
}; };
const onChanged = {
addListener: jest.fn(),
removeListener: jest.fn(),
};
export default { export default {
storage: { local }, storage: { local, onChanged },
runtime: {
sendMessage: jest.fn(async () => undefined),
},
}; };
export function __resetBrowserStorageMock() { export function __resetBrowserStorageMock() {
@@ -32,4 +40,6 @@ export function __resetBrowserStorageMock() {
local.get.mockClear(); local.get.mockClear();
local.set.mockClear(); local.set.mockClear();
local.remove.mockClear(); local.remove.mockClear();
onChanged.addListener.mockClear();
onChanged.removeListener.mockClear();
} }