96 lines
2.9 KiB
JavaScript
96 lines
2.9 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import {
|
|
captureOperation,
|
|
deleteWarning,
|
|
decodePendingDelete,
|
|
encodePendingDelete,
|
|
mutationFollowup,
|
|
readPendingDelete,
|
|
sharedUploadWarning,
|
|
unfinishedDeleteItems
|
|
} from '../src/mutations.ts';
|
|
|
|
test('pending mutations replay while terminal failures restart', () => {
|
|
assert.equal(mutationFollowup('succeeded'), 'complete');
|
|
assert.equal(mutationFollowup('pending'), 'replay');
|
|
assert.equal(mutationFollowup('failed'), 'restart');
|
|
assert.equal(mutationFollowup('rejected'), 'restart');
|
|
assert.equal(mutationFollowup('conflict'), 'restart');
|
|
});
|
|
|
|
test('partial delete recovery preserves only unfinished identities', () => {
|
|
const ids = ['new-failed', 'new-conflict'];
|
|
const pending = unfinishedDeleteItems(
|
|
[
|
|
{
|
|
path: 'done',
|
|
operation_id: 'done-id',
|
|
result: 'succeeded',
|
|
error: null
|
|
},
|
|
{
|
|
path: 'waiting',
|
|
operation_id: 'waiting-id',
|
|
result: 'pending',
|
|
error: null
|
|
},
|
|
{
|
|
path: 'failed',
|
|
operation_id: 'failed-id',
|
|
result: 'failed',
|
|
error: null
|
|
},
|
|
{
|
|
path: 'conflict',
|
|
operation_id: 'conflict-id',
|
|
result: 'conflict',
|
|
error: null
|
|
},
|
|
{
|
|
path: 'uncertain',
|
|
operation_id: 'uncertain-id',
|
|
result: null,
|
|
error: 'object_store_unavailable'
|
|
}
|
|
],
|
|
() => ids.shift()
|
|
);
|
|
assert.deepEqual(pending, [
|
|
{ path: 'waiting', operation_id: 'waiting-id' },
|
|
{ path: 'failed', operation_id: 'new-failed' },
|
|
{ path: 'conflict', operation_id: 'new-conflict' },
|
|
{ path: 'uncertain', operation_id: 'uncertain-id' }
|
|
]);
|
|
});
|
|
|
|
test('persisted delete batches survive reload with the same captured root', () => {
|
|
const items = [{ path: 'folder/file', operation_id: 'operation-1' }];
|
|
const encoded = encodePendingDelete('shared', 'folder', items);
|
|
assert.deepEqual(readPendingDelete(encoded), {
|
|
root: 'shared',
|
|
prefix: 'folder',
|
|
items
|
|
});
|
|
assert.deepEqual(decodePendingDelete(encoded, 'shared', 'folder'), items);
|
|
assert.deepEqual(decodePendingDelete(encoded, 'personal', 'folder'), []);
|
|
assert.deepEqual(decodePendingDelete('{"items":[null]}', 'shared', 'folder'), []);
|
|
});
|
|
|
|
test('logical mutations capture their root before navigation changes', () => {
|
|
let root = 'personal';
|
|
const captured = captureOperation(root, 'folder/file', 'operation-1');
|
|
root = 'shared';
|
|
assert.deepEqual(captured, {
|
|
root: 'personal',
|
|
path: 'folder/file',
|
|
operationId: 'operation-1'
|
|
});
|
|
});
|
|
|
|
test('shared replacement confirmation is explicit', () => {
|
|
assert.equal(sharedUploadWarning('personal', 'file'), null);
|
|
assert.match(sharedUploadWarning('shared', 'file'), /replace a file for every user/);
|
|
assert.match(deleteWarning('shared', 'folder', true), /for every user/);
|
|
assert.doesNotMatch(deleteWarning('personal', 'file', false), /every user/);
|
|
});
|