62 lines
2.2 KiB
JavaScript
62 lines
2.2 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
|
|
import {
|
|
createOperationRegistry,
|
|
OPERATION_CONFLICTS,
|
|
operationBlocked,
|
|
} from '../../.test-dist/src/web/state/operations.js';
|
|
|
|
const deferred = () => {
|
|
let resolve;
|
|
const promise = new Promise((done) => { resolve = done; });
|
|
return { promise, resolve };
|
|
};
|
|
|
|
test('operation conflicts block domain controls but leave copy and navigation alone', () => {
|
|
for (const [key, conflicts] of Object.entries(OPERATION_CONFLICTS)) {
|
|
for (const conflict of conflicts) {
|
|
assert.ok(OPERATION_CONFLICTS[conflict].includes(key), `${key} -> ${conflict} is not symmetric`);
|
|
}
|
|
}
|
|
|
|
const refreshing = { profileRefresh: { status: 'running', target: 'primary' } };
|
|
assert.equal(operationBlocked(refreshing, 'connection'), true);
|
|
assert.equal(operationBlocked(refreshing, 'serverApply'), true);
|
|
assert.equal(operationBlocked(refreshing, 'profileDelete'), true);
|
|
|
|
const applying = { serverApply: { status: 'running', target: 'primary:server' } };
|
|
assert.equal(operationBlocked(applying, 'connection'), true);
|
|
assert.equal(operationBlocked(applying, 'profileRefresh'), true);
|
|
});
|
|
|
|
test('double click shares one in-flight request end to end', async () => {
|
|
const request = deferred();
|
|
let requests = 0;
|
|
const registry = createOperationRegistry();
|
|
const action = () => { requests += 1; return request.promise; };
|
|
const first = registry.run('serverApply', action, 'primary:server');
|
|
const second = registry.run('serverApply', action, 'primary:server');
|
|
|
|
assert.equal(second, first);
|
|
assert.equal(registry.getSnapshot().serverApply.status, 'running');
|
|
request.resolve({ success: true });
|
|
assert.deepEqual(await first, { success: true });
|
|
assert.equal(requests, 1);
|
|
assert.deepEqual(registry.getSnapshot(), {});
|
|
});
|
|
|
|
test('a conflicting operation is rejected before its action starts', async () => {
|
|
const connection = deferred();
|
|
const registry = createOperationRegistry();
|
|
const running = registry.run('connection', () => connection.promise);
|
|
let applyCalls = 0;
|
|
|
|
const result = registry.run('serverApply', () => { applyCalls += 1; });
|
|
assert.equal(await result, false);
|
|
assert.equal(applyCalls, 0);
|
|
|
|
connection.resolve(true);
|
|
await running;
|
|
});
|