Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions src/parsers/__tests__/json.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import assert from 'node:assert/strict';
import { describe, it, mock } from 'node:test';

let content;
mock.module('../../utils/parser.mjs', {
namedExports: {
loadFromURL: async () => content,
},
});

const { parseTypeMap } = await import('../json.mjs');

describe('parseTypeMap', () => {
it('should return an empty object when path is falsy', async () => {
for (const falsy of [undefined, null, '']) {
assert.deepStrictEqual(await parseTypeMap(falsy), {});
}
});

it('should parse and return the JSON content from a given path', async () => {
content = JSON.stringify({ Buffer: 'buffer.md', fs: 'fs.md' });
const result = await parseTypeMap('/some/path/types.json');
assert.deepStrictEqual(result, { Buffer: 'buffer.md', fs: 'fs.md' });
});

it('should throw a SyntaxError when content is not valid JSON', async () => {
content = 'not valid json';
await assert.rejects(
() => parseTypeMap('/some/path/types.json'),
SyntaxError
);
});
});
96 changes: 95 additions & 1 deletion src/utils/__tests__/generators.test.mjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import { describe, it, mock, afterEach } from 'node:test';

import {
groupNodesByModule,
getVersionFromSemVer,
coerceSemVer,
getCompatibleVersions,
legacyToJSON,
buildApiDocURL,
createLazyGenerator,
} from '../generators.mjs';

describe('groupNodesByModule', () => {
Expand Down Expand Up @@ -79,3 +82,94 @@ describe('getCompatibleVersions', () => {
assert.equal(result.length, 2);
});
});

describe('legacyToJSON', () => {
const base = {
type: 'module',
source: 'lib/fs.js',
introduced_in: 'v0.10.0',
meta: {},
stability: 2,
stabilityText: 'Stable',
classes: [],
methods: ['readFile'],
properties: [],
miscs: [],
modules: ['fs'],
globals: [],
};

it('serialises a normal section with all keys', () => {
const result = JSON.parse(legacyToJSON({ ...base, api: 'fs' }));
assert.ok('type' in result);
assert.ok('methods' in result);
assert.ok('modules' in result);
});

it('omits modules key for index sections', () => {
const result = JSON.parse(legacyToJSON({ ...base, api: 'index' }));
assert.ok(!('modules' in result));
});

it('uses all.json key order when api is null', () => {
const result = JSON.parse(legacyToJSON({ ...base, api: null }));
// all.json only includes miscs, modules, classes, globals, methods
assert.ok('miscs' in result);
assert.ok('modules' in result);
assert.ok(!('type' in result));
assert.ok(!('source' in result));
});

it('passes extra args to JSON.stringify (e.g. indentation)', () => {
const result = legacyToJSON({ ...base, api: 'fs' }, null, 2);
assert.ok(result.includes('\n'));
});
});

describe('buildApiDocURL', () => {
const entry = { api: 'fs' };
const base = 'https://nodejs.org';

it('builds a .md URL by default', () => {
const url = buildApiDocURL(entry, base);
assert.ok(url instanceof URL);
assert.ok(url.pathname.endsWith('.md'));
assert.ok(url.pathname.includes('/fs'));
});

it('builds a .html URL when useHtml is true', () => {
const url = buildApiDocURL(entry, base, true);
assert.ok(url.pathname.endsWith('.html'));
});
});

describe('createLazyGenerator', () => {
afterEach(() => mock.restoreAll());

it('spreads metadata properties onto the returned object', () => {
const metadata = { name: 'ast', version: '1.0.0', dependsOn: undefined };
const gen = createLazyGenerator(metadata);
assert.equal(gen.name, 'ast');
assert.equal(gen.version, '1.0.0');
});

it('exposes generate and processChunk functions that delegate to the lazily loaded module', async () => {
// Both exports are mocked in a single mock.module() call to avoid ESM import
// cache collisions that occur when re-mocking the same specifier across two it() blocks.
const specifier = import.meta.resolve('../../generators/ast/generate.mjs');
const fakeGenerate = async input => `processed:${input}`;
const fakeProcessChunk = async (input, indices) =>
indices.map(i => input[i]);
mock.module(specifier, {
namedExports: { generate: fakeGenerate, processChunk: fakeProcessChunk },
});

const gen = createLazyGenerator({ name: 'ast' });

const generateResult = await gen.generate('hello');
assert.equal(generateResult, 'processed:hello');

const processChunkResult = await gen.processChunk(['a', 'b', 'c'], [0, 2]);
assert.deepStrictEqual(processChunkResult, ['a', 'c']);
});
});
53 changes: 53 additions & 0 deletions src/utils/__tests__/url.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import assert from 'node:assert/strict';
import { describe, it, mock, afterEach } from 'node:test';

let fileContent = 'hello from file';
mock.module('node:fs/promises', {
namedExports: {
readFile: async () => fileContent,
},
});

const { toParsedURL, loadFromURL } = await import('../url.mjs');

describe('toParsedURL', () => {
it('should return the same URL instance when given a URL object', () => {
const url = new URL('https://nodejs.org');
assert.strictEqual(toParsedURL(url), url);
});

it('should parse a valid URL string into a URL object', () => {
const result = toParsedURL('https://nodejs.org/api');
assert.ok(result instanceof URL);
assert.strictEqual(result.hostname, 'nodejs.org');
});

it('should return null for a string that cannot be parsed as a URL', () => {
assert.strictEqual(toParsedURL('not-a-url'), null);
});
});

describe('loadFromURL', () => {
afterEach(() => mock.restoreAll());

it('should read content from the filesystem for a plain file path', async () => {
fileContent = 'file content';
const result = await loadFromURL('/some/path/file.txt');
assert.strictEqual(result, 'file content');
});

it('should read content from the filesystem for a file: URL', async () => {
fileContent = 'from file url';
const result = await loadFromURL(new URL('file:///some/file.txt'));
assert.strictEqual(result, 'from file url');
});

it('should fetch content from an http URL', async () => {
mock.method(globalThis, 'fetch', async () => ({
text: async () => 'fetched content',
}));

const result = await loadFromURL('https://nodejs.org/data.txt');
assert.strictEqual(result, 'fetched content');
});
});
Loading