Files
orca/config/scripts/xterm-sourcemap-source.test.mjs
T

110 lines
3.7 KiB
JavaScript

import { mkdtemp, mkdir, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import path from 'node:path'
import { afterEach, describe, expect, it } from 'vitest'
import { assertMappedSourcesMatch } from './xterm-sourcemap-source.mjs'
const roots = []
const widget = 'export const widget = 1;\n'
const version = "export const XTERM_VERSION = '6.0.0';\n"
const sourcePatch = 'diff --git a/src/Widget.ts b/src/Widget.ts\n'
afterEach(async () => {
await Promise.all(roots.splice(0).map((root) => rm(root, { recursive: true, force: true })))
})
async function fixture() {
const root = await mkdtemp(path.join(tmpdir(), 'orca-xterm-map-'))
roots.push(root)
await mkdir(path.join(root, 'src'))
await writeFile(path.join(root, 'src', 'Widget.ts'), widget)
await writeFile(path.join(root, 'src', 'Version.ts'), version)
const map = {
sources: ['../../src/Widget.ts', '../../src/Version.ts'],
sourcesContent: [widget, version]
}
const options = {
packageRoot: root,
sourceRoot: root,
sourceMaps: { 'bundle.map': '../../' },
sourcePatch
}
const save = async (value = map) => {
await writeFile(path.join(root, 'bundle.map'), JSON.stringify(value))
}
await save()
return { root, map, options, save }
}
describe('xterm source-map provenance', () => {
it('matches every mapped source byte for byte, including the unstamped version', async () => {
const { options } = await fixture()
expect(() => assertMappedSourcesMatch(options)).not.toThrow()
})
it('rejects a changed source not embedded in the shipped maps', async () => {
const { options } = await fixture()
expect(() =>
assertMappedSourcesMatch({
...options,
sourcePatch: `${sourcePatch}diff --git a/src/Widget.test.ts b/src/Widget.test.ts\n`
})
).toThrow('changed source is not shipped')
})
it('checks unedited mapped files too', async () => {
const { map, options, save } = await fixture()
map.sourcesContent[1] = "export const XTERM_VERSION = 'wrong';\n"
await save()
expect(() => assertMappedSourcesMatch(options)).toThrow(
'does not match checkout: src/Version.ts'
)
})
it('requires complete embedded contents in every declared map', async () => {
const { map, options, save } = await fixture()
delete map.sourcesContent
await save()
expect(() => assertMappedSourcesMatch(options)).toThrow('missing or incomplete sourcesContent')
})
it('rejects an empty map policy and unmatched prefixes', async () => {
const { options } = await fixture()
expect(() => assertMappedSourcesMatch({ ...options, sourceMaps: {} })).toThrow('at least one')
expect(() =>
assertMappedSourcesMatch({
...options,
sourceMaps: { 'bundle.map': 'wrong/' }
})
).toThrow('no sources match prefix')
})
it('rejects duplicate and escaping source paths', async () => {
const { map, options, save } = await fixture()
map.sources.push(map.sources[0])
map.sourcesContent.push(widget)
await save()
expect(() => assertMappedSourcesMatch(options)).toThrow('duplicate mapped source')
map.sources[0] = '../../src/../Widget.ts'
await save()
expect(() => assertMappedSourcesMatch(options)).toThrow('unexpected mapped source')
})
it('requires each changed source in each declared map', async () => {
const { root, options } = await fixture()
await writeFile(
path.join(root, 'second.map'),
JSON.stringify({
sources: ['webpack://xterm/./src/Version.ts'],
sourcesContent: [version]
})
)
expect(() =>
assertMappedSourcesMatch({
...options,
sourceMaps: { ...options.sourceMaps, 'second.map': 'webpack://xterm/./' }
})
).toThrow('second.map: changed source is not shipped')
})
})