discourse/plugins/discourse-local-dates/test/javascripts/unit/discourse-local-dates-test.js
Régis Hanol adbb820c94
FIX: Respect custom date format selection in local dates (#36860)
When inserting a date with a custom format like "LTS", the format was
being silently changed to "LL". This happened because the code assumed
any format without a time value should fall back to date-only display,
but that logic was too broad.

Additionally, the markdown preview and rich text editor showed different
results for the same date - the preview displayed "Today 3:25 PM" while
the rich editor showed "December 24, 2025 3:25 PM". This inconsistency
stemmed from calendar mode (relative dates) being always-on in the
preview but disabled when a format was specified in the rich editor.

The fix narrows the format fallback to only apply when using combined
date+time formats (LLL, LLLL) without a time - these are the only cases
where falling back to a date-only format actually makes sense. For
time-only formats like LTS or already date-only formats like LL, we now
preserve the user's choice.

Calendar mode now behaves consistently: it's enabled by default for
relative dates like "Today", but automatically disabled when a custom
format is specified, matching what users expect when they explicitly
choose a format.

Follow up to https://github.com/discourse/discourse/pull/36781

**BEFORE**

<img width="1746" height="1372" alt="2025-12-24 @ 15 44 34"
src="https://github.com/user-attachments/assets/9420cff8-424c-4f57-a5c7-8e2ca8885b2c"
/>

**AFTER**

<img width="1746" height="1372" alt="2025-12-24 @ 15 43 07"
src="https://github.com/user-attachments/assets/d38a03d6-bb6a-4287-9d44-6cf8a23f6aa9"
/>

**IT WORKED FINE IN RICH TEXT**

<img width="1746" height="1372" alt="2025-12-24 @ 15 44 44"
src="https://github.com/user-attachments/assets/7259cc88-57d0-4ab6-98b1-908753e41530"
/>
2025-12-24 16:42:33 +01:00

125 lines
3.8 KiB
JavaScript

import { setupTest } from "ember-qunit";
import { module, test } from "qunit";
import freezeTime from "../helpers/freeze-time";
import { applyLocalDates } from "../initializers/discourse-local-dates";
module("Unit | discourse-local-dates", function (hooks) {
setupTest(hooks);
function createElementFromHTML(htmlString) {
const div = document.createElement("div");
div.innerHTML = htmlString.trim();
// we need "element", not "node", since `.dataset` isn't available on nodes
return div.firstElementChild;
}
const fromElement = () =>
createElementFromHTML(
"<span " +
'data-date="2022-10-06" ' +
'data-time="17:21:00" ' +
'class="discourse-local-date" ' +
'data-range="from" ' +
'data-timezone="Asia/Singapore" ' +
'data-title="Testing dates with the local date builder">' +
"</span>"
);
const toElement = () =>
createElementFromHTML(
"<span " +
'data-date="2022-10-06" ' +
'data-time="22:22:00" ' +
'class="discourse-local-date" ' +
'data-range="to" ' +
'data-timezone="Asia/Singapore" ' +
'data-title="Testing dates with the local date builder">' +
"</span>"
);
test("applyLocalDates sets formatted relative time", function (assert) {
const from = fromElement();
const to = toElement();
const dateElements = [from, to];
freezeTime(
{ date: "2022-10-07T10:10:10", timezone: "Asia/Singapore" },
() => {
applyLocalDates(dateElements, {
discourse_local_dates_enabled: true,
});
assert.dom(".relative-time", from).hasText("Yesterday 5:21 PM");
assert.dom(".relative-time", to).hasText("10:22 PM (Singapore)");
}
);
});
test("applyLocalDates does not fail when a date element has no time", function (assert) {
const from = fromElement();
const to = toElement();
delete to.dataset.time;
const dateElements = [from, to];
freezeTime(
{ date: "2022-10-07T10:10:10", timezone: "Asia/Singapore" },
() => {
applyLocalDates(dateElements, {
discourse_local_dates_enabled: true,
});
assert.dom(".relative-time", from).hasText("Yesterday 5:21 PM");
assert.dom(".relative-time", to).hasText("Yesterday");
}
);
});
test("applyLocalDates disables calendar mode when custom format is specified", function (assert) {
const element = createElementFromHTML(
"<span " +
'data-date="2022-10-06" ' +
'data-time="17:21:00" ' +
'class="discourse-local-date" ' +
'data-format="LLL" ' +
'data-timezone="Asia/Singapore">' +
"</span>"
);
freezeTime(
{ date: "2022-10-06T10:10:10", timezone: "Asia/Singapore" },
() => {
applyLocalDates([element], {
discourse_local_dates_enabled: true,
});
// With calendar mode, this would show "Today 5:21 PM"
// With calendar disabled (due to custom format), it shows full date
assert
.dom(".relative-time", element)
.hasText("October 6, 2022 5:21 PM");
}
);
});
test("applyLocalDates uses calendar mode when no custom format is specified", function (assert) {
const element = createElementFromHTML(
"<span " +
'data-date="2022-10-06" ' +
'data-time="17:21:00" ' +
'class="discourse-local-date" ' +
'data-timezone="Asia/Singapore">' +
"</span>"
);
freezeTime(
{ date: "2022-10-06T10:10:10", timezone: "Asia/Singapore" },
() => {
applyLocalDates([element], {
discourse_local_dates_enabled: true,
});
// Without custom format, calendar mode is enabled, showing relative date
assert.dom(".relative-time", element).hasText("Today 5:21 PM");
}
);
});
});