22 lines
1.4 KiB
TypeScript
22 lines
1.4 KiB
TypeScript
import { test } from 'node:test';
|
|
import assert from 'node:assert/strict';
|
|
import { acquireEmployeeLock, type LockBackend } from './clock-lock';
|
|
const now=Date.parse('2026-10-21T08:00:00Z');
|
|
function backend(age:number) {
|
|
let current:{id:string;created:string}|null={id:'old',created:new Date(now-age).toISOString()};
|
|
const api:LockBackend={create:async()=>{if(current)throw {status:400};current={id:'new',created:new Date(now).toISOString()};return current;},find:async()=>current,remove:async id=>{if(current?.id!==id)throw{status:404};current=null;}};
|
|
return {api,current:()=>current};
|
|
}
|
|
test('live locks block another device; abandoned locks are recoverable',async()=>{
|
|
await assert.rejects(()=>acquireEmployeeLock(backend(60_000).api,'worker',now),/Another scan/);
|
|
const expired=backend(121_000);assert.equal(await acquireEmployeeLock(expired.api,'worker',now),'new');
|
|
});
|
|
test('release of an expired owner never deletes a newer lock',async()=>{
|
|
const expired=backend(121_000);await acquireEmployeeLock(expired.api,'worker',now);
|
|
await assert.rejects(()=>expired.api.remove('old'));
|
|
assert.equal(expired.current()?.id,'new');
|
|
});
|
|
test('database outages do not lead to stealing a lock',async()=>{
|
|
const b=backend(121_000);b.api.create=async()=>{throw{status:503};};
|
|
await assert.rejects(()=>acquireEmployeeLock(b.api,'worker',now));assert.equal(b.current()?.id,'old');
|
|
});
|