Skip to content

Commit 8d30282

Browse files
Add Jest configuration and unit tests for interlinearizer feature
- Introduced Jest configuration in `jest.config.ts` and setup file in `jest.setup.ts` for testing. - Added unit tests for the `interlinearizer.web-view` component , `InterlinearXmlParser`, and `main` in `src/__tests__/`. - Created mocks for static assets and dependencies to facilitate testing. - Updated ESLint and Prettier configurations to ignore Jest-related files and directories. - Enhanced README to document the new testing structure and usage. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent eb5578f commit 8d30282

26 files changed

Lines changed: 2507 additions & 171 deletions

.eslintignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ dist
2929
release
3030
temp-build
3131

32+
# Jest
33+
__mocks__
34+
coverage
35+
3236
# generated files
3337
package-lock.json
3438

.eslintrc.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,14 @@ module.exports = {
155155
'import/no-self-import': 'off',
156156
},
157157
},
158+
{
159+
// Jest globals (describe, it, expect, etc.) so ESLint does not report no-undef
160+
files: ['**/*.test.{ts,tsx}', '**/*.spec.{ts,tsx}', '**/__tests__/**/*.{ts,tsx}'],
161+
plugins: ['jest'],
162+
env: {
163+
'jest/globals': true,
164+
},
165+
},
158166
],
159167
parserOptions: {
160168
ecmaVersion: 2022,
@@ -163,7 +171,7 @@ module.exports = {
163171
tsconfigRootDir: __dirname,
164172
createDefaultProgram: true,
165173
},
166-
plugins: ['@typescript-eslint', 'no-type-assertion', 'no-null'],
174+
plugins: ['@typescript-eslint', 'jest', 'no-type-assertion', 'no-null'],
167175
settings: {
168176
'import/resolver': {
169177
typescript: {

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ dist
1414
release
1515
dist-ssr
1616
*.local
17+
coverage
1718

1819
# formatting and linting
1920
.eslintcache

.prettierignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ dist
2929
release
3030
temp-build
3131

32+
# Jest
33+
__mocks__
34+
coverage
35+
3236
# generated files
3337
package-lock.json
3438

.stylelintignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ dist
2929
release
3030
temp-build
3131

32+
# Jest
33+
__mocks__
34+
coverage
35+
3236
# generated files
3337
package-lock.json
3438

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ The general file structure for an extension is as follows:
9999
- `*.web-view.tsx` files will be treated as React WebViews
100100
- `*.web-view.scss` files provide styles for WebViews
101101
- `*.web-view.html` files are a conventional way to provide HTML WebViews (no special functionality)
102+
- `src/__tests__/` contains unit tests (Jest) for the extension, including parser tests and web-view tests
103+
- `__mocks__/` contains Jest mocks for the PAPI, file modules, and test fixtures used by tests in `src/__tests__/`
102104
- `assets/` contains asset files the extension and its WebViews can retrieve using the `papi-extension:` protocol, as well as textual descriptions in various languages. It is copied into the build folder
103105
- `assets/displayData.json` contains (optionally) a path to the extension's icon file as well as text for the extension's display name, short summary, and path to the full description file
104106
- `assets/descriptions/` contains textual descriptions of the extension in various languages

__mocks__/@papi/backend.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* Jest manual mock for @papi/backend. Jest auto-applies this when tests call
3+
* jest.mock('@papi/backend'). Provides papi and logger so main.ts can be unit-tested without the
4+
* real Platform API.
5+
*
6+
* Main.ts uses: import papi, { logger } from '@papi/backend'
7+
*/
8+
9+
const mockRegisterWebViewProvider = jest.fn().mockResolvedValue({ dispose: jest.fn() });
10+
const mockOpenWebView = jest.fn().mockResolvedValue(undefined);
11+
const mockLogger = {
12+
debug: jest.fn(),
13+
error: jest.fn(),
14+
info: jest.fn(),
15+
warn: jest.fn(),
16+
};
17+
18+
const papi = {
19+
webViewProviders: {
20+
registerWebViewProvider: mockRegisterWebViewProvider,
21+
},
22+
webViews: {
23+
openWebView: mockOpenWebView,
24+
},
25+
};
26+
27+
module.exports = {
28+
__mockRegisterWebViewProvider: mockRegisterWebViewProvider,
29+
__mockOpenWebView: mockOpenWebView,
30+
__mockLogger: mockLogger,
31+
default: papi,
32+
logger: mockLogger,
33+
};

__mocks__/fileMock.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* Jest mock for static asset imports (images, fonts, etc.). Importing e.g. `logo.png` in tests will
3+
* receive this string instead of running file loaders. Mirrors webpack's asset/inline and
4+
* asset/resource handling in webpack.config.base.
5+
*
6+
* @see https://jestjs.io/docs/webpack#handling-static-assets
7+
*/
8+
module.exports = 'test-file-stub';

__mocks__/interlinearXmlContent.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/**
2+
* Jest mock for webpack ?raw XML import. Exports the contents of test-data/Interlinear_en_MAT.xml
3+
* so interlinearizer.web-view.tsx can parse it in unit tests without webpack.
4+
*/
5+
const fs = require('fs');
6+
const path = require('path');
7+
8+
const xmlPath = path.join(__dirname, '..', 'test-data', 'Interlinear_en_MAT.xml');
9+
module.exports = fs.readFileSync(xmlPath, 'utf-8');

__mocks__/papi-backend.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* Jest mock for @papi/backend. Provides papi and logger so main.ts can be unit-tested without
3+
* loading the real Platform API.
4+
*
5+
* Main.ts uses: import papi, { logger } from '@papi/backend' With esModuleInterop, default export
6+
* must be the papi object; logger as named export.
7+
*/
8+
9+
const mockRegisterWebViewProvider = jest.fn().mockResolvedValue({ dispose: jest.fn() });
10+
const mockOpenWebView = jest.fn().mockResolvedValue(undefined);
11+
const mockLogger = {
12+
debug: jest.fn(),
13+
error: jest.fn(),
14+
info: jest.fn(),
15+
warn: jest.fn(),
16+
};
17+
18+
const papi = {
19+
webViewProviders: {
20+
registerWebViewProvider: mockRegisterWebViewProvider,
21+
},
22+
webViews: {
23+
openWebView: mockOpenWebView,
24+
},
25+
};
26+
27+
module.exports = {
28+
__mockRegisterWebViewProvider: mockRegisterWebViewProvider,
29+
__mockOpenWebView: mockOpenWebView,
30+
__mockLogger: mockLogger,
31+
default: papi,
32+
logger: mockLogger,
33+
};

0 commit comments

Comments
 (0)