Skip to content

Commit 2d37129

Browse files
committed
feat(ci): add CI configuration and coverage tests for ArtoolkitPlugin
1 parent 1c3d015 commit 2d37129

File tree

3 files changed

+101
-6
lines changed

3 files changed

+101
-6
lines changed

.github/workflows/build.yml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches:
6+
- '**'
7+
pull_request:
8+
branches:
9+
- '**'
10+
11+
jobs:
12+
build-and-test:
13+
runs-on: ubuntu-latest
14+
steps:
15+
- name: Checkout
16+
uses: actions/checkout@v4
17+
18+
- name: Setup Node
19+
uses: actions/setup-node@v4
20+
with:
21+
node-version-file: .nvmrc
22+
cache: npm
23+
24+
- name: Install
25+
run: npm ci
26+
27+
- name: Build
28+
run: npm run build
29+
30+
- name: Test with coverage
31+
run: npm run coverage

tests/plugin.more.spec.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { describe, it, expect, vi, beforeEach } from 'vitest';
2+
import { ArtoolkitPlugin } from '../src/plugin.js';
3+
import { createEventBus } from './setupTests';
4+
5+
describe('ArtoolkitPlugin (more coverage)', () => {
6+
let core: { eventBus: ReturnType<typeof createEventBus> };
7+
8+
beforeEach(() => {
9+
core = { eventBus: createEventBus() };
10+
});
11+
12+
it('disable() removes handlers and terminates worker', async () => {
13+
const plugin = new ArtoolkitPlugin({ worker: true });
14+
await plugin.init(core);
15+
16+
// Fake a browser worker with spies
17+
const addEventListener = vi.fn();
18+
const removeEventListener = vi.fn();
19+
const terminate = vi.fn();
20+
// @ts-ignore
21+
plugin._worker = { addEventListener, removeEventListener, terminate, postMessage: vi.fn() };
22+
23+
await plugin.enable();
24+
// Simulate that we added a message listener during start
25+
expect(typeof plugin.enabled).toBe('boolean');
26+
27+
await plugin.disable();
28+
29+
expect(removeEventListener).toHaveBeenCalledWith('message', expect.any(Function));
30+
expect(terminate).toHaveBeenCalledTimes(1);
31+
});
32+
33+
it('engine:update falls back when postMessage throws', async () => {
34+
const plugin = new ArtoolkitPlugin({ worker: true });
35+
await plugin.init(core);
36+
37+
const postMessage = vi.fn(() => { throw new Error('boom'); });
38+
// @ts-ignore
39+
plugin._worker = { postMessage };
40+
41+
// No throw should propagate
42+
// @ts-ignore call private
43+
plugin._onEngineUpdate({ id: 99, imageBitmap: {} as ImageBitmap, width: 2, height: 2 });
44+
45+
// Fallback tries a second post without ImageBitmap, so we expect at least one call
46+
expect(postMessage).toHaveBeenCalled();
47+
});
48+
49+
it('getMarkerState returns null when marker not tracked', async () => {
50+
const plugin = new ArtoolkitPlugin({ worker: false });
51+
await plugin.init(core);
52+
expect(plugin.getMarkerState(12345)).toBeNull();
53+
});
54+
55+
it('detectionResult with no detections is safely ignored', async () => {
56+
const plugin = new ArtoolkitPlugin({ worker: false });
57+
await plugin.init(core);
58+
await plugin.enable();
59+
60+
// @ts-ignore
61+
plugin._onWorkerMessage({ data: { type: 'detectionResult', payload: {} } });
62+
63+
// No exception; no markers added
64+
expect(plugin.getMarkerState(1)).toBeNull();
65+
});
66+
});

vitest.config.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,12 @@ export default defineConfig({
88
provider: 'v8',
99
all: true,
1010
include: ['src/**/*.js'],
11-
// Exclude files that are either pure re-exports or not yet unit-testable (worker)
1211
exclude: ['src/worker/**', 'src/index.js'],
1312
thresholds: {
14-
// Slightly relaxed thresholds while we build out more tests
15-
lines: 50,
16-
statements: 50,
17-
branches: 40,
18-
functions: 50,
13+
lines: 65,
14+
statements: 65,
15+
branches: 50,
16+
functions: 65,
1917
},
2018
},
2119
},

0 commit comments

Comments
 (0)