63 lines
3.3 KiB
JavaScript
63 lines
3.3 KiB
JavaScript
const { test } = require('node:test')
|
||
const assert = require('node:assert/strict')
|
||
const fs = require('node:fs')
|
||
const path = require('node:path')
|
||
const vm = require('node:vm')
|
||
const ts = require('typescript')
|
||
const vue = require('vue')
|
||
const { renderToString } = require('@vue/server-renderer')
|
||
const { parse, compileScript } = require('@vue/compiler-sfc')
|
||
|
||
function component(filename, globals = {}) {
|
||
const { descriptor } = parse(fs.readFileSync(filename, 'utf8'), { filename })
|
||
const compiled = compileScript(descriptor, { id: filename, inlineTemplate: true }).content
|
||
const source = ts.transpileModule(compiled, { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022, esModuleInterop: true } }).outputText
|
||
const context = vm.createContext({ exports: {}, require, ...globals })
|
||
vm.runInContext(source, context)
|
||
return context.exports.default
|
||
}
|
||
|
||
// Resolve the configured renderer, so accidentally wiring the unrelated "active" renderer fails this test.
|
||
const storeSource = fs.readFileSync(`${__dirname}/../stores/data.js`, 'utf8')
|
||
const store = ts.createSourceFile('data.js', storeSource, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS)
|
||
let chatColumn
|
||
function visit(node) {
|
||
if (ts.isObjectLiteralExpression(node) && node.properties.some(property =>
|
||
ts.isPropertyAssignment(property) && property.name.getText(store) === 'key' && property.initializer.getText(store) === '"chatEnabled"')) chatColumn = node
|
||
ts.forEachChild(node, visit)
|
||
}
|
||
visit(store)
|
||
const rendererName = chatColumn.properties.find(property => property.name?.getText(store) === 'component').initializer.getText(store)
|
||
const rendererImport = store.statements.find(statement => ts.isImportDeclaration(statement) && statement.importClause?.name?.text === rendererName)
|
||
const renderer = component(path.resolve(__dirname, '..', rendererImport.moduleSpecifier.text.replace(/^~\//, '')))
|
||
const column = vm.runInNewContext(`(${chatColumn.getText(store)})`, { [rendererName]: renderer })
|
||
|
||
test('project list renders the actual chat setting, independently of an unrelated active flag', async () => {
|
||
for (const [row, expected] of [
|
||
[{ chatEnabled: true }, 'Ja'],
|
||
[{ chatEnabled: true, active: false }, 'Ja'],
|
||
[{ chatEnabled: false, active: true }, 'Nein'],
|
||
[{ chatEnabled: false }, 'Nein'],
|
||
[{ active: true }, '–'],
|
||
]) {
|
||
const html = await renderToString(vue.createSSRApp(column.component, { row }))
|
||
assert.match(html, new RegExp(`>${expected}</span>`), JSON.stringify(row))
|
||
}
|
||
})
|
||
|
||
test('project information shows Ja and Nein after loading the saved setting', async () => {
|
||
const information = component(`${__dirname}/../components/EntityShowSubInformation.vue`, {
|
||
useDataStore: () => ({ dataTypes: { projects: { templateColumns: [column] } } }),
|
||
useTempStore: () => ({}), useRouter: () => ({}),
|
||
})
|
||
for (const chatEnabled of [true, false]) {
|
||
const app = vue.createSSRApp(information, { item: { id: 1, chatEnabled }, topLevelType: 'projects', platform: 'default' })
|
||
app.component('UCard', { setup: (_, { slots }) => () => vue.h('section', slots.default?.()) })
|
||
app.component('UAlert', { render: () => null })
|
||
app.component('TelephonyCallButton', { render: () => null })
|
||
const html = await renderToString(app)
|
||
assert.match(html, /Projektchat aktiviert/)
|
||
assert.match(html, new RegExp(`>${chatEnabled ? 'Ja' : 'Nein'}</span>`))
|
||
}
|
||
})
|