chore(react/collections/calendar): reintroduce tests

This commit is contained in:
Elian Doran 2025-09-06 11:20:39 +03:00
parent 69af62cde0
commit 10a6a3056a
No known key found for this signature in database
4 changed files with 30 additions and 45 deletions

View File

@ -1,6 +1,7 @@
import { describe, expect, it } from "vitest";
import { buildNote, buildNotes } from "../../test/easy-froca.js";
import CalendarView, { getFullCalendarLocale } from "./calendar_view.js";
import { buildNote, buildNotes } from "../../../test/easy-froca.js";
import { buildEvent, buildEvents } from "./event_builder.js";
import { LOCALE_MAPPINGS } from "./index.js";
import { LOCALES } from "@triliumnext/commons";
describe("Building events", () => {
@ -9,7 +10,7 @@ describe("Building events", () => {
{ title: "Note 1", "#startDate": "2025-05-05" },
{ title: "Note 2", "#startDate": "2025-05-07" },
]);
const events = await CalendarView.buildEvents(noteIds);
const events = await buildEvents(noteIds);
expect(events).toHaveLength(2);
expect(events[0]).toMatchObject({ title: "Note 1", start: "2025-05-05", end: "2025-05-06" });
@ -21,7 +22,7 @@ describe("Building events", () => {
{ title: "Note 1", "#endDate": "2025-05-05" },
{ title: "Note 2", "#endDateDate": "2025-05-07" }
]);
const events = await CalendarView.buildEvents(noteIds);
const events = await buildEvents(noteIds);
expect(events).toHaveLength(0);
});
@ -31,7 +32,7 @@ describe("Building events", () => {
{ title: "Note 1", "#startDate": "2025-05-05", "#endDate": "2025-05-05" },
{ title: "Note 2", "#startDate": "2025-05-07", "#endDate": "2025-05-08" },
]);
const events = await CalendarView.buildEvents(noteIds);
const events = await buildEvents(noteIds);
expect(events).toHaveLength(2);
expect(events[0]).toMatchObject({ title: "Note 1", start: "2025-05-05", end: "2025-05-06" });
@ -43,7 +44,7 @@ describe("Building events", () => {
{ title: "Note 1", "#myStartDate": "2025-05-05", "#calendar:startDate": "myStartDate" },
{ title: "Note 2", "#startDate": "2025-05-07", "#calendar:startDate": "myStartDate" },
]);
const events = await CalendarView.buildEvents(noteIds);
const events = await buildEvents(noteIds);
expect(events).toHaveLength(2);
expect(events[0]).toMatchObject({
@ -65,7 +66,7 @@ describe("Building events", () => {
{ title: "Note 3", "#startDate": "2025-05-05", "#myEndDate": "2025-05-05", "#calendar:startDate": "myStartDate", "#calendar:endDate": "myEndDate" },
{ title: "Note 4", "#startDate": "2025-05-07", "#myEndDate": "2025-05-08", "#calendar:startDate": "myStartDate", "#calendar:endDate": "myEndDate" },
]);
const events = await CalendarView.buildEvents(noteIds);
const events = await buildEvents(noteIds);
expect(events).toHaveLength(4);
expect(events[0]).toMatchObject({ title: "Note 1", start: "2025-05-05", end: "2025-05-06" });
@ -79,7 +80,7 @@ describe("Building events", () => {
{ title: "Note 1", "#myTitle": "My Custom Title 1", "#startDate": "2025-05-05", "#calendar:title": "myTitle" },
{ title: "Note 2", "#startDate": "2025-05-07", "#calendar:title": "myTitle" },
]);
const events = await CalendarView.buildEvents(noteIds);
const events = await buildEvents(noteIds);
expect(events).toHaveLength(2);
expect(events[0]).toMatchObject({ title: "My Custom Title 1", start: "2025-05-05" });
@ -92,7 +93,7 @@ describe("Building events", () => {
{ title: "Note 1", "~myTitle": "mySharedTitle", "#startDate": "2025-05-05", "#calendar:title": "myTitle" },
{ title: "Note 2", "#startDate": "2025-05-07", "#calendar:title": "myTitle" },
]);
const events = await CalendarView.buildEvents(noteIds);
const events = await buildEvents(noteIds);
expect(events).toHaveLength(2);
expect(events[0]).toMatchObject({ title: "My shared title", start: "2025-05-05" });
@ -105,7 +106,7 @@ describe("Building events", () => {
{ title: "Note 1", "~myTitle": "mySharedTitle", "#startDate": "2025-05-05", "#calendar:title": "myTitle" },
{ title: "Note 2", "#startDate": "2025-05-07", "#calendar:title": "myTitle" },
]);
const events = await CalendarView.buildEvents(noteIds);
const events = await buildEvents(noteIds);
expect(events).toHaveLength(2);
expect(events[0]).toMatchObject({ title: "My shared custom title", start: "2025-05-05" });
@ -125,7 +126,7 @@ describe("Promoted attributes", () => {
"#calendar:displayedAttributes": "weight,mood"
});
const event = await CalendarView.buildEvent(note, { startDate: "2025-04-04" });
const event = await buildEvent(note, { startDate: "2025-04-04" });
expect(event).toHaveLength(1);
expect(event[0]?.promotedAttributes).toMatchObject([
[ "weight", "75" ],
@ -143,7 +144,7 @@ describe("Promoted attributes", () => {
"#relation:assignee": "promoted,alias=Assignee,single,text",
});
const event = await CalendarView.buildEvent(note, { startDate: "2025-04-04" });
const event = await buildEvent(note, { startDate: "2025-04-04" });
expect(event).toHaveLength(1);
expect(event[0]?.promotedAttributes).toMatchObject([
[ "assignee", "Target note" ]
@ -155,7 +156,7 @@ describe("Promoted attributes", () => {
{ title: "Note 1", "#startDate": "2025-05-05", "#startTime": "13:36", "#endTime": "14:56" },
{ title: "Note 2", "#startDate": "2025-05-07", "#endDate": "2025-05-08", "#startTime": "13:36", "#endTime": "14:56" },
]);
const events = await CalendarView.buildEvents(noteIds);
const events = await buildEvents(noteIds);
expect(events).toHaveLength(2);
expect(events[0]).toMatchObject({ title: "Note 1", start: "2025-05-05T13:36:00", end: "2025-05-05T14:56:00" });
@ -167,7 +168,7 @@ describe("Promoted attributes", () => {
{ title: "Note 1", "#startDate": "2025-05-05", "#startTime": "13:30" },
{ title: "Note 2", "#startDate": "2025-05-07", "#endDate": "2025-05-08", "#startTime": "13:36" },
]);
const events = await CalendarView.buildEvents(noteIds);
const events = await buildEvents(noteIds);
expect(events).toHaveLength(2);
expect(events[0]).toMatchObject({ title: "Note 1", start: "2025-05-05T13:30:00" });
@ -183,12 +184,12 @@ describe("Building locales", () => {
continue;
}
const fullCalendarLocale = await getFullCalendarLocale(id);
const fullCalendarLocale = LOCALE_MAPPINGS[id];
if (id !== "en") {
expect(fullCalendarLocale, `For locale ${id}`).toBeDefined();
} else {
expect(fullCalendarLocale).toBeUndefined();
expect(fullCalendarLocale).toBeNull();
}
}
});

View File

@ -75,7 +75,7 @@ export async function buildEventsForCalendar(note: FNote, e: EventSourceFuncArg)
return events.flat();
}
async function buildEvent(note: FNote, { startDate, endDate, startTime, endTime }: Event) {
export async function buildEvent(note: FNote, { startDate, endDate, startTime, endTime }: Event) {
const customTitleAttributeName = note.getLabelValue("calendar:title");
const titles = await parseCustomTitle(customTitleAttributeName, note);
const color = note.getLabelValue("calendar:color") ?? note.getLabelValue("color");

View File

@ -3,12 +3,9 @@ import { ViewModeProps } from "../interface";
import Calendar from "./calendar";
import { useCallback, useEffect, useMemo, useRef, useState } from "preact/hooks";
import "./index.css";
import { useNoteLabel, useNoteLabelBoolean, useResizeObserver, useSpacedUpdate, useTriliumOption, useTriliumOptionInt } from "../../react/hooks";
import { CreateChildrenResponse, LOCALE_IDS } from "@triliumnext/commons";
import { useNoteLabel, useNoteLabelBoolean, useResizeObserver, useSpacedUpdate, useTriliumEvent, useTriliumOption, useTriliumOptionInt } from "../../react/hooks";
import { LOCALE_IDS } from "@triliumnext/commons";
import { Calendar as FullCalendar } from "@fullcalendar/core";
import { removeOwnedAttributesByNameOrType, setLabel } from "../../../services/attributes";
import { circle } from "leaflet";
import server from "../../../services/server";
import { parseStartEndDateFromEvent, parseStartEndTimeFromEvent } from "./utils";
import dialog from "../../../services/dialog";
import { t } from "../../../services/i18n";
@ -32,7 +29,7 @@ const CALENDAR_VIEWS = [
]
// Here we hard-code the imports in order to ensure that they are embedded by webpack without having to load all the languages.
const LOCALE_MAPPINGS: Record<LOCALE_IDS, (() => Promise<{ default: LocaleInput }>) | null> = {
export const LOCALE_MAPPINGS: Record<LOCALE_IDS, (() => Promise<{ default: LocaleInput }>) | null> = {
de: () => import("@fullcalendar/core/locales/de"),
es: () => import("@fullcalendar/core/locales/es"),
fr: () => import("@fullcalendar/core/locales/fr"),
@ -75,6 +72,15 @@ export default function CalendarView({ note, noteIds }: ViewModeProps<CalendarVi
const { eventDidMount } = useEventDisplayCustomization();
const editingProps = useEditing(note, isEditable, isCalendarRoot);
// React to changes.
useTriliumEvent("entitiesReloaded", ({ loadResults }) => {
if (loadResults.getNoteIds().some(noteId => noteIds.includes(noteId)) // note title change.
|| loadResults.getAttributeRows().some((a) => noteIds.includes(a.noteId ?? ""))) // subnote change.
{
calendarRef.current?.refetchEvents();
}
});
return (plugins &&
<div className="calendar-view" ref={containerRef}>
<Calendar

View File

@ -39,28 +39,6 @@ export default class CalendarView extends ViewMode<{}> {
}
}
async onEntitiesReloaded({ loadResults }: EventData<"entitiesReloaded">) {
// Refresh note IDs if they got changed.
if (loadResults.getBranchRows().some((branch) => branch.parentNoteId === this.parentNote.noteId)) {
this.noteIds = this.parentNote.getChildNoteIds();
}
// Refresh calendar on attribute change.
if (loadResults.getAttributeRows().some((attribute) => attribute.noteId === this.parentNote.noteId && attribute.name?.startsWith("calendar:") && attribute.name !== "calendar:view")) {
return true;
}
// Refresh on note title change.
if (loadResults.getNoteIds().some(noteId => this.noteIds.includes(noteId))) {
this.calendar?.refetchEvents();
}
// Refresh dataset on subnote change.
if (loadResults.getAttributeRows().some((a) => this.noteIds.includes(a.noteId ?? ""))) {
this.calendar?.refetchEvents();
}
}
buildTouchBarCommand({ TouchBar, buildIcon }: CommandListenerData<"buildTouchBar">) {
if (!this.calendar) {
return;