105 lines
4.7 KiB
JavaScript
105 lines
4.7 KiB
JavaScript
import assert from 'node:assert/strict'
|
|
import test from 'node:test'
|
|
import { readFileSync } from 'node:fs'
|
|
import { compileFunction } from 'node:vm'
|
|
import { createRequire } from 'node:module'
|
|
import { computed, reactive, ref } from './vue.mjs'
|
|
|
|
const root = new URL('../../frontend/src/views/Setup/', import.meta.url)
|
|
const source = readFileSync(new URL('Setup.js', root), 'utf8')
|
|
const createPage = compileFunction(
|
|
source.replace(/^import .*$/gm, '').replaceAll('import.meta.env.DEV', 'false')
|
|
.replace('export function usePage', 'function usePage') + '\nreturn usePage()',
|
|
['computed', 'onUnmounted', 'reactive', 'ref', 'ElMessage', 'lang', 'axios', 'Plus', 'http', 'buildSetupFinalURL', 'probeService', 'window']
|
|
)
|
|
|
|
function fixture(tlsMode, type = '2') {
|
|
const requests = []
|
|
const messages = []
|
|
const window = { location: { href: 'https://mail.example.test/setup' } }
|
|
const page = createPage(computed, () => {}, reactive, ref,
|
|
{ error: message => messages.push(message) }, {}, {}, {}, {
|
|
post: async (path, payload) => {
|
|
requests.push({ path, payload })
|
|
return { errorNo: 0, data: { tlsMode, type, port: 8080 } }
|
|
}
|
|
}, () => 'https://mail.example.test/', () => assert.fail('外部证书不应探测签发状态'), window)
|
|
return { page, requests, messages, window }
|
|
}
|
|
|
|
test('反代初始化强制导入外部证书,即使旧配置仍是自动 DNS 类型', async () => {
|
|
const { page, requests, messages, window } = fixture('proxy')
|
|
await page.getSSLConfig()
|
|
assert.equal(page.proxyHTTPS.value, true)
|
|
assert.equal(page.sslSettings.type, '1')
|
|
page.sslSettings.type = '0'
|
|
page.handleSSLTypeChange()
|
|
assert.equal(page.sslSettings.type, '1')
|
|
await page.handleSSLChallengeChange('dns')
|
|
assert.equal(requests.length, 1)
|
|
assert.equal(page.dnsChecking.value, false)
|
|
// 绕过控件强行修改内存也不能让提交回到自动签发分支。
|
|
page.sslSettings.type = '0'
|
|
page.sslSettings.challenge = 'dns'
|
|
page.sslSettings.key_path = '/external/key.pem'
|
|
page.sslSettings.crt_path = '/external/cert.pem'
|
|
await page.setSSLConfig()
|
|
assert.deepEqual(requests.at(-1), {
|
|
path: '/api/v1/setup', payload: {
|
|
action: 'set', step: 'ssl', ssl_type: '1',
|
|
key_path: '/external/key.pem', crt_path: '/external/cert.pem'
|
|
}
|
|
})
|
|
assert.equal(requests.length, 2)
|
|
assert.equal(window.location.href, 'https://mail.example.test/')
|
|
assert.deepEqual(messages, [])
|
|
})
|
|
|
|
test('直接 HTTPS 初始化保留自动 HTTP 和 DNS 选项', async () => {
|
|
for (const type of ['0', '2']) {
|
|
const { page, messages } = fixture('direct', type)
|
|
await page.getSSLConfig()
|
|
assert.equal(page.proxyHTTPS.value, false)
|
|
assert.equal(page.sslSettings.type, '0')
|
|
assert.equal(page.sslSettings.challenge, type === '2' ? 'dns' : 'http')
|
|
assert.deepEqual(messages, [])
|
|
}
|
|
})
|
|
|
|
test('初始化模板能编译,实际渲染按反代策略隐藏自动选项并保留导入路径', async () => {
|
|
const require = createRequire(new URL('../../frontend/package.json', import.meta.url))
|
|
const { parse, compileScript } = require('@vue/compiler-sfc')
|
|
const { createSSRApp, compile, h } = require('vue')
|
|
const { renderToString } = require('vue/server-renderer')
|
|
const { descriptor, errors } = parse(readFileSync(new URL('Setup.vue', root), 'utf8'))
|
|
assert.deepEqual(errors, [])
|
|
assert.doesNotThrow(() => compileScript(descriptor, { id: 'setup-proxy', inlineTemplate: true }))
|
|
const render = compile(descriptor.template.content)
|
|
for (const tlsMode of ['proxy', 'direct']) {
|
|
const { page } = fixture(tlsMode, '0')
|
|
await page.getSSLConfig()
|
|
page.active.value = 5
|
|
page.lang.ssl_auto = '自动申请证书'
|
|
page.lang.ssl_manuallyf = '导入外部证书'
|
|
const app = createSSRApp({ setup: () => page, render })
|
|
for (const name of new Set(descriptor.template.content.match(/\bel-[a-z-]+/g))) {
|
|
app.component(name, {
|
|
props: ['label', 'value'],
|
|
setup: (props, { slots }) => () => h('div', { 'data-label': props.label, 'data-value': props.value }, slots.default?.())
|
|
})
|
|
}
|
|
app.directive('loading', { getSSRProps: () => ({}) })
|
|
const html = await renderToString(app)
|
|
assert.match(html, /data-label="导入外部证书"/)
|
|
if (tlsMode === 'proxy') {
|
|
assert.doesNotMatch(html, /data-label="自动申请证书"|ssl-challenge-select-row|ssl-storage-card|ssl-port-warning/)
|
|
assert.match(html, /外部续期后也需重新导入并应用/)
|
|
assert.match(html, /modelvalue="\.\/data\/ssl\/private\.key"/)
|
|
assert.match(html, /modelvalue="\.\/data\/ssl\/public\.crt"/)
|
|
} else {
|
|
assert.match(html, /data-label="自动申请证书"/)
|
|
assert.match(html, /ssl-challenge-select-row|ssl-storage-card/)
|
|
}
|
|
}
|
|
})
|