mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-12 15:26:16 -08:00
build(site): [SITE-07] reproduce Monaco CSS HTML and JSON workers
This commit is contained in:
1 parent
11296975f1
commit
0d3ddbf355
28 files changed
+3158
-10
No files matched your search
@@ -1,5 +1,12 @@
|
||||
# Browser regression entry
|
||||
|
||||
`editor-languages.spec.js` loads the frozen Monaco 0.30.1 CSS/HTML/JSON workers,
|
||||
checks real Worker creation, positive/negative diagnostics, tag completion, document
|
||||
symbols and formatting, and disposes models/workers. It uses `createWebWorker` with
|
||||
the archived mode managers' options; this version does not expose public language
|
||||
worker getters other than TypeScript. These checks complement `editor-types.spec.js`
|
||||
and do not replace full editor UI or actual player playback tests.
|
||||
|
||||
`yarn test:vast-native` is the explicit external Google IMA suite; it is separate
|
||||
from default `*.spec.js` PR checks. It uses local VAST/media inputs and real SDK
|
||||
loading, playback, content restoration and destruction. See
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
import { expect, test } from './fixtures.js'
|
||||
|
||||
test('docs Monaco CSS, HTML and JSON workers validate, complete and format real models', async ({ page }, testInfo) => {
|
||||
const startedWorkers = []
|
||||
page.on('worker', worker => startedWorkers.push(worker.url()))
|
||||
await page.goto('/test/player.html?core=candidate&chapter=published')
|
||||
await page.addScriptTag({ url: '/assets/js/vs/loader.js' })
|
||||
const result = await page.evaluate(async () => {
|
||||
window.require.config({ paths: { vs: '/assets/js/vs' } })
|
||||
await new Promise((resolve, reject) => window.require(['vs/editor/editor.main'], resolve, reject))
|
||||
const api = window.monaco
|
||||
const models = []
|
||||
const workers = []
|
||||
const model = (text, language, name) => {
|
||||
const value = api.editor.createModel(text, language, api.Uri.parse(`file:///${name}`))
|
||||
models.push(value)
|
||||
return value
|
||||
}
|
||||
const connect = async (language, createData, resources) => {
|
||||
// Monaco 0.30.1 exposes getTypeScriptWorker but no CSS/HTML/JSON accessor.
|
||||
// Use the same public worker constructor and createData as its mode managers.
|
||||
const worker = api.editor.createWebWorker({ moduleId: `vs/language/${language}/${language}Worker`, label: language, createData })
|
||||
workers.push(worker)
|
||||
await worker.withSyncedResources(resources.map(model => model.uri))
|
||||
return worker.getProxy()
|
||||
}
|
||||
try {
|
||||
const css = model('a { color: red; }', 'css', 'valid.css')
|
||||
const badCss = model('a { color: ; }', 'css', 'invalid.css')
|
||||
const json = model('{"value":1}', 'json', 'valid.json')
|
||||
const badJson = model('{"value":}', 'json', 'invalid.json')
|
||||
const html = model('<div><p>hello</p><p>world</p></div>', 'html', 'valid.html')
|
||||
const htmlCompletion = model('<di', 'html', 'completion.html')
|
||||
const cssWorker = await connect('css', { languageId: 'css', options: api.languages.css.cssDefaults.options }, [css, badCss])
|
||||
const jsonWorker = await connect('json', { languageId: 'json', languageSettings: api.languages.json.jsonDefaults.diagnosticsOptions, enableSchemaRequest: false }, [json, badJson])
|
||||
const htmlWorker = await connect('html', { languageId: 'html', languageSettings: api.languages.html.htmlDefaults.options }, [html, htmlCompletion])
|
||||
const completion = await htmlWorker.doComplete(htmlCompletion.uri.toString(), { line: 0, character: 3 })
|
||||
const symbols = await htmlWorker.findDocumentSymbols(html.uri.toString())
|
||||
const edits = await htmlWorker.format(html.uri.toString(), null, { tabSize: 2, insertSpaces: true, wrapLineLength: 120 })
|
||||
const jsonEdits = await jsonWorker.format(json.uri.toString(), null, { tabSize: 2, insertSpaces: true })
|
||||
return {
|
||||
cssValid: await cssWorker.doValidation(css.uri.toString()),
|
||||
cssInvalid: await cssWorker.doValidation(badCss.uri.toString()),
|
||||
jsonValid: await jsonWorker.doValidation(json.uri.toString()),
|
||||
jsonInvalid: await jsonWorker.doValidation(badJson.uri.toString()),
|
||||
completionLabels: completion.items.map(item => item.label),
|
||||
htmlSymbols: symbols.map(item => item.name),
|
||||
htmlEdits: edits,
|
||||
jsonEdits,
|
||||
}
|
||||
}
|
||||
finally {
|
||||
workers.forEach(worker => worker.dispose())
|
||||
models.forEach(model => model.dispose())
|
||||
}
|
||||
})
|
||||
await testInfo.attach('monaco-language-results', { contentType: 'application/json', body: JSON.stringify({ ...result, startedWorkers }, null, 2) })
|
||||
expect(startedWorkers.length).toBeGreaterThanOrEqual(3)
|
||||
expect(result.cssValid).toEqual([])
|
||||
expect(result.cssInvalid.some(item => item.severity === 1 && item.message)).toBe(true)
|
||||
expect(result.jsonValid).toEqual([])
|
||||
expect(result.jsonInvalid.some(item => item.severity === 1 && item.message)).toBe(true)
|
||||
expect(result.completionLabels).toContain('div')
|
||||
expect(result.htmlSymbols).toEqual(['div', 'p', 'p'])
|
||||
expect(result.htmlEdits.some(item => item.newText.includes('\n') && item.newText.includes('hello'))).toBe(true)
|
||||
expect(result.jsonEdits.some(item => item.newText.includes('\n'))).toBe(true)
|
||||
})
|
||||
@@ -1,6 +1,7 @@
|
||||
import assert from 'node:assert/strict'
|
||||
// eslint-disable-next-line test/no-import-node-test -- Verify fixed source transforms without executing archived runtime.
|
||||
import test from 'node:test'
|
||||
import { aliasModule, moduleIds, nameModule, verifyWorkerSources } from '../scripts/site-vendor/monaco/languages.ts'
|
||||
import { browserTypeScript, verifyTypeScriptSource } from '../scripts/site-vendor/monaco/typescript.ts'
|
||||
|
||||
const source = `"use strict";
|
||||
@@ -37,3 +38,36 @@ test('Monaco TypeScript proof rejects modified or repeated worker content', () =
|
||||
assert.throws(() => verifyTypeScriptSource(source, worker + output), /Duplicate/)
|
||||
assert.throws(() => verifyTypeScriptSource(source, worker.slice(1)), /differs/)
|
||||
})
|
||||
|
||||
test('Monaco AMD naming ignores strings and preserves source bodies', () => {
|
||||
const anonymous = '// define(fake)\nconst example = "define(fake)";\ndefine(["exports"], function (exports) { exports.value = 1; });\n//# sourceMappingURL=source.js.map\n'
|
||||
const named = nameModule(anonymous, 'library/main')
|
||||
assert(named.includes('const example = "define(fake)";'))
|
||||
assert(named.includes('define(\'library/main\',["exports"]'))
|
||||
assert(!named.includes('sourceMappingURL'))
|
||||
assert.deepEqual(moduleIds(named), ['library/main'])
|
||||
assert(nameModule(anonymous.trimEnd(), 'library/main').endsWith('//# sourceMappingURL=source.js.map;'))
|
||||
assert.throws(() => nameModule(named, 'library/main'), /anonymous AMD dependency array/)
|
||||
assert.throws(() => nameModule(anonymous + anonymous, 'library/main'), /one anonymous/)
|
||||
assert.throws(() => nameModule(anonymous, 'library/\'main'), /identifier/)
|
||||
assert.throws(() => nameModule(`${anonymous}//# sourceMappingURL=second.map\n`, 'library/main'), /Duplicate source map/)
|
||||
})
|
||||
|
||||
test('Monaco worker proof covers helper code, aliases and all module boundaries', () => {
|
||||
const id = 'library/main'
|
||||
const source = nameModule('const helper = 1;\ndefine(["exports"], function (exports) { exports.value = helper; });', id)
|
||||
const alias = aliasModule('library', 'main')
|
||||
const worker = `${source}\n\n${alias}\n`
|
||||
const fragments = [{ id, source }, { id: 'library', source: alias }]
|
||||
const ids = [id, 'library']
|
||||
verifyWorkerSources(worker, ids, fragments)
|
||||
assert.throws(() => verifyWorkerSources(worker.replace('helper = 1', 'helper = 2'), ids, fragments), /Source differs/)
|
||||
assert.throws(() => verifyWorkerSources(`globalThis.hidden = true;\n${worker}`, ids, fragments), /Unattributed worker content/)
|
||||
assert.throws(() => verifyWorkerSources(`${worker}globalThis.hidden = true;`, ids, fragments), /Unattributed worker suffix/)
|
||||
assert.throws(() => verifyWorkerSources(worker, ids, fragments.slice(0, 1)), /Incomplete source coverage/)
|
||||
assert.throws(() => verifyWorkerSources(worker, ids, [{ id, source: alias }, fragments[1]]), /ownership/)
|
||||
assert.throws(() => verifyWorkerSources(worker.replace('[\'library/main\']', '[\'library/other\']'), ids, fragments), /Source differs/)
|
||||
assert.throws(() => verifyWorkerSources(worker + alias, ids, fragments), /Duplicate AMD/)
|
||||
assert.throws(() => verifyWorkerSources(`${worker}define('extra', [], function () {});`, ids, fragments), /inventory changed/)
|
||||
assert.throws(() => moduleIds('define(dynamicName, [], function () {});'), /literal AMD name/)
|
||||
})
|
||||
Reference in new issue
Block a user