mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-29 03:09:36 +00:00
fix: roll back rejected general settings save
Issue: #439 User-Visible: yes
This commit is contained in:
committed by
claude[bot]
parent
5f90eaf4ef
commit
d5ad0371aa
@@ -1,7 +1,11 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
|
||||
import { enqueueSerializedWrite } from '../test-build/serialized-write-queue.js';
|
||||
import {
|
||||
enqueueSerializedWrite,
|
||||
optimisticAttempt,
|
||||
rollbackOptimistic,
|
||||
} from '../test-build/serialized-write-queue.js';
|
||||
|
||||
function deferred() {
|
||||
let resolve;
|
||||
@@ -51,3 +55,48 @@ test('a failed write does not poison the next queued edit (#224)', async () => {
|
||||
await recovered;
|
||||
assert.deepEqual(seen, ['failed', 'recovered']);
|
||||
});
|
||||
|
||||
test('a rejected optimistic write restores only its own candidate (#439)', () => {
|
||||
const fingerprint = (value) => JSON.stringify(value);
|
||||
const previous = { settings: { enabled: true } };
|
||||
const attempted = { settings: { enabled: false } };
|
||||
const attempt = optimisticAttempt(previous, attempted, 'server-fingerprint', 7, fingerprint);
|
||||
let updates = 0;
|
||||
const host = {
|
||||
_serverCfg: attempted,
|
||||
_cfgRev: 7,
|
||||
_cfgContentFingerprint: fingerprint(attempted),
|
||||
requestUpdate: () => { updates += 1; },
|
||||
};
|
||||
|
||||
assert.equal(rollbackOptimistic(host, attempt, fingerprint), true);
|
||||
assert.deepEqual(host._serverCfg, previous);
|
||||
assert.notEqual(host._serverCfg, previous, 'the rollback snapshot is isolated from later mutations');
|
||||
assert.equal(host._cfgContentFingerprint, 'server-fingerprint');
|
||||
assert.equal(updates, 1);
|
||||
});
|
||||
|
||||
test('a conflict reload or newer mutation wins over a rejected candidate (#439)', () => {
|
||||
const fingerprint = (value) => JSON.stringify(value);
|
||||
const previous = { settings: { value: 'server-before' } };
|
||||
const attempted = { settings: { value: 'draft' } };
|
||||
const attempt = optimisticAttempt(previous, attempted, 'before', 3, fingerprint);
|
||||
const authoritative = { settings: { value: 'server-after' } };
|
||||
let updates = 0;
|
||||
const host = {
|
||||
_serverCfg: authoritative,
|
||||
_cfgRev: 4,
|
||||
_cfgContentFingerprint: fingerprint(authoritative),
|
||||
requestUpdate: () => { updates += 1; },
|
||||
};
|
||||
|
||||
assert.equal(rollbackOptimistic(host, attempt, fingerprint), false);
|
||||
assert.equal(host._serverCfg, authoritative);
|
||||
assert.equal(updates, 0);
|
||||
|
||||
host._cfgRev = 3;
|
||||
host._serverCfg = { settings: { value: 'newer-local-edit' } };
|
||||
assert.equal(rollbackOptimistic(host, attempt, fingerprint), false);
|
||||
assert.equal(host._serverCfg.settings.value, 'newer-local-edit');
|
||||
assert.equal(updates, 0);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user