Table sorting preferences will be saved and reused based on the user’s selections

This commit is contained in:
2026-10-25 00:39:55 -03:00
parent 19edee4e11
commit 0f1f399d1a
40 changed files with 896 additions and 230 deletions

View File

@@ -53,6 +53,18 @@ function setup(items = [opportunity("A", "2026-11-15")]) {
return h;
}
test("calendar controls, accessibility labels and missing dates are English", () => {
const h = setup([opportunity("A", "2026-11-15"), opportunity("B", null)]);
const { options } = h.activate();
assert.equal(options.locale, "en");
assert.deepEqual(plain(options.buttonText), { today: "Today", month: "Month", week: "Week" });
assert.deepEqual(plain(options.buttonHints), { prev: "Previous", next: "Next", today: "Today", dayGridMonth: "Month", dayGridWeek: "Week" });
assert.equal(options.moreLinkHint(1), "View 1 more opportunity");
assert.equal(options.moreLinkHint(3), "View 3 more opportunities");
assert.ok(h.nodes().some(node => node.attributes["aria-label"] === "Opportunity views"));
assert.ok(h.nodes().some(node => node.textContent === "No valid Close Date (1)"));
});
test("close dates retain the API day across offsets and reject invalid dates", () => {
const { api } = setup();
for (const date of ["2026-11-15", "2026-11-15T00:00:00Z", "2026-11-15T23:00:00-05:00"]) assert.equal(api.closeDate(date), "2026-11-15");
@@ -81,10 +93,10 @@ test("daily count badges follow filters and are cleaned up when cells unmount",
const badge = frame.children[0];
assert.equal(badge.textContent, "3");
assert.equal(badge.hidden, false);
assert.equal(badge.attributes["aria-label"], "3 oportunidades");
assert.equal(badge.attributes["aria-label"], "3 opportunities");
h.api.render([h.state.items[0]], h.state);
assert.equal(badge.textContent, "1");
assert.equal(badge.attributes["aria-label"], "1 oportunidade");
assert.equal(badge.attributes["aria-label"], "1 opportunity");
h.api.render([], h.state);
assert.equal(badge.textContent, "0");
assert.equal(badge.attributes["data-empty"], "true");
@@ -120,7 +132,7 @@ test("overview is the default; tabs lazily initialize and reuse a monthly/weekly
assert.equal(h.table.hidden, false); assert.equal(surface.hidden, true); assert.equal(h.loads, 0);
const tabs = h.nodes().filter(element => element.attributes.role === "tab");
assert.deepEqual(tabs.map(tab => tab.children[0].view), ["overview", "calendar"]);
assert.deepEqual(tabs.map(tab => tab.children[1].textContent), ["Vis\u00e3o geral", "Calend\u00e1rio"]);
assert.deepEqual(tabs.map(tab => tab.children[1].textContent), ["Overview", "Calendar"]);
assert.equal(tabs[0].attributes["aria-selected"], "true");
tabs[1].click();
const instance = h.instances[0];
@@ -171,7 +183,7 @@ test("undated opportunities remain visible and open read-only details", () => {
assert.ok(h.nodes().some(node => node.attributes.role === "dialog"));
assert.deepEqual(h.nodes().filter(node => node.tag === "dt").map(node => node.textContent), ["Customer", "Owner", "Close Date", "Amount"]);
assert.equal(h.nodes().find(node => node.tag === "a").href, "https://example.invalid/?puid=A");
assert.ok(h.nodes().some(node => node.tag === "dd" && node.textContent === "N/D"));
assert.ok(h.nodes().some(node => node.tag === "dd" && node.textContent === "N/A"));
assert.equal(h.api.closeDetails(), true);
assert.equal(h.document.activeElement, undated.children[1]);
});
@@ -216,7 +228,7 @@ test("overflow uses our dialog instead of the FullCalendar offsetParent-dependen
test("calendar events show their stage and handle missing stage values", () => {
const h = setup();
const calendar = h.activate();
for (const [value, label] of [["FORECAST", "FORECAST"], ["UPSIDE", "UPSIDE"], [null, "N/D"]]) {
for (const [value, label] of [["FORECAST", "FORECAST"], ["UPSIDE", "UPSIDE"], [null, "N/A"]]) {
const item = { ...h.state.items[0], ForecastGroup_c: value };
const { domNodes } = calendar.options.eventContent({ event: { title: item.Name, extendedProps: { item } } });
assert.equal(domNodes[0].children.length, 2);