mirror of
https://github.com/cnlimiter/codex-register.git
synced 2026-05-06 20:02:51 +08:00
151 lines
3.7 KiB
JavaScript
151 lines
3.7 KiB
JavaScript
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const fs = require('node:fs');
|
|
const vm = require('node:vm');
|
|
|
|
const APP_JS_PATH = '/Users/zhoukailian/.config/superpowers/worktrees/codex-manager/repro-batch-monitor/static/js/app.js';
|
|
|
|
function createElementStub() {
|
|
return {
|
|
style: {},
|
|
dataset: {},
|
|
value: '',
|
|
checked: false,
|
|
disabled: false,
|
|
innerHTML: '',
|
|
textContent: '',
|
|
className: '',
|
|
appendChild() {},
|
|
addEventListener() {},
|
|
removeEventListener() {},
|
|
querySelector() {
|
|
return createElementStub();
|
|
},
|
|
querySelectorAll() {
|
|
return [];
|
|
},
|
|
closest() {
|
|
return null;
|
|
},
|
|
};
|
|
}
|
|
|
|
function createSandbox() {
|
|
const elements = new Map();
|
|
|
|
const sandbox = {
|
|
console,
|
|
setTimeout,
|
|
clearTimeout,
|
|
setInterval: () => 1,
|
|
clearInterval: () => {},
|
|
Event: class Event {
|
|
constructor(type) {
|
|
this.type = type;
|
|
}
|
|
},
|
|
document: {
|
|
getElementById(id) {
|
|
if (!elements.has(id)) {
|
|
elements.set(id, createElementStub());
|
|
}
|
|
return elements.get(id);
|
|
},
|
|
createElement() {
|
|
return createElementStub();
|
|
},
|
|
addEventListener() {},
|
|
querySelector() {
|
|
return createElementStub();
|
|
},
|
|
querySelectorAll() {
|
|
return [];
|
|
},
|
|
},
|
|
sessionStorage: {
|
|
getItem() {
|
|
return null;
|
|
},
|
|
setItem() {},
|
|
removeItem() {},
|
|
},
|
|
toast: {
|
|
info() {},
|
|
success() {},
|
|
warning() {},
|
|
error() {},
|
|
},
|
|
api: {
|
|
get() {
|
|
throw new Error('api.get should not be called in this test');
|
|
},
|
|
post() {
|
|
throw new Error('api.post should not be called in this test');
|
|
},
|
|
},
|
|
loadRecentAccounts() {},
|
|
getServiceTypeText(type) {
|
|
return {
|
|
tempmail: '临时邮箱',
|
|
outlook: 'Outlook',
|
|
}[type] || type;
|
|
},
|
|
window: null,
|
|
WebSocket: null,
|
|
};
|
|
|
|
sandbox.window = sandbox;
|
|
sandbox.window.location = { protocol: 'http:', host: '127.0.0.1:8005' };
|
|
|
|
vm.createContext(sandbox);
|
|
vm.runInContext(fs.readFileSync(APP_JS_PATH, 'utf8'), sandbox, { filename: 'app.js' });
|
|
|
|
return { sandbox, elements };
|
|
}
|
|
|
|
test('single task websocket completion updates task info and resets buttons', () => {
|
|
const { sandbox, elements } = createSandbox();
|
|
|
|
vm.runInContext(
|
|
`
|
|
var __lastWs = null;
|
|
startLogPolling = function() {
|
|
throw new Error('startLogPolling should not be called for completed status');
|
|
};
|
|
loadRecentAccounts = function() {};
|
|
currentTask = { task_uuid: 'task-1' };
|
|
taskCompleted = false;
|
|
taskFinalStatus = null;
|
|
elements.startBtn.disabled = true;
|
|
elements.cancelBtn.disabled = false;
|
|
elements.taskStatusRow.style.display = 'grid';
|
|
WebSocket = function(url) {
|
|
this.url = url;
|
|
this.readyState = 0;
|
|
__lastWs = this;
|
|
};
|
|
WebSocket.OPEN = 1;
|
|
WebSocket.CLOSED = 3;
|
|
WebSocket.prototype.close = function() {
|
|
this.readyState = WebSocket.CLOSED;
|
|
};
|
|
connectWebSocket('task-1');
|
|
__lastWs.onmessage({
|
|
data: JSON.stringify({
|
|
type: 'status',
|
|
status: 'completed',
|
|
email: 'demo@example.com',
|
|
email_service: 'tempmail',
|
|
}),
|
|
});
|
|
`,
|
|
sandbox,
|
|
);
|
|
|
|
assert.equal(elements.get('start-btn').disabled, false);
|
|
assert.equal(elements.get('cancel-btn').disabled, true);
|
|
assert.equal(elements.get('task-status').textContent, '已完成');
|
|
assert.equal(elements.get('task-email').textContent, 'demo@example.com');
|
|
assert.equal(elements.get('task-service').textContent, '临时邮箱');
|
|
});
|