This commit is contained in:
1 parent
03841c6e3d
commit
036a8c0e1e
32 files changed
+1805
-89
No files matched your search
@@ -78,6 +78,84 @@ parentPort.on('message', (data) => globalThis.self.onmessage({ data }));
|
||||
});
|
||||
afterAll(() => rmSync(directory, { recursive: true, force: true }));
|
||||
|
||||
it.each([false, true])(
|
||||
'keeps declarations fixed in direct and worker planning and date comparisons (cancelled: %s)',
|
||||
async (cancelled) => {
|
||||
const submitted = {
|
||||
horizon: { start: '2024-01-02', end: '2024-02-01' },
|
||||
balances: [
|
||||
{ id: 'cp', type: 'cp' as const, quantity: 4, expiryDate: '2024-01-05' },
|
||||
],
|
||||
rules: [],
|
||||
declaredDays: [
|
||||
{ date: '2024-01-02', type: 'cp' as const },
|
||||
{ date: '2024-01-03', type: 'rtt' as const },
|
||||
{ date: '2024-01-05', type: 'other' as const },
|
||||
],
|
||||
};
|
||||
const { calculatePlanningInternal, calculatePlanningAsyncInternal } =
|
||||
await import('./leave-planner.core');
|
||||
let interruption = false;
|
||||
const direct = cancelled
|
||||
? await calculatePlanningAsyncInternal(
|
||||
{
|
||||
...submitted,
|
||||
progress: (stage: string) => {
|
||||
if (stage === 'non-working-day-gain') interruption = true;
|
||||
},
|
||||
},
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
() => interruption,
|
||||
)
|
||||
: calculatePlanningInternal(submitted);
|
||||
const calculation = createPlanningCalculation({
|
||||
...submitted,
|
||||
progress: (stage) => {
|
||||
if (cancelled && stage === 'non-working-day-gain') calculation.cancel();
|
||||
},
|
||||
});
|
||||
const outcome = await calculation.outcome;
|
||||
expect(outcome.kind).toBe(cancelled ? 'PlanningIncomplete' : 'Plan');
|
||||
expect(direct.kind).toBe(outcome.kind);
|
||||
const plan =
|
||||
outcome.kind === 'Plan'
|
||||
? outcome
|
||||
: outcome.kind === 'PlanningIncomplete'
|
||||
? outcome.incumbent
|
||||
: undefined;
|
||||
const directPlan =
|
||||
direct.kind === 'Plan'
|
||||
? direct
|
||||
: direct.kind === 'PlanningIncomplete'
|
||||
? direct.incumbent
|
||||
: undefined;
|
||||
expect(plan).toBeDefined();
|
||||
expect(plan?.declaredDays).toEqual(submitted.declaredDays);
|
||||
expect(plan?.placements.map(({ date }) => date)).toEqual(['2024-01-04']);
|
||||
expect(directPlan?.placements).toEqual(plan?.placements);
|
||||
expect(plan?.remainingBalances).toMatchObject([{ id: 'cp', quantity: 3 }]);
|
||||
if (!cancelled) expect(outcome).toEqual(direct);
|
||||
expect(await calculation.explanation).toMatchObject({
|
||||
kind: 'PlanExplanation',
|
||||
declaredDays: submitted.declaredDays,
|
||||
});
|
||||
expect((await calculation.trace)?.initialState.declaredDays).toEqual(
|
||||
submitted.declaredDays,
|
||||
);
|
||||
const original = structuredClone(outcome);
|
||||
const comparison = await calculation.analyzeCounterfactual(plan!.placements[0]);
|
||||
for (const { date } of submitted.declaredDays)
|
||||
expect(comparison.results.find((result) => result.date === date)).toMatchObject({
|
||||
status: 'ineligible',
|
||||
reason: { code: 'declared-day' },
|
||||
});
|
||||
expect(await calculation.outcome).toEqual(original);
|
||||
},
|
||||
);
|
||||
|
||||
it('stops during calendar preparation without a plan or an obligation conflict', async () => {
|
||||
const stages: string[] = [];
|
||||
let preparationUpdates = 0;
|
||||
@@ -85,6 +163,7 @@ parentPort.on('message', (data) => globalThis.self.onmessage({ data }));
|
||||
horizon: { start: '2024-01-01', end: '2027-01-01' },
|
||||
balances: [],
|
||||
rules: [],
|
||||
declaredDays: [{ date: '2024-01-02', type: 'other' }],
|
||||
progress: (stage) => {
|
||||
stages.push(stage);
|
||||
if (stage === 'preparation' && ++preparationUpdates === 2) calculation.cancel();
|
||||
@@ -99,7 +178,10 @@ parentPort.on('message', (data) => globalThis.self.onmessage({ data }));
|
||||
expect(outcome.incumbent).toBeUndefined();
|
||||
expect(preparationUpdates).toBeGreaterThanOrEqual(2);
|
||||
expect(stages).not.toContain('obligations');
|
||||
expect((await calculation.trace)?.status).toBe('incomplete');
|
||||
expect(await calculation.trace).toMatchObject({
|
||||
status: 'incomplete',
|
||||
initialState: { declaredDays: [{ date: '2024-01-02', type: 'other' }] },
|
||||
});
|
||||
expect(await calculation.explanationError).toBeUndefined();
|
||||
expect(heartbeats).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user