Skip to content

coverage: increase to ~47% #309

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 5, 2025
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import assert from 'node:assert/strict';
import { describe, it } from 'node:test';

import { generateFileList } from '../generateFileList.mjs';

describe('generateFileList', () => {
it('should transform test.js files with updated require paths', () => {
const codeBlocks = [
{
name: 'test.js',
content: "const addon = require('./build/Release/addon');",
},
];

const result = generateFileList(codeBlocks);
const testFile = result.find(file => file.name === 'test.js');

assert(testFile.content.includes("'use strict';"));
assert(testFile.content.includes('`./build/${common.buildType}/addon`'));
assert(!testFile.content.includes("'./build/Release/addon'"));
});

it('should preserve other files unchanged', () => {
const codeBlocks = [{ name: 'addon.cc', content: '#include <node.h>' }];

const result = generateFileList(codeBlocks);

assert.equal(
result.find(file => file.name === 'addon.cc').content,
'#include <node.h>'
);
});

it('should add binding.gyp file', () => {
const codeBlocks = [{ name: 'addon.cc', content: 'code' }];

const result = generateFileList(codeBlocks);
const bindingFile = result.find(file => file.name === 'binding.gyp');

assert(bindingFile);
const config = JSON.parse(bindingFile.content);
assert.equal(config.targets[0].target_name, 'addon');
assert(config.targets[0].sources.includes('addon.cc'));
});

it('should handle empty input', () => {
const result = generateFileList([]);

assert.equal(result.length, 1);
assert.equal(result[0].name, 'binding.gyp');
});
});
74 changes: 74 additions & 0 deletions src/generators/addon-verify/utils/__tests__/section.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import assert from 'node:assert/strict';
import { describe, it } from 'node:test';

import {
isBuildableSection,
normalizeSectionName,
generateSectionFolderName,
} from '../section.mjs';

describe('isBuildableSection', () => {
it('should return true when both .cc and .js files are present', () => {
const codeBlocks = [
{ name: 'addon.cc', content: 'C++ code' },
{ name: 'test.js', content: 'JS code' },
];

assert.equal(isBuildableSection(codeBlocks), true);
});

it('should return false when only .cc file is present', () => {
const codeBlocks = [{ name: 'addon.cc', content: 'C++ code' }];

assert.equal(isBuildableSection(codeBlocks), false);
});

it('should return false when only .js file is present', () => {
const codeBlocks = [{ name: 'test.js', content: 'JS code' }];

assert.equal(isBuildableSection(codeBlocks), false);
});

it('should return false for empty array', () => {
assert.equal(isBuildableSection([]), false);
});
});

describe('normalizeSectionName', () => {
it('should convert to lowercase and replace spaces with underscores', () => {
assert.equal(normalizeSectionName('Hello World'), 'hello_world');
});

it('should remove non-word characters', () => {
assert.equal(normalizeSectionName('Test-Section!@#'), 'testsection');
});

it('should handle empty string', () => {
assert.equal(normalizeSectionName(''), '');
});

it('should handle mixed cases and special characters', () => {
assert.equal(
normalizeSectionName('My Test & Example #1'),
'my_test__example_1'
);
});
});

describe('generateSectionFolderName', () => {
it('should generate folder name with padded index', () => {
assert.equal(generateSectionFolderName('hello_world', 0), '01_hello_world');
});

it('should pad single digit indices', () => {
assert.equal(generateSectionFolderName('test', 5), '06_test');
});

it('should not pad double digit indices', () => {
assert.equal(generateSectionFolderName('example', 15), '16_example');
});

it('should handle empty section name', () => {
assert.equal(generateSectionFolderName('', 0), '01_');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import assert from 'node:assert/strict';
import { describe, it } from 'node:test';

import { findParent, buildHierarchy } from '../buildHierarchy.mjs';

describe('findParent', () => {
it('finds parent with lower depth', () => {
const entries = [{ heading: { depth: 1 } }, { heading: { depth: 2 } }];
const parent = findParent(entries[1], entries, 0);
assert.equal(parent, entries[0]);
});

it('throws when no parent exists', () => {
const entries = [{ heading: { depth: 2 } }];
assert.throws(() => findParent(entries[0], entries, -1));
});
});

describe('buildHierarchy', () => {
it('returns empty array for empty input', () => {
assert.deepEqual(buildHierarchy([]), []);
});

it('keeps root entries at top level', () => {
const entries = [{ heading: { depth: 1 } }, { heading: { depth: 1 } }];
const result = buildHierarchy(entries);
assert.equal(result.length, 2);
});

it('nests children under parents', () => {
const entries = [{ heading: { depth: 1 } }, { heading: { depth: 2 } }];
const result = buildHierarchy(entries);

assert.equal(result.length, 1);
assert.equal(result[0].hierarchyChildren.length, 1);
assert.equal(result[0].hierarchyChildren[0], entries[1]);
});

it('handles multiple levels', () => {
const entries = [
{ heading: { depth: 1 } },
{ heading: { depth: 2 } },
{ heading: { depth: 3 } },
];
const result = buildHierarchy(entries);

assert.equal(result.length, 1);
assert.equal(result[0].hierarchyChildren[0].hierarchyChildren.length, 1);
});
});
126 changes: 126 additions & 0 deletions src/generators/legacy-json/utils/__tests__/parseList.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import assert from 'node:assert/strict';
import { describe, it } from 'node:test';

import {
transformTypeReferences,
extractPattern,
parseListItem,
parseList,
} from '../parseList.mjs';

describe('transformTypeReferences', () => {
it('replaces template syntax with curly braces', () => {
const result = transformTypeReferences('`<string>`');
assert.equal(result, '{string}');
});

it('normalizes multiple types', () => {
const result = transformTypeReferences('`<string>` | `<number>`');
assert.equal(result, '{string|number}');
});
});

describe('extractPattern', () => {
it('extracts pattern and removes from text', () => {
const current = {};
const result = extractPattern(
'name: test description',
/name:\s*([^.\s]+)/,
'name',
current
);

assert.equal(current.name, 'test');
assert.equal(result, ' description');
});

it('returns original text when pattern not found', () => {
const current = {};
const result = extractPattern(
'no match',
/missing:\s*([^.]+)/,
'missing',
current
);

assert.equal(result, 'no match');
assert.equal(current.missing, undefined);
});
});

describe('parseListItem', () => {
it('parses basic list item', () => {
const child = {
children: [
{
type: 'paragraph',
children: [{ type: 'text', value: 'param {string} description' }],
},
],
};

const result = parseListItem(child);
assert.equal(typeof result, 'object');
assert.ok(result.textRaw);
});

it('identifies return items', () => {
const child = {
children: [
{
type: 'paragraph',
children: [{ type: 'text', value: 'Returns: something' }],
},
],
};

const result = parseListItem(child);
assert.equal(result.name, 'return');
});
});

describe('parseList', () => {
it('processes property sections', () => {
const section = { type: 'property', name: 'test' };
const nodes = [
{
type: 'list',
children: [
{
children: [
{
type: 'paragraph',
children: [{ type: 'text', value: '{string} description' }],
},
],
},
],
},
];

parseList(section, nodes);
assert.ok(section.textRaw);
});

it('processes event sections', () => {
const section = { type: 'event' };
const nodes = [
{
type: 'list',
children: [
{
children: [
{
type: 'paragraph',
children: [{ type: 'text', value: 'param description' }],
},
],
},
],
},
];

parseList(section, nodes);
assert.ok(Array.isArray(section.params));
});
});
Loading
Loading