codeschmiede-toolkit
Version:
A/B Test Development Toolkit
170 lines (137 loc) • 5.14 kB
JavaScript
'use strict';
const test = require('node:test');
const assert = require('node:assert/strict');
const fs = require('fs');
const os = require('os');
const path = require('path');
const { spawnSync } = require('child_process');
const { transformSource, processFile } = require('../lib/inline-html.cjs');
function evaluateValue(source) {
const fn = new Function(`${source}; return value;`);
return fn();
}
test('transforms mixed static and interpolated multiline template strings', () => {
const source = [
'const value = 5;',
'const markup = `<div>',
' <h1>Test Value</h1>',
' <p>${value}</p>',
'</div>`;',
].join('\n');
const expected = [
'const value = 5;',
'const markup = \'<div>\' +',
' \'<h1>Test Value</h1>\' +',
' `<p>${value}</p>` +',
' \'</div>\';',
].join('\n');
assert.equal(transformSource(source), expected);
});
test('keeps multiple interpolations on the same line intact', () => {
const source = [
'const value = 5;',
'const markup = `<p>${value}-${value + 1}</p>',
' <span>Static</span>`;',
].join('\n');
const expected = [
'const value = 5;',
'const markup = `<p>${value}-${value + 1}</p>` +',
' \'<span>Static</span>\';',
].join('\n');
assert.equal(transformSource(source), expected);
});
test('does not transform single-line template strings', () => {
const source = 'const value = `<div>${count}</div>`;';
assert.equal(transformSource(source), source);
});
test('removes only empty boundary lines and keeps inner blank lines', () => {
const source = [
'const value = `',
'',
' <div>',
'',
' <span>Value</span>',
' </div>',
'',
'`;',
].join('\n');
const expected = [
'const value = \'<div>\' +',
' \'\' +',
' \'<span>Value</span>\' +',
' \'</div>\';',
].join('\n');
assert.equal(transformSource(source), expected);
});
test('preserves runtime content for quotes, backticks and backslashes', () => {
const source = [
'const quote = "It\\\'s";',
'const tick = "tick";',
'const value = `<div class="${quote}">',
'Backslash \\\\ and \\`${tick}\\`',
'</div>`;',
].join('\n');
const transformed = transformSource(source);
assert.notEqual(transformed, source);
assert.equal(
evaluateValue(transformed),
'<div class="It\'s">Backslash \\ and `tick`</div>'
);
});
test('does not transform tagged template strings', () => {
const source = [
'const value = html`',
' <div>${count}</div>',
'`;',
].join('\n');
assert.equal(transformSource(source), source);
});
test('does not rewrite files when nothing changed', () => {
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'inlinehtml-unchanged-'));
const filePath = path.join(tempDir, 'example.js');
const source = 'const value = `<div>${count}</div>`;';
fs.writeFileSync(filePath, source, 'utf8');
const unchangedDate = new Date('2020-01-01T00:00:00.000Z');
fs.utimesSync(filePath, unchangedDate, unchangedDate);
const beforeStat = fs.statSync(filePath);
const result = processFile(filePath);
const afterStat = fs.statSync(filePath);
assert.equal(result.status, 'unchanged');
assert.equal(afterStat.mtimeMs, beforeStat.mtimeMs);
assert.equal(fs.readFileSync(filePath, 'utf8'), source);
});
test('reports parse errors and leaves the file untouched', () => {
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'inlinehtml-error-'));
const filePath = path.join(tempDir, 'broken.js');
const source = 'const value = `unterminated;\n';
fs.writeFileSync(filePath, source, 'utf8');
const result = processFile(filePath);
assert.equal(result.status, 'error');
assert.match(result.error.message, /Unterminated template/i);
assert.equal(fs.readFileSync(filePath, 'utf8'), source);
});
test('cli rewrites files in place and becomes a no-op on the second run', () => {
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'inlinehtml-cli-'));
const srcDir = path.join(tempDir, 'src');
const filePath = path.join(srcDir, 'variation-01.js');
fs.mkdirSync(srcDir);
fs.writeFileSync(filePath, [
'const value = 5;',
'const markup = `<div>',
' <p>${value}</p>',
'</div>`;',
].join('\n'), 'utf8');
const cliPath = path.resolve(__dirname, '../bin/inlinehtml.cjs');
const firstRun = spawnSync(process.execPath, [cliPath], {
cwd: tempDir,
encoding: 'utf8',
});
assert.equal(firstRun.status, 0, firstRun.stderr);
assert.match(firstRun.stdout, /updated src[\\/]+variation-01\.js/);
const secondRun = spawnSync(process.execPath, [cliPath], {
cwd: tempDir,
encoding: 'utf8',
});
assert.equal(secondRun.status, 0, secondRun.stderr);
assert.match(secondRun.stdout, /unchanged src[\\/]+variation-01\.js/);
});