v0.3.1 with Saxon fully working
This commit is contained in:
122
tests/transformEngines.test.ts
Normal file
122
tests/transformEngines.test.ts
Normal file
@@ -0,0 +1,122 @@
|
||||
import { beforeAll, describe, expect, it } from 'vitest';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { resolve } from 'node:path';
|
||||
import vm from 'node:vm';
|
||||
import {
|
||||
availableTransformEngines,
|
||||
runTransformation,
|
||||
} from '../src/transform/transformService';
|
||||
import { compileXsltTextToSefJson } from '../src/transform/saxonJsDynamicCompiler';
|
||||
|
||||
const xmlText = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<library>
|
||||
<book id="b1"><title>Practical XSLT</title><author>Ada</author></book>
|
||||
<book id="b2"><title>Browser XML</title><author>Lin</author></book>
|
||||
</library>`;
|
||||
|
||||
const xslt10Text = `<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
<xsl:output method="xml" omit-xml-declaration="yes"/>
|
||||
<xsl:template match="/library">
|
||||
<titles><xsl:for-each select="book"><title><xsl:value-of select="title"/></title></xsl:for-each></titles>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>`;
|
||||
|
||||
const xslt20Text = `<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
<xsl:output method="xml" omit-xml-declaration="yes"/>
|
||||
<xsl:template match="/library">
|
||||
<books><xsl:value-of select="upper-case(string-join(book/title, '|'))"/></books>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>`;
|
||||
|
||||
const xslt30Text = `<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
<xsl:output method="xml" omit-xml-declaration="yes"/>
|
||||
<xsl:mode on-no-match="shallow-copy"/>
|
||||
<xsl:template match="book/title/text()">
|
||||
<xsl:value-of select="upper-case(.)"/>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>`;
|
||||
|
||||
beforeAll(() => {
|
||||
if (window.SaxonJS) return;
|
||||
|
||||
const scriptPath = resolve(process.cwd(), 'public/vendor/saxon/SaxonJS2.js');
|
||||
const script = readFileSync(scriptPath, 'utf8');
|
||||
vm.runInContext(script, vm.createContext(window));
|
||||
});
|
||||
|
||||
describe('transform engine registry', () => {
|
||||
it('keeps the native browser XSLTProcessor engine selectable', () => {
|
||||
expect(availableTransformEngines.map((engine) => engine.id)).toContain(
|
||||
'native-xsltprocessor'
|
||||
);
|
||||
});
|
||||
|
||||
it('exposes the dynamic SaxonJS engine for XSLT 2.0/3.0', () => {
|
||||
expect(availableTransformEngines.map((engine) => engine.id)).toContain(
|
||||
'saxon-js-dynamic'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('SaxonJS dynamic compiler', () => {
|
||||
it('compiles raw XSLT text to SEF JSON', async () => {
|
||||
const sef = await compileXsltTextToSefJson(xslt30Text);
|
||||
const parsed = JSON.parse(sef) as { N?: string; target?: string };
|
||||
|
||||
expect(parsed.N).toBe('package');
|
||||
expect(parsed.target).toBe('JS');
|
||||
});
|
||||
|
||||
it('runs an XSLT 1.0 stylesheet', async () => {
|
||||
const result = await runTransformation({
|
||||
xmlText,
|
||||
xsltText: xslt10Text,
|
||||
engine: 'saxon-js-dynamic',
|
||||
});
|
||||
|
||||
expect(
|
||||
result.diagnostics.filter((item) => item.severity === 'error')
|
||||
).toHaveLength(0);
|
||||
expect(result.output).toContain('<title>Practical XSLT</title>');
|
||||
expect(result.output).toContain('<title>Browser XML</title>');
|
||||
});
|
||||
|
||||
it('runs an XSLT 2.0 stylesheet with XPath 2.0 functions', async () => {
|
||||
const result = await runTransformation({
|
||||
xmlText,
|
||||
xsltText: xslt20Text,
|
||||
engine: 'saxon-js-dynamic',
|
||||
});
|
||||
|
||||
expect(
|
||||
result.diagnostics.filter((item) => item.severity === 'error')
|
||||
).toHaveLength(0);
|
||||
expect(result.output).toContain('PRACTICAL XSLT|BROWSER XML');
|
||||
});
|
||||
|
||||
it('runs an XSLT 3.0 stylesheet with xsl:mode on-no-match', async () => {
|
||||
const result = await runTransformation({
|
||||
xmlText,
|
||||
xsltText: xslt30Text,
|
||||
engine: 'saxon-js-dynamic',
|
||||
});
|
||||
|
||||
expect(
|
||||
result.diagnostics.filter((item) => item.severity === 'error')
|
||||
).toHaveLength(0);
|
||||
expect(result.output).toContain('<title>PRACTICAL XSLT</title>');
|
||||
expect(result.output).toContain('<title>BROWSER XML</title>');
|
||||
});
|
||||
|
||||
it('returns diagnostics for invalid XSLT', async () => {
|
||||
const result = await runTransformation({
|
||||
xmlText,
|
||||
xsltText: '<xsl:stylesheet version="3.0">',
|
||||
engine: 'saxon-js-dynamic',
|
||||
});
|
||||
|
||||
expect(result.diagnostics.some((item) => item.severity === 'error')).toBe(
|
||||
true
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user