Files
creator-hub/web/tests/account-start-readiness.test.cjs
T
rogee e50bed9ad8
douyin-release-gate / verify (push) Failing after 18m54s
feat: add account events and private message management
Add Douyin notification polling, event details, and manual multi-account private messaging.

Refine environment memory settings, account operations, login collection recovery, and message UI; update tests and documentation.
2026-10-07 10:23:05 +08:00

134 lines
6.4 KiB
JavaScript

const assert = require('node:assert/strict');
const { readFileSync } = require('node:fs');
const { createRequire, Module } = require('node:module');
const { resolve } = require('node:path');
const test = require('node:test');
const vm = require('node:vm');
const ts = require('typescript');
const requireWeb = createRequire(resolve(__dirname, '../package.json'));
function compile(relativePath, imports = {}) {
const path = resolve(__dirname, relativePath);
const loaded = new Module(path, module);
loaded.require = id => imports[id] || requireWeb(id);
loaded._compile(ts.transpileModule(readFileSync(path, 'utf8'), {
compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 },
}).outputText, path);
return loaded.exports;
}
const helpers = compile('../src/utils/helpers.ts');
const actions = compile('../src/components/accounts/account-actions.ts', {
'@/services/api': {},
'@/utils/account-collection-status': compile('../src/utils/account-collection-status.ts'),
});
const account = {
id: '1004291301', runtime_status: 'active', login_status: 'logged_in',
environment: { alias: 'environment', schedule_block_reason: 'runtime_missing' },
};
const stopped = { alias: 'environment', state: 'missing', status: '未记录运行实例', gateway_reachable: true };
const source = ts.createSourceFile('AccountManagementList.tsx',
readFileSync(resolve(__dirname, '../src/components/accounts/AccountManagementList.tsx'), 'utf8'),
ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
let renderer;
function visit(node) {
if (ts.isObjectLiteralExpression(node) && node.properties.some(property =>
ts.isPropertyAssignment(property) && property.name.getText(source) === 'title' && property.initializer.text === '操作')) {
renderer = node.properties.find(property => ts.isPropertyAssignment(property) && property.name.getText(source) === 'render').initializer.getText(source);
}
ts.forEachChild(node, visit);
}
visit(source);
assert.ok(renderer, '必须存在账号操作列');
function renderActions(row = account, browser = stopped, actionBusy = '') {
const calls = [];
const code = ts.transpileModule(`exports.render = ${renderer};`, {
compilerOptions: { jsx: ts.JsxEmit.ReactJSX, module: ts.ModuleKind.CommonJS },
}).outputText;
const context = {
exports: {}, require: requireWeb, ...requireWeb('antd'),
DownOutlined: requireWeb('@ant-design/icons').DownOutlined,
...helpers, ...actions, browsers: browser ? [browser] : [], verifiedLogin: {}, actionBusy,
performPrimary: (row, intent) => calls.push([row.id, intent]), moreAction() {}, setEnvironmentTarget() {},
};
vm.runInNewContext(code, context);
const cell = context.exports.render(undefined, row);
const [tooltip, dropdown] = cell.props.children;
return { button: tooltip.props.children, tooltip, menu: dropdown.props.menu, calls };
}
test('未启动只阻止采集调度,不阻止启动环境', () => {
const readiness = helpers.accountReadiness(account, account.environment);
assert.equal(readiness.ready, false);
assert.equal(readiness.reason, 'runtime_missing');
assert.equal(readiness.label, '运行环境未启动');
assert.equal(readiness.canStart, true);
});
test('可调度账号仍可启动,未知阻塞原因不能绕过', () => {
assert.equal(helpers.accountReadiness(account, {}).canStart, true);
assert.equal(helpers.accountReadiness(account, { schedule_block_reason: 'unknown_block' }).canStart, false);
});
for (const [name, row, binding, error] of [
['未绑定', account, null],
['状态读取失败', account, account.environment, new Error('unavailable')],
['停止待确认', account, { ...account.environment, runtime_cleanup_pending: true }],
['固定出口异常', account, { ...account.environment, network_exit_id: 'proxy', network_exit_health: 'unhealthy' }],
['账号暂停', { ...account, runtime_status: 'paused' }, account.environment],
['暂停账号仍在停止', { ...account, runtime_status: 'paused' }, { ...account.environment, runtime_id: 'runtime' }],
]) {
test(`${name}不能通过启动环境绕过限制`, () => {
assert.equal(helpers.accountReadiness(row, binding, error).canStart, false);
});
}
test('1004291301 未启动时主按钮和更多菜单均允许启动', () => {
const { button, tooltip, menu, calls } = renderActions();
assert.equal(button.props.children, '启动环境');
assert.equal(button.props.disabled, false);
assert.equal(tooltip.props.title, undefined);
assert.equal(menu.items.find(item => item.key === 'start').disabled, false);
button.props.onClick();
assert.deepEqual(calls, [['1004291301', 'start']]);
});
test('需要重新登录的未启动账号可点击重新登录', () => {
const { button, calls } = renderActions({ ...account, login_status: 'manual_login' });
assert.equal(button.props.children, '重新登录');
assert.equal(button.props.disabled, false);
button.props.onClick();
assert.deepEqual(calls, [['1004291301', 'login']]);
});
for (const environment of [
{ ...account.environment, runtime_cleanup_pending: true },
{ ...account.environment, network_exit_id: 'proxy', network_exit_health: 'unhealthy' },
{ ...account.environment, schedule_block_reason: 'unknown_block' },
]) {
test(`列表启动入口仍遵守限制 ${JSON.stringify(environment)}`, () => {
const { button, tooltip, menu } = renderActions({ ...account, environment });
assert.equal(button.props.disabled, true);
assert.ok(tooltip.props.title);
assert.equal(menu.items.find(item => item.key === 'start').disabled, true);
});
}
test('暂停账号保留恢复运行入口,不能从更多菜单直接启动', () => {
const paused = { ...account, runtime_status: 'paused' };
const { button, menu } = renderActions(paused);
assert.equal(button.props.children, '恢复运行');
assert.equal(button.props.disabled, false);
assert.equal(menu.items.find(item => item.key === 'start').disabled, true);
});
test('操作执行中仍禁用主按钮,运行中不重复启动', () => {
assert.equal(renderActions(account, stopped, account.id).button.props.disabled, true);
const running = { ...stopped, state: 'running', status: 'ready' };
const { button, menu } = renderActions({ ...account, environment: { alias: 'environment' } }, running);
assert.equal(button.props.children, '同步资料');
assert.equal(button.props.disabled, false);
assert.equal(menu.items.find(item => item.key === 'start').disabled, true);
});