I firmly believe in free software. The application I'm making here have capabilities that I've not seen in any system. It presents itself as an opportunity to collaborate on a tool that serves the people rather than corporations. Whose incentives are to help people rather, not make the most money. And whose terms ensure that these freedoms and incentives cannot be taken back or subverted. I license this software under the AGPL.
629 lines
20 KiB
TypeScript
629 lines
20 KiB
TypeScript
/*
|
|
SPDX-FileCopyrightText: © 2025 Hornwitser <code@hornwitser.no>
|
|
SPDX-License-Identifier: AGPL-3.0-or-later
|
|
*/
|
|
import { ClientEntity } from "~/utils/client-entity";
|
|
import { ClientSchedule, ClientScheduleEventSlot, ClientScheduleLocation, ClientScheduleShiftSlot, toIso } from "~/utils/client-schedule";
|
|
import { describe, expect, test } from "vitest";
|
|
import type { ApiEntity, ApiSchedule } from "~/shared/types/api";
|
|
import { DateTime, FixedOffsetZone } from "~/shared/utils/luxon";
|
|
|
|
const locale = "en-GB";
|
|
const now = DateTime.now().setLocale(locale);
|
|
const later = now.plus({ minutes: 2 });
|
|
const zone = now.zone;
|
|
const nowIso = now.setZone(FixedOffsetZone.utcInstance).toISO();
|
|
const laterIso = later.setZone(FixedOffsetZone.utcInstance).toISO();
|
|
|
|
function fixtureClientSchedule(multiSlot = false) {
|
|
const left = new ClientScheduleLocation(1, now, false, "Left", "");
|
|
const right = new ClientScheduleLocation(2, now, false, "Right", "This is the right place");
|
|
|
|
const events = [
|
|
new ClientScheduleEvent(
|
|
1, now, false, "Up", false, "", false, "What's Up?", 0, new Set(multiSlot ? [1, 2] : [1]),
|
|
),
|
|
new ClientScheduleEvent(
|
|
2, now, false, "Down", false, "", false, "", 0, new Set(multiSlot ? [] : [2]),
|
|
),
|
|
];
|
|
const eventSlots = idMap([
|
|
new ClientScheduleEventSlot(1, false, false, 1, now, now.plus({ hours: 1 }), new Set([left.id]), new Set(), 0),
|
|
new ClientScheduleEventSlot(2, false, false, multiSlot ? 1 : 2, now, now.plus({ hours: 2 }), new Set([right.id]), new Set(), 0),
|
|
]);
|
|
|
|
const red = new ClientScheduleRole(1, now, false, "Red", "Is a color.");
|
|
const blue = new ClientScheduleRole(2, now, false, "Blue", "");
|
|
const shifts = [
|
|
new ClientScheduleShift(
|
|
1, now, false, red.id, "White", "", new Set(multiSlot ? [1, 2] : [1]),
|
|
),
|
|
new ClientScheduleShift(
|
|
2, now, false, blue.id, "Black", "Is dark.", new Set(multiSlot ? [] : [2]),
|
|
),
|
|
];
|
|
const shiftSlots = idMap([
|
|
new ClientScheduleShiftSlot(1, false, false, 1, now, now.plus({ hours: 1 }), new Set()),
|
|
new ClientScheduleShiftSlot(2, false, false, multiSlot ? 1 : 2, now, now.plus({ hours: 2 }), new Set()),
|
|
]);
|
|
|
|
const schedule = new ClientSchedule(
|
|
111,
|
|
now,
|
|
false,
|
|
new ClientMap(ClientScheduleLocation, idMap([left, right]), new Map()),
|
|
new ClientMap(ClientScheduleEvent, idMap(events), new Map()),
|
|
eventSlots,
|
|
new ClientMap(ClientScheduleRole, idMap([red, blue]), new Map()),
|
|
new ClientMap(ClientScheduleShift, idMap(shifts), new Map()),
|
|
shiftSlots,
|
|
);
|
|
for (const event of events.values()) {
|
|
event.schedule = schedule;
|
|
}
|
|
for (const eventSlot of eventSlots.values()) {
|
|
eventSlot.schedule = schedule;
|
|
}
|
|
for (const shift of shifts.values()) {
|
|
shift.schedule = schedule;
|
|
}
|
|
for (const shiftSlot of shiftSlots.values()) {
|
|
shiftSlot.schedule = schedule;
|
|
}
|
|
return schedule;
|
|
}
|
|
|
|
function fixtureApiSchedule(): ApiSchedule {
|
|
return {
|
|
id: 111,
|
|
updatedAt: nowIso,
|
|
locations: [
|
|
{
|
|
id: 1,
|
|
updatedAt: nowIso,
|
|
name: "Left",
|
|
},
|
|
{
|
|
id: 2,
|
|
updatedAt: nowIso,
|
|
name: "Right",
|
|
description: "This is the right place",
|
|
},
|
|
],
|
|
events: [
|
|
{
|
|
id: 1,
|
|
updatedAt: nowIso,
|
|
name: "Up",
|
|
description: "What's Up?",
|
|
slots: [{
|
|
id: 1,
|
|
start: nowIso,
|
|
end: toIso(now.plus({ hours: 1 })),
|
|
locationIds: [1],
|
|
}],
|
|
},
|
|
{
|
|
id: 2,
|
|
updatedAt: nowIso,
|
|
name: "Down",
|
|
slots: [{
|
|
id: 2,
|
|
start: nowIso,
|
|
end: toIso(now.plus({ hours: 2 })),
|
|
locationIds: [2],
|
|
}],
|
|
},
|
|
],
|
|
roles: [
|
|
{
|
|
id: 1,
|
|
updatedAt: nowIso,
|
|
name: "Red",
|
|
description: "Is a color.",
|
|
},
|
|
{
|
|
id: 2,
|
|
updatedAt: nowIso,
|
|
name: "Blue",
|
|
},
|
|
],
|
|
shifts: [
|
|
{
|
|
id: 1,
|
|
updatedAt: nowIso,
|
|
name: "White",
|
|
roleId: 1,
|
|
slots: [{
|
|
id: 1,
|
|
start: nowIso,
|
|
end: toIso(now.plus({ hours: 1 })),
|
|
}],
|
|
},
|
|
{
|
|
id: 2,
|
|
updatedAt: nowIso,
|
|
name: "Black",
|
|
description: "Is dark.",
|
|
roleId: 2,
|
|
slots: [{
|
|
id: 2,
|
|
start: nowIso,
|
|
end: toIso(now.plus({ hours: 2 })),
|
|
}],
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
describe("class ClientSchedule", () => {
|
|
test("load from api", () => {
|
|
const schedule = ClientSchedule.fromApi(fixtureApiSchedule(), { zone, locale })
|
|
expect(schedule).toStrictEqual(fixtureClientSchedule());
|
|
});
|
|
|
|
test("save to api", () => {
|
|
const schedule = fixtureClientSchedule();
|
|
expect(schedule.toApi(false)).toEqual(fixtureApiSchedule())
|
|
});
|
|
|
|
const entityTests: [string, (schedule: ClientSchedule) => ClientEntity<ApiEntity>][] = [
|
|
[
|
|
"location",
|
|
() => ClientScheduleLocation.create(3, "New location", "", { zone, locale })
|
|
],
|
|
[
|
|
"event",
|
|
(schedule) => ClientScheduleEvent.create(schedule, 3, "New location", false, "", false, "", 0, new Set(), { zone, locale })
|
|
],
|
|
[
|
|
"role",
|
|
() => ClientScheduleRole.create(3, "New location", "", { zone, locale })
|
|
],
|
|
[
|
|
"shift",
|
|
(schedule) => ClientScheduleShift.create(schedule, 3, 1, "New location", "", new Set(), { zone, locale })
|
|
],
|
|
] as const;
|
|
for (const [name, create] of entityTests) {
|
|
describe(name, () => {
|
|
const Name = name[0].toUpperCase() + name.slice(1);
|
|
test(`create`, () => {
|
|
const schedule = fixtureClientSchedule();
|
|
const entity = create(schedule);
|
|
// Create
|
|
(schedule as any)[`${name}s`].add(entity);
|
|
// Check
|
|
expect(schedule.isModified()).toBe(true);
|
|
expect((schedule as any)[`${name}s`].get(entity.id).isModified()).toBe(true);
|
|
expect((schedule as any)[`${name}s`].get(entity.id).isNew()).toBe(true);
|
|
expect((schedule as any)[`${name}s`].get(entity.id)).toBe(entity);
|
|
});
|
|
test("edit", () => {
|
|
const schedule = fixtureClientSchedule();
|
|
const entity = (schedule as any)[`${name}s`].get(1);
|
|
expect(schedule.isModified()).toBe(false);
|
|
expect(entity.isModified()).toBe(false);
|
|
const originalName = entity.name;
|
|
// Edit
|
|
entity.name = `Modified ${name}`;
|
|
// Check
|
|
expect(schedule.isModified()).toBe(true);
|
|
expect(entity.isModified()).toBe(true);
|
|
expect(entity.serverName).toBe(originalName);
|
|
});
|
|
if (name === "location") {
|
|
test.skip("delete location in use throws", () => {
|
|
const schedule = fixtureClientSchedule();
|
|
expect(
|
|
() => { schedule.locations.get(1)!.deleted = true; }
|
|
).toThrow(new Error('Cannot delete location, event "Up" depends on it'));
|
|
});
|
|
} else if (name === "role") {
|
|
test.skip("delete role in use throws", () => {
|
|
const schedule = fixtureClientSchedule();
|
|
expect(
|
|
() => { schedule.roles.get(1)!.deleted = true; }
|
|
).toThrow(new Error('Cannot delete role, shift "White" depends on it'));
|
|
});
|
|
}
|
|
test("delete", () => {
|
|
const schedule = fixtureClientSchedule();
|
|
const entity = (schedule as any)[`${name}s`].get(1);
|
|
expect(schedule.isModified()).toBe(false);
|
|
expect(entity.isModified()).toBe(false);
|
|
// Delete
|
|
if (name === "location") {
|
|
schedule.events.get(1)!.deleted = true;
|
|
} else if (name === "role") {
|
|
schedule.shifts.get(1)!.deleted = true;
|
|
}
|
|
entity.deleted = true;
|
|
// Check
|
|
expect(schedule.isModified()).toBe(true);
|
|
expect(entity.isModified()).toBe(true);
|
|
expect(entity.serverDeleted).toBe(false);
|
|
expect(entity.deleted).toBe(true);
|
|
});
|
|
});
|
|
}
|
|
|
|
describe("event slot", () => {
|
|
test("edit", () => {
|
|
const schedule = fixtureClientSchedule();
|
|
expect(schedule.isModified()).toBe(false);
|
|
expect(schedule.events.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.events.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.eventSlots.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.eventSlots.get(2)!.isModified()).toBe(false);
|
|
// Modify
|
|
schedule.eventSlots.get(1)!.start = later;
|
|
// Check
|
|
expect(schedule.isModified()).toBe(true);
|
|
expect(schedule.events.get(1)!.isModified()).toBe(true);
|
|
expect(schedule.events.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.eventSlots.get(1)!.isModified()).toBe(true);
|
|
expect(schedule.eventSlots.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.events.get(1)!.slots.size).toBe(1);
|
|
expect(schedule.events.get(2)!.slots.size).toBe(1);
|
|
});
|
|
test("add and apply", () => {
|
|
const schedule = fixtureClientSchedule();
|
|
// Add
|
|
const slot = ClientScheduleEventSlot.create(
|
|
schedule,
|
|
3,
|
|
1,
|
|
now,
|
|
now.plus({ hours: 3 }),
|
|
new Set(),
|
|
new Set(),
|
|
0,
|
|
);
|
|
schedule.eventSlots.set(slot.id, slot);
|
|
schedule.events.get(1)!.slotIds.add(slot.id);
|
|
// Sanity check
|
|
expect(schedule.isModified()).toBe(true);
|
|
// Apply change
|
|
schedule.apiUpdate({
|
|
id: 111,
|
|
updatedAt: laterIso,
|
|
events: [{
|
|
id: 1,
|
|
updatedAt: nowIso,
|
|
name: "Up",
|
|
description: "What's Up?",
|
|
slots: [
|
|
{
|
|
id: 1,
|
|
start: nowIso,
|
|
end: toIso(now.plus({ hours: 1 })),
|
|
locationIds: [1],
|
|
},
|
|
{
|
|
id: 3,
|
|
start: nowIso,
|
|
end: toIso(now.plus({ hours: 3 })),
|
|
locationIds: [],
|
|
},
|
|
],
|
|
}],
|
|
}, { zone, locale });
|
|
// Check
|
|
expect(schedule.isModified()).toBe(false);
|
|
expect(schedule.events.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.events.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.eventSlots.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.eventSlots.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.eventSlots.get(3)!.isNewEntity).toBe(false);
|
|
expect(schedule.events.get(1)!.slots.size).toBe(2);
|
|
expect(schedule.events.get(2)!.slots.size).toBe(1);
|
|
});
|
|
test("edit and apply", () => {
|
|
const schedule = fixtureClientSchedule();
|
|
// Modify
|
|
schedule.eventSlots.get(1)!.locationIds.add(2);
|
|
schedule.eventSlots.get(1)!.locationIds.delete(1);
|
|
// Sanity check
|
|
expect(schedule.isModified()).toBe(true);
|
|
// Apply change
|
|
schedule.apiUpdate({
|
|
id: 111,
|
|
updatedAt: laterIso,
|
|
events: [{
|
|
id: 1,
|
|
updatedAt: laterIso,
|
|
name: "Up",
|
|
description: "What's Up?",
|
|
slots: [{
|
|
id: 1,
|
|
start: nowIso,
|
|
end: toIso(now.plus({ hours: 1 })),
|
|
locationIds: [2],
|
|
}],
|
|
}],
|
|
}, { zone, locale });
|
|
// Check
|
|
expect(schedule.isModified()).toBe(false);
|
|
expect(schedule.events.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.events.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.eventSlots.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.eventSlots.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.eventSlots.get(1)!.locationIds).toEqual(new Set([2]));
|
|
expect(schedule.events.get(1)!.slots.size).toBe(1);
|
|
expect(schedule.events.get(2)!.slots.size).toBe(1);
|
|
});
|
|
test("delete and apply", () => {
|
|
const schedule = fixtureClientSchedule(true);
|
|
// delete
|
|
schedule.eventSlots.get(1)!.deleted = true;
|
|
// Sanity check
|
|
expect(schedule.isModified()).toBe(true);
|
|
// Apply change
|
|
schedule.apiUpdate({
|
|
id: 111,
|
|
updatedAt: laterIso,
|
|
events: [{
|
|
id: 1,
|
|
updatedAt: laterIso,
|
|
name: "Up",
|
|
description: "What's Up?",
|
|
slots: [{
|
|
id: 2,
|
|
start: nowIso,
|
|
end: toIso(now.plus({ hours: 2 })),
|
|
locationIds: [2],
|
|
}],
|
|
}],
|
|
}, { zone, locale });
|
|
// Check
|
|
expect(schedule.isModified()).toBe(false);
|
|
expect(schedule.events.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.events.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.eventSlots.has(1)).toBe(false);
|
|
expect(schedule.eventSlots.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.events.get(1)!.slots.size).toBe(1);
|
|
expect(schedule.events.get(2)!.slots.size).toBe(0);
|
|
});
|
|
test("move to another event", () => {
|
|
const schedule = fixtureClientSchedule();
|
|
expect(schedule.isModified()).toBe(false);
|
|
expect(schedule.events.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.events.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.eventSlots.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.eventSlots.get(2)!.isModified()).toBe(false);
|
|
// Modify
|
|
schedule.eventSlots.get(1)!.setEventId(2);
|
|
// Check
|
|
expect(schedule.isModified()).toBe(true);
|
|
expect(schedule.events.get(1)!.isModified()).toBe(true);
|
|
expect(schedule.events.get(2)!.isModified()).toBe(true);
|
|
expect(schedule.eventSlots.get(1)!.isModified()).toBe(true);
|
|
expect(schedule.eventSlots.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.events.get(1)!.slots.size).toBe(0);
|
|
expect(schedule.events.get(2)!.slots.size).toBe(2);
|
|
// Move back
|
|
schedule.eventSlots.get(1)!.setEventId(1);
|
|
// Check
|
|
expect(schedule.isModified()).toBe(false);
|
|
expect(schedule.events.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.events.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.eventSlots.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.eventSlots.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.events.get(1)!.slots.size).toBe(1);
|
|
expect(schedule.events.get(2)!.slots.size).toBe(1);
|
|
});
|
|
test("discard", () => {
|
|
const schedule = fixtureClientSchedule();
|
|
schedule.eventSlots.get(1)!.start = later;
|
|
schedule.eventSlots.get(1)!.discard();
|
|
// Check
|
|
expect(schedule.isModified()).toBe(false);
|
|
expect(schedule.events.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.events.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.eventSlots.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.eventSlots.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.events.get(1)!.slots.size).toBe(1);
|
|
expect(schedule.events.get(2)!.slots.size).toBe(1);
|
|
});
|
|
test("discard from another event", () => {
|
|
const schedule = fixtureClientSchedule();
|
|
schedule.eventSlots.get(1)!.setEventId(2);
|
|
schedule.eventSlots.get(1)!.discard();
|
|
// Check
|
|
expect(schedule.isModified()).toBe(false);
|
|
expect(schedule.events.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.events.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.eventSlots.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.eventSlots.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.events.get(1)!.slots.size).toBe(1);
|
|
expect(schedule.events.get(2)!.slots.size).toBe(1);
|
|
});
|
|
});
|
|
|
|
describe("shift slot", () => {
|
|
test("edit", () => {
|
|
const schedule = fixtureClientSchedule();
|
|
expect(schedule.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.shiftSlots.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.shiftSlots.get(2)!.isModified()).toBe(false);
|
|
// Modify
|
|
schedule.shiftSlots.get(1)!.start = later;
|
|
// Check
|
|
expect(schedule.isModified()).toBe(true);
|
|
expect(schedule.shifts.get(1)!.isModified()).toBe(true);
|
|
expect(schedule.shifts.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.shiftSlots.get(1)!.isModified()).toBe(true);
|
|
expect(schedule.shiftSlots.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(1)!.slots.size).toBe(1);
|
|
expect(schedule.shifts.get(2)!.slots.size).toBe(1);
|
|
});
|
|
test("add and apply", () => {
|
|
const schedule = fixtureClientSchedule();
|
|
// Add
|
|
const slot = ClientScheduleShiftSlot.create(
|
|
schedule,
|
|
3,
|
|
1,
|
|
now,
|
|
now.plus({ hours: 3 }),
|
|
new Set(),
|
|
);
|
|
schedule.shiftSlots.set(slot.id, slot);
|
|
schedule.shifts.get(1)!.slotIds.add(slot.id);
|
|
// Sanity check
|
|
expect(schedule.isModified()).toBe(true);
|
|
// Apply change
|
|
schedule.apiUpdate({
|
|
id: 111,
|
|
updatedAt: laterIso,
|
|
shifts: [{
|
|
id: 1,
|
|
updatedAt: nowIso,
|
|
name: "White",
|
|
roleId: 1,
|
|
slots: [
|
|
{
|
|
id: 1,
|
|
start: nowIso,
|
|
end: toIso(now.plus({ hours: 1 })),
|
|
},
|
|
{
|
|
id: 3,
|
|
start: nowIso,
|
|
end: toIso(now.plus({ hours: 3 })),
|
|
},
|
|
],
|
|
}],
|
|
}, { zone, locale });
|
|
// Check
|
|
expect(schedule.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.shiftSlots.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.shiftSlots.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.shiftSlots.get(3)!.isNewEntity).toBe(false);
|
|
expect(schedule.shifts.get(1)!.slots.size).toBe(2);
|
|
expect(schedule.shifts.get(2)!.slots.size).toBe(1);
|
|
});
|
|
test("edit and apply", () => {
|
|
const schedule = fixtureClientSchedule();
|
|
// Modify
|
|
schedule.shiftSlots.get(1)!.assigned.add(2);
|
|
// Sanity check
|
|
expect(schedule.isModified()).toBe(true);
|
|
// Apply change
|
|
schedule.apiUpdate({
|
|
id: 111,
|
|
updatedAt: laterIso,
|
|
shifts: [{
|
|
id: 1,
|
|
updatedAt: nowIso,
|
|
name: "White",
|
|
roleId: 1,
|
|
slots: [{
|
|
id: 1,
|
|
start: nowIso,
|
|
end: toIso(now.plus({ hours: 1 })),
|
|
assigned: [2],
|
|
}],
|
|
}],
|
|
}, { zone, locale });
|
|
// Check
|
|
expect(schedule.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.shiftSlots.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.shiftSlots.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.shiftSlots.get(1)!.assigned).toEqual(new Set([2]));
|
|
expect(schedule.shifts.get(1)!.slots.size).toBe(1);
|
|
});
|
|
test("delete and apply", () => {
|
|
const schedule = fixtureClientSchedule(true);
|
|
// delete
|
|
schedule.shiftSlots.get(1)!.deleted = true;
|
|
// Sanity check
|
|
expect(schedule.isModified()).toBe(true);
|
|
// Apply change
|
|
schedule.apiUpdate({
|
|
id: 111,
|
|
updatedAt: laterIso,
|
|
shifts: [{
|
|
id: 1,
|
|
updatedAt: nowIso,
|
|
name: "White",
|
|
roleId: 1,
|
|
slots: [{
|
|
id: 2,
|
|
start: nowIso,
|
|
end: toIso(now.plus({ hours: 2 })),
|
|
}],
|
|
}],
|
|
}, { zone, locale });
|
|
// Check
|
|
expect(schedule.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.shiftSlots.has(1)).toBe(false);
|
|
expect(schedule.shiftSlots.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(1)!.slots.size).toBe(1);
|
|
expect(schedule.shifts.get(2)!.slots.size).toBe(0);
|
|
});
|
|
test("move to another shift", () => {
|
|
const schedule = fixtureClientSchedule();
|
|
expect(schedule.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.shiftSlots.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.shiftSlots.get(2)!.isModified()).toBe(false);
|
|
// Modify
|
|
schedule.shiftSlots.get(1)!.setShiftId(2);
|
|
// Check
|
|
expect(schedule.isModified()).toBe(true);
|
|
expect(schedule.shifts.get(1)!.isModified()).toBe(true);
|
|
expect(schedule.shifts.get(2)!.isModified()).toBe(true);
|
|
expect(schedule.shiftSlots.get(1)!.isModified()).toBe(true);
|
|
expect(schedule.shiftSlots.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(1)!.slots.size).toBe(0);
|
|
expect(schedule.shifts.get(2)!.slots.size).toBe(2);
|
|
// Move back
|
|
schedule.shiftSlots.get(1)!.setShiftId(1);
|
|
// Check
|
|
expect(schedule.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.shiftSlots.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.shiftSlots.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(1)!.slots.size).toBe(1);
|
|
expect(schedule.shifts.get(2)!.slots.size).toBe(1);
|
|
});
|
|
test("discard", () => {
|
|
const schedule = fixtureClientSchedule();
|
|
schedule.shiftSlots.get(1)!.start = later;
|
|
schedule.shiftSlots.get(1)!.discard();
|
|
// Check
|
|
expect(schedule.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.shiftSlots.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.shiftSlots.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(1)!.slots.size).toBe(1);
|
|
expect(schedule.shifts.get(2)!.slots.size).toBe(1);
|
|
});
|
|
test("discard from another shift", () => {
|
|
const schedule = fixtureClientSchedule();
|
|
schedule.shiftSlots.get(1)!.setShiftId(2);
|
|
schedule.shiftSlots.get(1)!.discard();
|
|
// Check
|
|
expect(schedule.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.shiftSlots.get(1)!.isModified()).toBe(false);
|
|
expect(schedule.shiftSlots.get(2)!.isModified()).toBe(false);
|
|
expect(schedule.shifts.get(1)!.slots.size).toBe(1);
|
|
expect(schedule.shifts.get(2)!.slots.size).toBe(1);
|
|
});
|
|
});
|
|
});
|