Smail/test/frontend/telegram-settings.test.mjs
smail 52a8c49c90
Some checks are pending
Security Checks / security (push) Waiting to run
审查检查点:修正Telegram刷新确认回归
使Telegram未保存配置在刷新时正确区分取消与确认,验证取消保留输入、确认重新加载及保存后解除保护。
2026-09-30 04:52:19 +08:00

137 lines
5.3 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/components/PluginSettings/', import.meta.url)
const source = readFileSync(new URL('TelegramSettings/TelegramSettings.js', root), 'utf8')
const create = compileFunction(source.replace(/^import .*$/gm, '').replace('export function ', 'function ') + '\nreturn useTelegramSettings()',
['computed', 'onMounted', 'onBeforeUnmount', 'reactive', 'ref', 'ElMessage', 'ElMessageBox', 'QRCode', 'http', 'isRecentAuthenticationCancelled', 'requestWithRecentAuthentication'])
const createPage = (http, confirm = async () => {}) => create(
computed,
() => {},
() => {},
reactive,
ref,
{ success() {} },
{ confirm },
{ toDataURL: async () => '' },
http,
() => false,
request => request()
)
const userSettings = (overrides = {}) => ({
version: 7,
bound: true,
displayName: 'smail_test_user',
needsRebind: false,
available: true,
message: '',
enabled: false,
showContent: false,
spoilerContent: false,
sendAttachments: false,
disableLinkPreview: true,
...overrides
})
test('Telegram 原生设置保留版本、限制用户字段,不依赖插件 iframe', async () => {
const requests = []
let conflict = false
const page = createPage({
get: async () => ({ errorNo: 0, data: userSettings() }),
put: async (url, body) => {
requests.push({ url, body })
return conflict
? { errorNo: 400, errorMsg: '配置已被其他操作更新,请刷新后重试' }
: { errorNo: 0, data: userSettings({ ...body, version: 8, synced: true, secret: '不应返回' }) }
},
post: async (url, body) => {
requests.push({ url, body })
return { errorNo: 0, data: {} }
}
})
await page.load()
assert.equal(page.ready.value, true)
assert.equal(page.status.bound, true)
assert.equal(page.status.displayName, 'smail_test_user')
page.settings.sendAttachments = true
await page.submit('save')
assert.equal(requests[0].body.version, 7)
assert.deepEqual(Object.keys(requests[0].body).sort(), [
'disableLinkPreview', 'enabled', 'sendAttachments', 'showContent', 'spoilerContent', 'version'
])
assert.equal(page.settings.secret, undefined)
await page.submit('test')
assert.equal(requests[1].url, '/api/v1/plugin/settings/telegram_push/test')
assert.equal(requests[1].body, undefined)
conflict = true
await page.submit('save')
assert.notEqual(page.errorMessage.value, '')
})
test('Telegram 首次读取失败禁止覆盖存量设置,机器人故障不影响停用', async () => {
let fail = true
const page = createPage({
get: async () => {
if (fail) throw new Error('模拟离线')
return { errorNo: 0, data: userSettings({ version: 0, bound: false, available: false, displayName: '' }) }
},
put: async () => assert.fail('读取失败后不能保存')
})
await page.load()
await page.submit('save')
assert.equal(page.ready.value, false)
fail = false
await page.load()
assert.equal(page.ready.value, true)
assert.equal(page.status.bound, false)
})
test('Telegram 模板独立编译,其他插件继续保持 sandbox 隔离', () => {
const require = createRequire(new URL('../../frontend/package.json', import.meta.url))
const { parse, compileScript, compileStyle } = require('@vue/compiler-sfc')
const parent = readFileSync(new URL('PluginSettings.vue', root), 'utf8')
assert.match(parent, /TelegramSettings\s+v-else-if="activePage\?\.value === 'telegram-user'"/)
assert.match(parent, /sandbox="allow-scripts"/)
assert.doesNotMatch(parent, /allow-same-origin/)
const { descriptor, errors } = parse(readFileSync(new URL('TelegramSettings/TelegramSettings.vue', root), 'utf8'))
assert.deepEqual(errors, [])
assert.doesNotThrow(() => compileScript(descriptor, { id: 'telegram-settings', inlineTemplate: true }))
assert.deepEqual(compileStyle({ source: readFileSync(new URL('TelegramSettings/TelegramSettings.css', root), 'utf8'), id: 'telegram-settings', scoped: true }).errors, [])
assert.doesNotMatch(source, /window\.parent|parent\.document|postMessage|localStorage/)
})
test('Telegram 通知编辑在切页和重新加载前确认,取消保留输入,保存后解除保护', async () => {
let cancel = true
let reads = 0
let prompts = 0
const page = createPage({
get: async () => {
reads++
return { errorNo: 0, data: userSettings({ version: 1, showContent: false }) }
},
put: async (url, body) => ({ errorNo: 0, data: userSettings({ ...body, version: 2, synced: true }) })
}, async () => { prompts++; if (cancel) throw new Error('取消') })
await page.load()
assert.equal(await page.beforeLeave(), true)
page.settings.showContent = true
assert.equal(await page.beforeLeave(), false)
await page.refresh()
assert.equal(reads, 1)
assert.equal(page.settings.showContent, true)
cancel = false
await page.refresh()
assert.equal(reads, 2)
assert.equal(page.settings.showContent, false)
await page.submit('save')
assert.equal(page.hasChanges.value, false)
const count = prompts
assert.equal(await page.beforeLeave(), true)
assert.equal(prompts, count)
page.working.value = 'save'
assert.equal(await page.beforeLeave(), false)
})