diff --git a/web-admin/scripts/quota-statistics.test.ts b/web-admin/scripts/quota-statistics.test.ts index 574282959..84bea97fe 100644 --- a/web-admin/scripts/quota-statistics.test.ts +++ b/web-admin/scripts/quota-statistics.test.ts @@ -571,3 +571,101 @@ test('refresh and search while permission request is pending do not cancel initi assert.equal(s.rows.value[0].id, 'loaded') h.stop() }) + +import { compileScript } from '@vue/compiler-sfc' +function compiledSfc(path: string, dependencies: Record, inlineTemplate = true) { + const descriptor = parse(readFileSync(new URL(path, import.meta.url), 'utf8')).descriptor + const compiled = compileScript(descriptor, { id: path, inlineTemplate }) + const source = ts.createSourceFile('compiled.ts', compiled.content, ts.ScriptTarget.Latest, true) + const env: Record = Object.fromEntries( + Object.entries(vue).filter(([key]) => /^[a-zA-Z_$][\w$]*$/.test(key) && key !== 'default') + ) + for (const statement of source.statements) { + if (!ts.isImportDeclaration(statement) || statement.importClause?.isTypeOnly) continue + const clause = statement.importClause + if (clause?.name) env[clause.name.text] = dependencies[clause.name.text] || {} + if (clause?.namedBindings && ts.isNamedImports(clause.namedBindings)) { + for (const item of clause.namedBindings.elements) { + if (item.isTypeOnly) continue + const name = (item.propertyName || item.name).text + env[item.name.text] = + statement.moduleSpecifier.getText(source) === '"vue"' || + statement.moduleSpecifier.getText(source) === "'vue'" + ? (vue as any)[name] + : dependencies[name] + } + } + } + const code = ts.transpile( + source.statements + .filter((s) => !ts.isImportDeclaration(s)) + .map((s) => s.getText(source)) + .join('\n') + .replace('export default', 'const component ='), + { target: ts.ScriptTarget.ESNext } + ) + return new Function(...Object.keys(env), `${code}; return component`)(...Object.values(env)) +} +for (const wrapper of [ + 'contract-quota/ContractQuotaPanel.vue', + 'certificate-usage/CertificateUsagePanel.vue' +]) { + for (const active of [undefined, false]) + test(`compiled ${wrapper} ${active === false ? 'inactive skips requests' : 'defaults to active and loads'}`, async () => { + const calls: string[] = [] + const dependencies = { + useUserStore: () => vue.reactive({ accessToken: 'token', getUserInfo: { tenantNo: 'a' } }), + fetchGetMenuCodes: async () => { + calls.push('permissions') + return { all: true } + }, + quotaStatisticsApi: { + contracts: async () => { + calls.push('contracts') + return { list: [], total: 0 } + }, + certificates: async () => { + calls.push('certificates') + return { list: [], total: 0 } + } + }, + usePersistedListColumns, + useServerColumnFilters, + createStatisticsLoader, + useListTableViewportHeight: () => ({ tableHeight: vue.ref(400) }), + statusLabel: statisticsLabels.statusLabel, + contractTypeLabel: statisticsLabels.contractTypeLabel + } + // Compile the real inner setup too; only its visual child tree is omitted here. + const StatisticsPanel = compiledSfc( + '../src/views/pl/quota-statistics/StatisticsPanel.vue', + dependencies, + false + ) + StatisticsPanel.render = () => null + const Wrapper = compiledSfc(`../src/views/pl/${wrapper}`, { StatisticsPanel }) + const renderer = vue.createRenderer({ + createElement: () => ({}), + createText: () => ({}), + createComment: () => ({}), + setText: () => {}, + setElementText: () => {}, + parentNode: () => null, + nextSibling: () => null, + insert: () => {}, + remove: () => {}, + patchProp: () => {} + }) + const app = renderer.createApp(Wrapper, active === undefined ? {} : { active }) + app.mount({}) + await flush() + await vue.nextTick() + assert.deepEqual( + calls, + active === false + ? [] + : ['permissions', wrapper.startsWith('contract') ? 'contracts' : 'certificates'] + ) + app.unmount() + }) +} diff --git a/web-admin/src/views/pl/certificate-usage/CertificateUsagePanel.vue b/web-admin/src/views/pl/certificate-usage/CertificateUsagePanel.vue index d7a7ad40b..6a5a15ee1 100644 --- a/web-admin/src/views/pl/certificate-usage/CertificateUsagePanel.vue +++ b/web-admin/src/views/pl/certificate-usage/CertificateUsagePanel.vue @@ -1,5 +1,5 @@ diff --git a/web-admin/src/views/pl/contract-quota/ContractQuotaPanel.vue b/web-admin/src/views/pl/contract-quota/ContractQuotaPanel.vue index 6f8d3c848..60c7393c2 100644 --- a/web-admin/src/views/pl/contract-quota/ContractQuotaPanel.vue +++ b/web-admin/src/views/pl/contract-quota/ContractQuotaPanel.vue @@ -1,5 +1,8 @@