Skip to content

Commit c7a9aa4

Browse files
committed
fix unit tests
1 parent 199ff6e commit c7a9aa4

File tree

6 files changed

+146
-30
lines changed

6 files changed

+146
-30
lines changed

packages/rehype-shiki/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@
77
},
88
"scripts": {
99
"lint:js": "eslint \"**/*.mjs\"",
10-
"test": "node --test"
10+
"test": "turbo test:unit",
11+
"test:unit": "node --experimental-test-module-mocks --test \"**/*.test.mjs\""
1112
},
1213
"dependencies": {
1314
"@shikijs/core": "^3.3.0",
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
import assert from 'node:assert/strict';
2+
import { describe, it, mock } from 'node:test';
3+
4+
// Mock dependencies
5+
const mockShiki = {
6+
codeToHtml: mock.fn(() => '<pre><code>highlighted code</code></pre>'),
7+
codeToHast: mock.fn(() => ({ type: 'element', tagName: 'pre' })),
8+
};
9+
10+
mock.module('@shikijs/core', {
11+
namedExports: { createHighlighterCoreSync: () => mockShiki },
12+
});
13+
14+
mock.module('@shikijs/engine-javascript', {
15+
namedExports: { createJavaScriptRegexEngine: () => ({}) },
16+
});
17+
18+
mock.module('shiki/themes/nord.mjs', {
19+
defaultExport: { name: 'nord', colors: { 'editor.background': '#2e3440' } },
20+
});
21+
22+
describe('createHighlighter', async () => {
23+
const { createHighlighter } = await import('../highlighter.mjs');
24+
25+
describe('getLanguageDisplayName', () => {
26+
it('returns display name for known languages', () => {
27+
const langs = [
28+
{ name: 'javascript', displayName: 'JavaScript', aliases: ['js'] },
29+
];
30+
const highlighter = createHighlighter({ langs });
31+
32+
assert.strictEqual(
33+
highlighter.getLanguageDisplayName('javascript'),
34+
'JavaScript'
35+
);
36+
assert.strictEqual(
37+
highlighter.getLanguageDisplayName('js'),
38+
'JavaScript'
39+
);
40+
});
41+
42+
it('returns original name for unknown languages', () => {
43+
const highlighter = createHighlighter({ langs: [] });
44+
assert.strictEqual(
45+
highlighter.getLanguageDisplayName('unknown'),
46+
'unknown'
47+
);
48+
});
49+
});
50+
51+
describe('highlightToHtml', () => {
52+
it('extracts inner HTML from code tag', () => {
53+
mockShiki.codeToHtml.mock.mockImplementationOnce(
54+
() => '<pre><code>const x = 1;</code></pre>'
55+
);
56+
57+
const highlighter = createHighlighter({});
58+
const result = highlighter.highlightToHtml('const x = 1;', 'javascript');
59+
60+
assert.strictEqual(result, 'const x = 1;');
61+
});
62+
});
63+
64+
describe('highlightToHast', () => {
65+
it('returns HAST tree from shiki', () => {
66+
const expectedHast = { type: 'element', tagName: 'pre' };
67+
mockShiki.codeToHast.mock.mockImplementationOnce(() => expectedHast);
68+
69+
const highlighter = createHighlighter({});
70+
const result = highlighter.highlightToHast('code', 'javascript');
71+
72+
assert.deepStrictEqual(result, expectedHast);
73+
});
74+
});
75+
});

packages/rehype-shiki/src/__tests__/languages.test.mjs

Lines changed: 0 additions & 27 deletions
This file was deleted.
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import assert from 'node:assert/strict';
2+
import { describe, it, mock } from 'node:test';
3+
4+
// Simplified mocks - only mock what's actually needed
5+
mock.module('../index.mjs', {
6+
namedExports: { highlightToHast: mock.fn(() => ({ children: [] })) },
7+
});
8+
9+
mock.module('classnames', {
10+
defaultExport: (...args) => args.filter(Boolean).join(' '),
11+
});
12+
13+
mock.module('hast-util-to-string', {
14+
namedExports: { toString: () => 'code' },
15+
});
16+
17+
const mockVisit = mock.fn();
18+
mock.module('unist-util-visit', {
19+
namedExports: { visit: mockVisit, SKIP: Symbol() },
20+
});
21+
22+
describe('rehypeShikiji', async () => {
23+
const { default: rehypeShikiji } = await import('../plugin.mjs');
24+
const mockTree = { type: 'root', children: [] };
25+
26+
it('calls visit twice', () => {
27+
mockVisit.mock.resetCalls();
28+
rehypeShikiji()(mockTree);
29+
assert.strictEqual(mockVisit.mock.calls.length, 2);
30+
});
31+
32+
it('creates CodeTabs for multiple code blocks', () => {
33+
const parent = {
34+
children: [
35+
{
36+
tagName: 'pre',
37+
children: [
38+
{
39+
tagName: 'code',
40+
data: { meta: 'displayName="JS"' },
41+
properties: { className: ['language-js'] },
42+
},
43+
],
44+
},
45+
{
46+
tagName: 'pre',
47+
children: [
48+
{
49+
tagName: 'code',
50+
data: { meta: 'displayName="TS"' },
51+
properties: { className: ['language-ts'] },
52+
},
53+
],
54+
},
55+
],
56+
};
57+
58+
mockVisit.mock.mockImplementation((tree, selector, visitor) => {
59+
if (selector === 'element') {
60+
visitor(parent.children[0], 0, parent);
61+
}
62+
});
63+
64+
rehypeShikiji()(mockTree);
65+
assert.ok(parent.children.some(child => child.tagName === 'CodeTabs'));
66+
});
67+
});

packages/rehype-shiki/src/plugin.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import classNames from 'classnames';
44
import { toString } from 'hast-util-to-string';
55
import { SKIP, visit } from 'unist-util-visit';
66

7-
import { highlightToHast } from '.';
7+
import { highlightToHast } from './index.mjs';
88

99
// This is what Remark will use as prefix within a <pre> className
1010
// to attribute the current language of the <pre> element

packages/rehype-shiki/turbo.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"lint:js": {
77
"inputs": ["src/**/*.mjs"]
88
},
9-
"test": {
9+
"test:unit": {
1010
"inputs": ["src/**/*.mjs"]
1111
}
1212
}

0 commit comments

Comments
 (0)