const { test } = require('node:test'); const assert = require('node:assert/strict'); const { readFileSync } = require('node:fs'); const vm = require('node:vm'); test('YAML editor associates the schema and routes module workers to local bundles', async () => { const calls = { vim: [], disposed: 0 }; const stored = new Map(); const context = vm.createContext({ URL, localStorage: { getItem: key => stored.get(key), setItem: (key, value) => stored.set(key, value) }, Worker: class { constructor(url, options) { this.url = url.href; this.type = options.type; } }, }); const editor = { addCommand(keybinding, handler) { calls.command = { keybinding, handler }; } }; const monaco = { KeyMod: { CtrlCmd: 2048 }, KeyCode: { KeyS: 49 }, Uri: { parse: uri => uri }, editor: { createModel(value, language, uri) { calls.model = { value, language, uri }; return calls.model; }, create(element, options) { calls.element = element; calls.options = options; return editor; }, }, }; const schema = { title: 'Patch', type: 'object', properties: { spec: { type: 'object' } } }; const source = new vm.SourceTextModule(readFileSync(`${__dirname}/editor.js`, 'utf8'), { context, initializeImportMeta: meta => { meta.url = 'http://localhost/assets/app.js'; }, }); await source.link(specifier => { const exports = specifier.endsWith('editor.api.js') ? monaco : specifier === 'monaco-yaml' ? { configureMonacoYaml(instance, options) { assert.equal(instance.editor, monaco.editor); calls.yaml = options; } } : specifier === 'monaco-vim' ? { initVimMode(instance, status) { assert.equal(instance, editor); calls.vim.push(status); return { dispose() { calls.disposed++; } }; } } : specifier.endsWith('.json') ? { default: schema } : {}; return new vm.SyntheticModule(Object.keys(exports), function () { for (const [name, value] of Object.entries(exports)) this.setExport(name, value); }, { context }); }); await source.evaluate(); const onApply = () => {}; const checkbox = { checked: false, addEventListener(type, handler) { assert.equal(type, 'change'); this.change = handler; } }; const status = {}; assert.equal(source.namespace.createYamlEditor('container', onApply, checkbox, status), editor); assert.equal(checkbox.checked, false); assert.equal(status.hidden, true); assert.equal(calls.vim.length, 0); assert.equal(calls.command.keybinding, monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyS); assert.equal(calls.command.handler, onApply); assert.equal(calls.element, 'container'); assert.equal(calls.options.model, calls.model); assert.deepEqual(calls.model, { value: 'spec: {}\n', language: 'yaml', uri: 'file:///patch.yaml' }); const association = calls.yaml.schemas[0]; assert.equal(association.schema.title, undefined); assert.equal(association.schema.properties, schema.properties); assert.equal(schema.title, 'Patch'); assert.equal(association.uri, 'http://localhost/assets/patch.schema.json'); assert.deepEqual(Array.from(association.fileMatch), ['**/patch.yaml']); checkbox.checked = true; checkbox.change(); assert.equal(calls.vim.length, 1); assert.equal(calls.vim[0], status); assert.equal(status.hidden, false); assert.equal(stored.get('mfctl.vimMode'), 'true'); checkbox.checked = false; checkbox.change(); assert.equal(calls.disposed, 1); assert.equal(status.hidden, true); assert.equal(stored.get('mfctl.vimMode'), 'false'); checkbox.checked = true; checkbox.change(); assert.equal(calls.vim.length, 2); const restoredCheckbox = { ...checkbox, checked: false }; const restoredStatus = {}; source.namespace.createYamlEditor('container', onApply, restoredCheckbox, restoredStatus); assert.equal(restoredCheckbox.checked, true); assert.equal(restoredStatus.hidden, false); assert.equal(calls.vim.length, 3); assert.equal(calls.vim[2], restoredStatus); for (const [label, file] of [['yaml', 'yaml.worker.js'], ['editorWorkerService', 'editor.worker.js']]) { const worker = context.MonacoEnvironment.getWorker('unused', label); assert.equal(worker.url, `http://localhost/assets/${file}`); assert.equal(worker.type, 'module'); } });