Files
RuoYi-Vue/browser-extension/multi-platform-publisher-1.1.17/tests/sidepanel-service-worker.test.mjs

126 lines
4.1 KiB
JavaScript
Raw Normal View History

import assert from 'node:assert/strict'
import { readFileSync } from 'node:fs'
import { dirname, resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
import vm from 'node:vm'
import test from 'node:test'
const testDirectory = dirname(fileURLToPath(import.meta.url))
const script = readFileSync(resolve(testDirectory, '../background/service-worker.js'), 'utf8')
function createRuntime(initialStorage = {}) {
const storage = { ...initialStorage }
const createdTabs = []
let nextTabId = 900
const event = () => ({ addListener() {} })
const chrome = {
runtime: {
getManifest: () => ({ version: '1.1.17' }),
onInstalled: event(),
onStartup: event(),
onMessage: event(),
sendMessage: async () => undefined
},
alarms: {
onAlarm: event(),
create: async () => undefined,
clear: async () => true
},
sidePanel: { setPanelBehavior: async () => undefined },
storage: {
local: {
get: async key => {
if (key == null) return { ...storage }
if (Array.isArray(key)) return Object.fromEntries(key.filter(item => item in storage).map(item => [item, storage[item]]))
return key in storage ? { [key]: storage[key] } : {}
},
set: async values => Object.assign(storage, values),
remove: async keys => {
for (const key of Array.isArray(keys) ? keys : [keys]) delete storage[key]
}
}
},
tabs: {
onUpdated: event(),
onRemoved: event(),
create: async options => {
const tab = { id: nextTabId++, windowId: 12, ...options }
createdTabs.push(tab)
return tab
},
get: async () => { throw new Error('tab not found') },
update: async (id, options) => ({ id, windowId: 12, ...options }),
query: async () => [],
sendMessage: async () => undefined
},
windows: { update: async () => undefined },
scripting: { executeScript: async () => [] }
}
const context = {
chrome,
console,
URL,
setTimeout,
clearTimeout,
fetch: async () => ({ ok: true, json: async () => ({ code: 200 }) })
}
vm.createContext(context)
vm.runInContext(script, context)
return { context, storage, createdTabs }
}
function task(taskId, platform, createdAt, status = 'FAILED') {
return {
taskId,
token: 'a'.repeat(32),
apiBaseUrl: 'https://feast.yidaima.cn/prod-api',
platform,
task: { title: platform + ' title' },
status,
statusMessage: '测试状态',
createdAt,
platformTabId: null
}
}
test('side panel lists only the latest task for each platform', async () => {
const now = Date.now()
const firstId = 'publish_' + '1'.repeat(32)
const latestId = 'publish_' + '2'.repeat(32)
const douyinId = 'publish_' + '3'.repeat(32)
const runtime = createRuntime({
['publisher_task_' + firstId]: task(firstId, 'xiaohongshu', now - 2000),
['publisher_task_' + latestId]: task(latestId, 'xiaohongshu', now - 1000),
['publisher_task_' + douyinId]: task(douyinId, 'douyin', now)
})
const tasks = await runtime.context.listSidePanelTasks()
assert.equal(tasks.length, 2)
assert.equal(tasks.find(item => item.platform === 'xiaohongshu').taskId, latestId)
assert.equal(tasks.find(item => item.platform === 'douyin').taskId, douyinId)
})
test('retry reopens a closed platform tab and stores the new mapping', async () => {
const taskId = 'publish_' + '4'.repeat(32)
const runtime = createRuntime({
['publisher_task_' + taskId]: task(taskId, 'xianyu', Date.now())
})
const result = await runtime.context.retryTask(taskId)
assert.equal(result.tabId, 900)
assert.equal(runtime.createdTabs[0].url, 'https://www.goofish.pro/sale/product/add?from=%2Fon-sale')
assert.equal(runtime.storage['publisher_task_' + taskId].status, 'OPENING')
assert.equal(runtime.storage.publisher_tab_900, taskId)
})
test('retry rejects a successfully published task', async () => {
const taskId = 'publish_' + '5'.repeat(32)
const runtime = createRuntime({
['publisher_task_' + taskId]: task(taskId, 'bilibili', Date.now(), 'SUCCEEDED')
})
await assert.rejects(() => runtime.context.retryTask(taskId), /不能重试/)
})