4c3fa64c95
- Background STATUS polling is enabled by default, per the spec's idle
polling rule (TS 102 221 14.6.2): `_POLL_ENABLED = True`, __main__ runs
`_poll_enable()` regardless of card presence (--poll-interval 0 still
disables) and `_do_status_poll` keeps ticking while enabled even without
a session, so a cardless start resumes as soon as a card appears.
- A new card session clears a POLLING OFF from the previous card in
`_apply_equipped_card` before re-enabling polling.
- The Phone-tab toggle now shows the *effective* state: OFF in amber
("card disabled polling (POLLING OFF)") while the card suspended
proactive polling, back to ON on the next POLL INTERVAL. The 5 s
background poll now passes `card_disabled` through (it was dropped, so
an autonomously received POLLING OFF never reached the UI).
- Tests: poll_ui updated (button OFF while suspended, warning path),
test_poll +2 (cardless ticking, module default via a subprocess check).
- Help EN/RU, docs/api.md, AGENTS; version 3.5.10; sw cache simple-v263.
573 frontend / 441 Python green.
65 lines
2.3 KiB
JavaScript
65 lines
2.3 KiB
JavaScript
const { test } = require('node:test');
|
|
const assert = require('node:assert');
|
|
const fs = require('node:fs');
|
|
const path = require('node:path');
|
|
|
|
const html = fs.readFileSync(path.join(__dirname, '..', 'index.html'), 'utf8');
|
|
|
|
function extractFunc(src, name, asyncFn) {
|
|
const re = new RegExp('function\\s+' + name + '\\s*\\([^)]*\\)\\s*\\{');
|
|
const m = re.exec(src);
|
|
if (!m) throw new Error('function ' + name + ' not found');
|
|
let i = m.index + m[0].length - 1;
|
|
let depth = 0;
|
|
for (; i < src.length; i++) {
|
|
if (src[i] === '{') depth++;
|
|
else if (src[i] === '}') {
|
|
depth--;
|
|
if (depth === 0) break;
|
|
}
|
|
}
|
|
return (asyncFn ? 'async ' : '') + src.slice(m.index, i + 1);
|
|
}
|
|
|
|
eval(extractFunc(html, 'pysimUpdatePollUI'));
|
|
globalThis.t = s => s;
|
|
|
|
function setup() {
|
|
const els = {
|
|
'pli-pause-btn': { textContent: '', classList: { add: () => {}, remove: () => {} } },
|
|
'pli-poll-stat': { textContent: '', className: 'text-xs text-gray-400' },
|
|
};
|
|
globalThis.document = { getElementById: id => els[id] || null };
|
|
return els;
|
|
}
|
|
|
|
test('pysimUpdatePollUI shows the interval while polling is on', () => {
|
|
const els = setup();
|
|
pysimUpdatePollUI(true, 30);
|
|
assert.strictEqual(els['pli-pause-btn'].textContent, 'ON');
|
|
assert.strictEqual(els['pli-poll-stat'].textContent, '(30s)');
|
|
assert.ok(!els['pli-poll-stat'].className.includes('amber'));
|
|
});
|
|
|
|
test('pysimUpdatePollUI shows the card-disabled state as OFF in amber', () => {
|
|
const els = setup();
|
|
pysimUpdatePollUI(true, 30, true);
|
|
assert.strictEqual(els['pli-pause-btn'].textContent, 'OFF');
|
|
assert.ok(els['pli-poll-stat'].textContent.includes('POLLING OFF'), els['pli-poll-stat'].textContent);
|
|
assert.ok(els['pli-poll-stat'].className.includes('text-amber-600'));
|
|
});
|
|
|
|
test('pysimUpdatePollUI shows the server warning while suspended', () => {
|
|
const els = setup();
|
|
pysimUpdatePollUI(true, 30, true, 'card disabled proactive polling');
|
|
assert.strictEqual(els['pli-pause-btn'].textContent, 'OFF');
|
|
assert.strictEqual(els['pli-poll-stat'].textContent, 'card disabled proactive polling');
|
|
});
|
|
|
|
test('pysimUpdatePollUI clears the status line when off', () => {
|
|
const els = setup();
|
|
pysimUpdatePollUI(false, 30);
|
|
assert.strictEqual(els['pli-pause-btn'].textContent, 'OFF');
|
|
assert.strictEqual(els['pli-poll-stat'].textContent, '');
|
|
});
|