mirror of
https://github.com/discourse/discourse.git
synced 2025-05-22 07:53:49 +08:00
REFACTOR: local dates to improve reliability with DST and recurrence (#9379)
This commit improves testing and separates local-date generation from dates with zone manipulations.
This commit is contained in:
@ -1,463 +0,0 @@
|
||||
import { acceptance } from "helpers/qunit-helpers";
|
||||
|
||||
const sandbox = sinon.createSandbox();
|
||||
|
||||
acceptance("Local Dates", {
|
||||
loggedIn: true,
|
||||
settings: {
|
||||
discourse_local_dates_enabled: true,
|
||||
discourse_local_dates_default_timezones: "Europe/Paris|America/Los_Angeles"
|
||||
},
|
||||
beforeEach() {
|
||||
freezeDateAndZone();
|
||||
},
|
||||
afterEach() {
|
||||
sandbox.restore();
|
||||
moment.tz.setDefault();
|
||||
}
|
||||
});
|
||||
|
||||
const DEFAULT_DATE = "2018-06-20";
|
||||
const DEFAULT_ZONE = "Europe/Paris";
|
||||
const DEFAULT_ZONE_FORMATED = DEFAULT_ZONE.split("/")[1];
|
||||
|
||||
function advance(count, unit = "days") {
|
||||
return moment(DEFAULT_DATE)
|
||||
.add(count, unit)
|
||||
.format("YYYY-MM-DD");
|
||||
}
|
||||
|
||||
function rewind(count, unit = "days") {
|
||||
return moment(DEFAULT_DATE)
|
||||
.subtract(count, unit)
|
||||
.format("YYYY-MM-DD");
|
||||
}
|
||||
|
||||
function freezeDateAndZone(date, zone, cb) {
|
||||
date = date || DEFAULT_DATE;
|
||||
zone = zone || DEFAULT_ZONE;
|
||||
|
||||
sandbox.restore();
|
||||
sandbox.stub(moment.tz, "guess");
|
||||
moment.tz.guess.returns(zone);
|
||||
moment.tz.setDefault(zone);
|
||||
|
||||
const now = moment(date).valueOf();
|
||||
sandbox.useFakeTimers(now);
|
||||
|
||||
if (cb) {
|
||||
cb();
|
||||
|
||||
moment.tz.guess.returns(DEFAULT_ZONE);
|
||||
moment.tz.setDefault(DEFAULT_ZONE);
|
||||
sandbox.useFakeTimers(moment(DEFAULT_DATE).valueOf());
|
||||
}
|
||||
}
|
||||
|
||||
function generateHTML(options = {}) {
|
||||
let output = `<span class="discourse-local-date past cooked-date"`;
|
||||
|
||||
output += ` data-date="${options.date || DEFAULT_DATE}"`;
|
||||
if (options.format) output += ` data-format="${options.format}"`;
|
||||
if (options.timezones) output += ` data-timezones="${options.timezones}"`;
|
||||
if (options.time) output += ` data-time="${options.time}"`;
|
||||
output += ` data-timezone="${options.timezone || DEFAULT_ZONE}"`;
|
||||
if (options.calendar) output += ` data-calendar="${options.calendar}"`;
|
||||
if (options.recurring) output += ` data-recurring="${options.recurring}"`;
|
||||
if (options.displayedTimezone)
|
||||
output += ` data-displayed-timezone="${options.displayedTimezone}"`;
|
||||
|
||||
return (output += "></span>");
|
||||
}
|
||||
|
||||
test("default format - time specified", assert => {
|
||||
const html = generateHTML({ date: advance(3), time: "02:00" });
|
||||
const transformed = $(html).applyLocalDates();
|
||||
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
"June 23, 2018 2:00 AM",
|
||||
"it uses moment LLL format"
|
||||
);
|
||||
});
|
||||
|
||||
test("default format - no time specified", assert => {
|
||||
let html = generateHTML({ date: advance(3) });
|
||||
let transformed = $(html).applyLocalDates();
|
||||
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
"June 23, 2018",
|
||||
"it uses moment LL format as default if not time is specified"
|
||||
);
|
||||
|
||||
freezeDateAndZone(advance(1), "Pacific/Auckland", () => {
|
||||
html = generateHTML({ date: advance(3) });
|
||||
transformed = $(html).applyLocalDates();
|
||||
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
`June 23, 2018 (${DEFAULT_ZONE_FORMATED})`,
|
||||
"it appends creator timezone if watching user timezone is different"
|
||||
);
|
||||
});
|
||||
|
||||
freezeDateAndZone(advance(1), "Europe/Vienna", () => {
|
||||
html = generateHTML({ date: advance(3) });
|
||||
transformed = $(html).applyLocalDates();
|
||||
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
"June 23, 2018",
|
||||
"it doesn’t append timezone if different but with the same utc offset"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("today", assert => {
|
||||
const html = generateHTML({ time: "16:00" });
|
||||
const transformed = $(html).applyLocalDates();
|
||||
|
||||
assert.equal(transformed.text().trim(), "Today 4:00 PM", "it display Today");
|
||||
});
|
||||
|
||||
test("today - no time", assert => {
|
||||
const html = generateHTML();
|
||||
const transformed = $(html).applyLocalDates();
|
||||
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
"Today",
|
||||
"it display Today without time"
|
||||
);
|
||||
});
|
||||
|
||||
test("yesterday", assert => {
|
||||
const html = generateHTML({ date: rewind(1), time: "16:00" });
|
||||
const transformed = $(html).applyLocalDates();
|
||||
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
"Yesterday 4:00 PM",
|
||||
"it displays yesterday"
|
||||
);
|
||||
});
|
||||
|
||||
test("yesterday - no time", assert => {
|
||||
const html = generateHTML({ date: rewind(1) });
|
||||
const transformed = $(html).applyLocalDates();
|
||||
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
"Yesterday",
|
||||
"it displays yesterday without time"
|
||||
);
|
||||
});
|
||||
|
||||
test("tomorrow", assert => {
|
||||
const html = generateHTML({ date: advance(1), time: "16:00" });
|
||||
const transformed = $(html).applyLocalDates();
|
||||
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
"Tomorrow 4:00 PM",
|
||||
"it displays tomorrow"
|
||||
);
|
||||
});
|
||||
|
||||
test("tomorrow - no time", assert => {
|
||||
const html = generateHTML({ date: advance(1) });
|
||||
const transformed = $(html).applyLocalDates();
|
||||
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
"Tomorrow",
|
||||
"it displays tomorrow without time"
|
||||
);
|
||||
});
|
||||
|
||||
test("today - no time with different zones", assert => {
|
||||
const html = generateHTML();
|
||||
let transformed = $(html).applyLocalDates();
|
||||
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
"Today",
|
||||
"it displays today without time"
|
||||
);
|
||||
|
||||
freezeDateAndZone(rewind(12, "hours"), "Pacific/Auckland", () => {
|
||||
transformed = $(html).applyLocalDates();
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
`June 20, 2018 (${DEFAULT_ZONE_FORMATED})`,
|
||||
"it displays the date without calendar and creator timezone"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("calendar off", assert => {
|
||||
const html = generateHTML({ calendar: "off", time: "16:00" });
|
||||
const transformed = $(html).applyLocalDates();
|
||||
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
"June 20, 2018 4:00 PM",
|
||||
"it displays the date without Today"
|
||||
);
|
||||
});
|
||||
|
||||
test("recurring", assert => {
|
||||
const html = generateHTML({ recurring: "1.week", time: "16:00" });
|
||||
let transformed = $(html).applyLocalDates();
|
||||
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
"Today 4:00 PM",
|
||||
"it displays the next occurrence"
|
||||
);
|
||||
|
||||
freezeDateAndZone(advance(1), null, () => {
|
||||
transformed = $(html).applyLocalDates();
|
||||
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
"June 27, 2018 4:00 PM",
|
||||
"it displays the next occurrence"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("format", assert => {
|
||||
const html = generateHTML({
|
||||
date: advance(3),
|
||||
format: "YYYY | MM - DD"
|
||||
});
|
||||
const transformed = $(html).applyLocalDates();
|
||||
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
"2018 | 06 - 23",
|
||||
"it uses the given format"
|
||||
);
|
||||
});
|
||||
|
||||
test("displayedTimezone", assert => {
|
||||
let html = generateHTML({
|
||||
date: advance(3),
|
||||
displayedTimezone: "America/Chicago",
|
||||
time: "16:00"
|
||||
});
|
||||
let transformed = $(html).applyLocalDates();
|
||||
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
"June 23, 2018 9:00 AM (Chicago)",
|
||||
"it displays timezone when different from watching user"
|
||||
);
|
||||
|
||||
html = generateHTML({
|
||||
date: advance(3),
|
||||
displayedTimezone: DEFAULT_ZONE,
|
||||
time: "16:00"
|
||||
});
|
||||
|
||||
transformed = $(html).applyLocalDates();
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
"June 23, 2018 4:00 PM",
|
||||
"it doesn’t display timezone when same from watching user"
|
||||
);
|
||||
|
||||
html = generateHTML({ displayedTimezone: "Etc/UTC" });
|
||||
transformed = $(html).applyLocalDates();
|
||||
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
"June 19, 2018 (UTC)",
|
||||
"it displays timezone and drops calendar mode when timezone is different from watching user"
|
||||
);
|
||||
|
||||
html = generateHTML({ displayedTimezone: DEFAULT_ZONE });
|
||||
transformed = $(html).applyLocalDates();
|
||||
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
"Today",
|
||||
"it doesn’t display timezone and doesn’t drop calendar mode when timezone is same from watching user"
|
||||
);
|
||||
|
||||
html = generateHTML({
|
||||
timezone: "America/Chicago"
|
||||
});
|
||||
transformed = $(html).applyLocalDates();
|
||||
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
"June 20, 2018 (Chicago)",
|
||||
"it uses timezone when displayedTimezone is not set"
|
||||
);
|
||||
|
||||
html = generateHTML();
|
||||
transformed = $(html).applyLocalDates();
|
||||
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
"Today",
|
||||
"it uses user’s timezone when displayedTimezone and timezone are not set"
|
||||
);
|
||||
|
||||
html = generateHTML({
|
||||
timezone: "America/Chicago",
|
||||
displayedTimezone: "Pacific/Auckland"
|
||||
});
|
||||
transformed = $(html).applyLocalDates();
|
||||
|
||||
assert.equal(
|
||||
transformed.text().trim(),
|
||||
"June 20, 2018 (Auckland)",
|
||||
"it uses displayedTimezone over timezone"
|
||||
);
|
||||
});
|
||||
|
||||
test("tooltip", assert => {
|
||||
let html = generateHTML({ timezone: "America/Chicago" });
|
||||
let transformed = $(html).applyLocalDates();
|
||||
let htmlToolip = transformed.attr("data-html-tooltip");
|
||||
let currentUserPreview = $(htmlToolip).find(".preview.current");
|
||||
let timezone = currentUserPreview.find(".timezone").text();
|
||||
let dateTime = currentUserPreview.find(".date-time").text();
|
||||
|
||||
assert.equal(
|
||||
timezone,
|
||||
DEFAULT_ZONE_FORMATED,
|
||||
"it adds watching user timezone as preview"
|
||||
);
|
||||
assert.equal(
|
||||
dateTime,
|
||||
"June 20, 2018 7:00 AM → June 21, 2018 7:00 AM",
|
||||
"it creates a range adjusted to watching user timezone"
|
||||
);
|
||||
|
||||
freezeDateAndZone(DEFAULT_DATE, "Pacific/Auckland", () => {
|
||||
html = generateHTML({ timezone: "Pacific/Auckland" });
|
||||
transformed = $(html).applyLocalDates();
|
||||
htmlToolip = transformed.attr("data-html-tooltip");
|
||||
currentUserPreview = $(htmlToolip).find(".preview.current");
|
||||
|
||||
assert.ok(
|
||||
exists(currentUserPreview),
|
||||
"it creates an entry if watching user has the same timezone than creator"
|
||||
);
|
||||
});
|
||||
|
||||
html = generateHTML({
|
||||
timezones: "Etc/UTC",
|
||||
timezone: "America/Chicago",
|
||||
time: "14:00:00"
|
||||
});
|
||||
transformed = $(html).applyLocalDates();
|
||||
htmlToolip = transformed.attr("data-html-tooltip");
|
||||
|
||||
assert.ok(
|
||||
exists($(htmlToolip).find(".preview.current")),
|
||||
"doesn’t create current timezone when displayed timezone equals watching user timezone"
|
||||
);
|
||||
|
||||
let $firstPreview = $(htmlToolip).find(".preview:nth-child(2)");
|
||||
dateTime = $firstPreview.find(".date-time").text();
|
||||
timezone = $firstPreview.find(".timezone").text();
|
||||
assert.equal(
|
||||
dateTime,
|
||||
"June 20, 2018 2:00 PM",
|
||||
"it doesn’t create range if time has been set"
|
||||
);
|
||||
assert.equal(timezone, "Chicago", "it adds the timezone of the creator");
|
||||
|
||||
let $secondPreview = $(htmlToolip).find(".preview:nth-child(3)");
|
||||
dateTime = $secondPreview.find(".date-time").text();
|
||||
timezone = $secondPreview.find(".timezone").text();
|
||||
assert.equal(timezone, "UTC", "Etc/UTC is rewritten to UTC");
|
||||
|
||||
freezeDateAndZone(moment("2018-11-26 21:00:00"), "Europe/Vienna", () => {
|
||||
html = generateHTML({
|
||||
date: "2018-11-22",
|
||||
timezone: "America/Chicago",
|
||||
time: "14:00"
|
||||
});
|
||||
transformed = $(html).applyLocalDates();
|
||||
htmlToolip = transformed.attr("data-html-tooltip");
|
||||
|
||||
$firstPreview = $(htmlToolip).find(".preview:nth-child(2)");
|
||||
|
||||
assert.equal(
|
||||
$firstPreview.find(".timezone").text(),
|
||||
"Chicago",
|
||||
"it adds the creator timezone to the previews"
|
||||
);
|
||||
assert.equal(
|
||||
$firstPreview.find(".date-time").text(),
|
||||
"November 22, 2018 2:00 PM",
|
||||
"it adds the creator timezone to the previews"
|
||||
);
|
||||
});
|
||||
|
||||
freezeDateAndZone(DEFAULT_DATE, "Europe/Vienna", () => {
|
||||
html = generateHTML({
|
||||
date: "2018-11-22",
|
||||
timezone: "America/Chicago",
|
||||
timezones: "Europe/Paris"
|
||||
});
|
||||
transformed = $(html).applyLocalDates();
|
||||
htmlToolip = transformed.attr("data-html-tooltip");
|
||||
|
||||
$firstPreview = $(htmlToolip)
|
||||
.find(".preview")
|
||||
.first();
|
||||
|
||||
assert.equal(
|
||||
$firstPreview.find(".timezone").text(),
|
||||
"Vienna",
|
||||
"it rewrites timezone with same offset and different name than watching user"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
test("test utils", assert => {
|
||||
assert.equal(
|
||||
moment().format("LLLL"),
|
||||
moment(DEFAULT_DATE).format("LLLL"),
|
||||
"it has defaults"
|
||||
);
|
||||
|
||||
assert.equal(moment.tz.guess(), DEFAULT_ZONE, "it has defaults");
|
||||
|
||||
freezeDateAndZone(advance(1), DEFAULT_ZONE, () => {
|
||||
assert.equal(
|
||||
moment().format("LLLL"),
|
||||
moment(DEFAULT_DATE)
|
||||
.add(1, "days")
|
||||
.format("LLLL"),
|
||||
"it applies new time"
|
||||
);
|
||||
assert.equal(moment.tz.guess(), DEFAULT_ZONE);
|
||||
});
|
||||
|
||||
assert.equal(
|
||||
moment().format("LLLL"),
|
||||
moment(DEFAULT_DATE).format("LLLL"),
|
||||
"it restores time"
|
||||
);
|
||||
|
||||
freezeDateAndZone(advance(1), "Pacific/Auckland", () => {
|
||||
assert.equal(
|
||||
moment().format("LLLL"),
|
||||
moment(DEFAULT_DATE)
|
||||
.add(1, "days")
|
||||
.format("LLLL")
|
||||
);
|
||||
assert.equal(moment.tz.guess(), "Pacific/Auckland", "it applies new zone");
|
||||
});
|
||||
|
||||
assert.equal(moment.tz.guess(), DEFAULT_ZONE, "it restores zone");
|
||||
});
|
@ -0,0 +1,168 @@
|
||||
import DateWithZoneHelper from "./date-with-zone-helper";
|
||||
|
||||
const PARIS = "Europe/Paris";
|
||||
const SYDNEY = "Australia/Sydney";
|
||||
|
||||
QUnit.module("lib:date-with-zone-helper");
|
||||
|
||||
function buildDateHelper(params = {}) {
|
||||
return new DateWithZoneHelper({
|
||||
year: params.year || 2020,
|
||||
day: params.day || 22,
|
||||
month: params.month || 2,
|
||||
hour: params.hour || 10,
|
||||
minute: params.minute || 5,
|
||||
timezone: params.timezone,
|
||||
localTimezone: PARIS
|
||||
});
|
||||
}
|
||||
|
||||
QUnit.test("#format", assert => {
|
||||
let date = buildDateHelper({
|
||||
day: 15,
|
||||
month: 2,
|
||||
hour: 15,
|
||||
minute: 36,
|
||||
timezone: PARIS
|
||||
});
|
||||
assert.equal(date.format(), "2020-03-15T15:36:00.000+01:00");
|
||||
});
|
||||
|
||||
QUnit.test("#repetitionsBetweenDates", assert => {
|
||||
let date;
|
||||
|
||||
date = buildDateHelper({
|
||||
day: 15,
|
||||
month: 1,
|
||||
hour: 15,
|
||||
minute: 36,
|
||||
timezone: PARIS
|
||||
});
|
||||
assert.equal(
|
||||
date.repetitionsBetweenDates(
|
||||
"1.hour",
|
||||
moment.tz("2020-02-15 15:36", SYDNEY)
|
||||
),
|
||||
10,
|
||||
"it correctly finds difference between timezones"
|
||||
);
|
||||
|
||||
date = buildDateHelper({
|
||||
day: 15,
|
||||
month: 1,
|
||||
hour: 15,
|
||||
minute: 36,
|
||||
timezone: PARIS
|
||||
});
|
||||
assert.equal(
|
||||
date.repetitionsBetweenDates(
|
||||
"1.minute",
|
||||
moment.tz("2020-02-15 15:36", PARIS)
|
||||
),
|
||||
0,
|
||||
"it correctly finds no difference"
|
||||
);
|
||||
|
||||
date = buildDateHelper({
|
||||
day: 15,
|
||||
month: 1,
|
||||
hour: 15,
|
||||
minute: 36,
|
||||
timezone: PARIS
|
||||
});
|
||||
assert.equal(
|
||||
date.repetitionsBetweenDates(
|
||||
"1.minute",
|
||||
moment.tz("2020-02-15 15:37", PARIS)
|
||||
),
|
||||
1,
|
||||
"it correctly finds no difference"
|
||||
);
|
||||
|
||||
date = buildDateHelper({
|
||||
day: 15,
|
||||
month: 1,
|
||||
hour: 15,
|
||||
minute: 36,
|
||||
timezone: PARIS
|
||||
});
|
||||
assert.equal(
|
||||
date.repetitionsBetweenDates(
|
||||
"2.minute",
|
||||
moment.tz("2020-02-15 15:41", PARIS)
|
||||
),
|
||||
2.5,
|
||||
"it correctly finds difference with a multiplicator"
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("#add", assert => {
|
||||
let date;
|
||||
let futureLocalDate;
|
||||
|
||||
date = buildDateHelper({
|
||||
day: 19,
|
||||
month: 2,
|
||||
hour: 15,
|
||||
minute: 36,
|
||||
timezone: PARIS
|
||||
});
|
||||
|
||||
assert.notOk(date.isDST());
|
||||
futureLocalDate = date.add(8, "months");
|
||||
assert.notOk(futureLocalDate.isDST());
|
||||
assert.equal(
|
||||
futureLocalDate.format(),
|
||||
"2020-11-19T15:36:00.000+01:00",
|
||||
"it correctly adds from a !isDST date to a !isDST date"
|
||||
);
|
||||
|
||||
date = buildDateHelper({
|
||||
day: 25,
|
||||
month: 3,
|
||||
hour: 15,
|
||||
minute: 36,
|
||||
timezone: PARIS
|
||||
});
|
||||
assert.ok(date.isDST());
|
||||
futureLocalDate = date.add(1, "year");
|
||||
assert.ok(futureLocalDate.isDST());
|
||||
assert.equal(
|
||||
futureLocalDate.format(),
|
||||
"2021-04-25T15:36:00.000+02:00",
|
||||
"it correctly adds from a isDST date to a isDST date"
|
||||
);
|
||||
|
||||
date = buildDateHelper({
|
||||
day: 25,
|
||||
month: 2,
|
||||
hour: 15,
|
||||
minute: 36,
|
||||
timezone: PARIS
|
||||
});
|
||||
assert.notOk(date.isDST());
|
||||
futureLocalDate = date.add(1, "week");
|
||||
assert.ok(futureLocalDate.isDST());
|
||||
assert.equal(
|
||||
futureLocalDate.format(),
|
||||
"2020-04-01T15:36:00.000+02:00",
|
||||
"it correctly adds from a !isDST date to a isDST date"
|
||||
);
|
||||
|
||||
date = buildDateHelper({
|
||||
day: 1,
|
||||
month: 3,
|
||||
hour: 15,
|
||||
minute: 36,
|
||||
timezone: PARIS
|
||||
});
|
||||
|
||||
assert.ok(date.isDST());
|
||||
futureLocalDate = date.add(8, "months");
|
||||
assert.notOk(futureLocalDate.isDST());
|
||||
assert.equal(
|
||||
futureLocalDate.format(),
|
||||
"2020-12-01T15:36:00.000+01:00",
|
||||
"it correctly adds from a isDST date to a !isDST date"
|
||||
);
|
||||
});
|
@ -0,0 +1,420 @@
|
||||
import LocalDateBuilder from "./local-date-builder";
|
||||
|
||||
const UTC = "Etc/UTC";
|
||||
const SYDNEY = "Australia/Sydney";
|
||||
const LOS_ANGELES = "America/Los_Angeles";
|
||||
const PARIS = "Europe/Paris";
|
||||
const LAGOS = "Africa/Lagos";
|
||||
const LONDON = "Europe/London";
|
||||
|
||||
QUnit.module("lib:local-date-builder");
|
||||
|
||||
const sandbox = sinon.createSandbox();
|
||||
|
||||
function freezeTime({ date, timezone }, cb) {
|
||||
date = date || "2020-01-22 10:34";
|
||||
const newTimezone = timezone || PARIS;
|
||||
const previousZone = moment.tz.guess();
|
||||
const now = moment.tz(date, newTimezone).valueOf();
|
||||
|
||||
sandbox.useFakeTimers(now);
|
||||
sandbox.stub(moment.tz, "guess");
|
||||
moment.tz.guess.returns(newTimezone);
|
||||
moment.tz.setDefault(newTimezone);
|
||||
|
||||
cb();
|
||||
|
||||
moment.tz.guess.returns(previousZone);
|
||||
moment.tz.setDefault(previousZone);
|
||||
sandbox.restore();
|
||||
}
|
||||
|
||||
QUnit.assert.buildsCorrectDate = function(options, expected, message) {
|
||||
const localTimezone = options.localTimezone || PARIS;
|
||||
delete options.localTimezone;
|
||||
|
||||
const localDateBuilder = new LocalDateBuilder(
|
||||
Object.assign(
|
||||
{},
|
||||
{
|
||||
date: "2020-03-22"
|
||||
},
|
||||
options
|
||||
),
|
||||
localTimezone
|
||||
);
|
||||
|
||||
if (expected.formated) {
|
||||
this.test.assert.equal(
|
||||
localDateBuilder.build().formated,
|
||||
expected.formated,
|
||||
message || "it formates the date correctly"
|
||||
);
|
||||
}
|
||||
|
||||
if (expected.previews) {
|
||||
this.test.assert.deepEqual(
|
||||
localDateBuilder.build().previews,
|
||||
expected.previews,
|
||||
message || "it formates the previews correctly"
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
QUnit.test("date", assert => {
|
||||
freezeTime({ date: "2020-03-11" }, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{ date: "2020-03-22", timezone: PARIS },
|
||||
{ formated: "March 22, 2020" },
|
||||
"it displays the date without time"
|
||||
);
|
||||
|
||||
assert.buildsCorrectDate(
|
||||
{ date: "2020-04-11", time: "11:00" },
|
||||
{ formated: "April 11, 2020 1:00 PM" },
|
||||
"it displays the date with time"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test("option[format]", assert => {
|
||||
freezeTime({ date: "2020-03-11" }, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{ format: "YYYY" },
|
||||
{ formated: "2020" },
|
||||
"it uses custom format"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test("option[displayedTimezone]", assert => {
|
||||
freezeTime({}, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{ displayedTimezone: SYDNEY },
|
||||
{ formated: "March 22, 2020 (Sydney)" },
|
||||
"it displays the timezone if the timezone is different from the date"
|
||||
);
|
||||
});
|
||||
|
||||
freezeTime({}, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{ displayedTimezone: PARIS, timezone: PARIS },
|
||||
{ formated: "March 22, 2020" },
|
||||
"it doesn't display the timezone if the timezone is the same than the date"
|
||||
);
|
||||
});
|
||||
|
||||
freezeTime({}, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{ timezone: UTC, displayedTimezone: UTC },
|
||||
{ formated: "March 22, 2020 (UTC)" },
|
||||
"it replaces `Etc/`"
|
||||
);
|
||||
});
|
||||
|
||||
freezeTime({}, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{ timezone: LOS_ANGELES, displayedTimezone: LOS_ANGELES },
|
||||
{ formated: "March 22, 2020 (Los Angeles)" },
|
||||
"it removes prefix and replaces `_`"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test("option[timezone]", assert => {
|
||||
freezeTime({}, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{ timezone: SYDNEY, displayedTimezone: PARIS },
|
||||
{ formated: "March 21, 2020" },
|
||||
"it correctly parses a date with the given timezone context"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test("option[recurring]", assert => {
|
||||
freezeTime({ date: "2020-04-06 06:00", timezone: LAGOS }, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{
|
||||
date: "2019-11-25",
|
||||
time: "11:00",
|
||||
timezone: PARIS,
|
||||
displayedTimezone: LAGOS,
|
||||
recurring: "1.weeks"
|
||||
},
|
||||
{
|
||||
formated: "April 6, 2020 10:00 AM (Lagos)"
|
||||
},
|
||||
"it correctly formats a recurring date starting from a !isDST timezone to a isDST timezone date when displayed to a user using a timezone with no DST"
|
||||
);
|
||||
});
|
||||
|
||||
freezeTime({ date: "2020-04-06 01:00", timezone: SYDNEY }, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{
|
||||
date: "2020-03-09",
|
||||
time: "02:00",
|
||||
timezone: UTC,
|
||||
recurring: "1.weeks",
|
||||
calendar: false,
|
||||
displayedTimezone: SYDNEY
|
||||
},
|
||||
{
|
||||
formated: "April 6, 2020 12:00 PM (Sydney)"
|
||||
},
|
||||
"it correctly formats a recurring date spanning over weeks"
|
||||
);
|
||||
});
|
||||
|
||||
freezeTime({ date: "2020-04-07 22:00" }, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{
|
||||
date: "2019-11-25",
|
||||
time: "11:00",
|
||||
recurring: "1.weeks",
|
||||
timezone: PARIS
|
||||
},
|
||||
{
|
||||
formated: "April 13, 2020 11:00 AM"
|
||||
},
|
||||
"it correctly adds from a !isDST date to a isDST date"
|
||||
);
|
||||
});
|
||||
|
||||
freezeTime({ date: "2020-04-06 10:59" }, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{
|
||||
date: "2020-03-30",
|
||||
time: "11:00",
|
||||
recurring: "1.weeks",
|
||||
timezone: PARIS
|
||||
},
|
||||
{
|
||||
formated: "Today 11:00 AM"
|
||||
},
|
||||
"it works to the minute"
|
||||
);
|
||||
});
|
||||
|
||||
freezeTime({ date: "2020-04-06 11:01" }, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{
|
||||
date: "2020-03-30",
|
||||
time: "11:00",
|
||||
recurring: "1.weeks",
|
||||
timezone: PARIS
|
||||
},
|
||||
{
|
||||
formated: "April 13, 2020 11:00 AM"
|
||||
},
|
||||
"it works to the minute"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test("option[countown]", assert => {
|
||||
freezeTime({ date: "2020-03-21 23:59" }, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{
|
||||
countdown: true,
|
||||
timezone: PARIS
|
||||
},
|
||||
{ formated: "a minute" },
|
||||
"it shows the time remaining"
|
||||
);
|
||||
});
|
||||
|
||||
freezeTime({ date: "2020-03-22 00:01" }, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{
|
||||
countdown: true,
|
||||
timezone: PARIS
|
||||
},
|
||||
{
|
||||
formated: I18n.t(
|
||||
"discourse_local_dates.relative_dates.countdown.passed"
|
||||
)
|
||||
},
|
||||
"it shows the date has passed"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
QUnit.test("option[calendar]", assert => {
|
||||
freezeTime({ date: "2020-03-23 23:00" }, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{ date: "2020-03-22", time: "23:59", timezone: PARIS },
|
||||
{ formated: "Yesterday 11:59 PM" },
|
||||
"it drops calendar mode when event date is more than one day before current date"
|
||||
);
|
||||
});
|
||||
|
||||
freezeTime({ date: "2020-03-20 23:59" }, () =>
|
||||
assert.buildsCorrectDate(
|
||||
{ date: "2020-03-21", time: "00:00", timezone: PARIS },
|
||||
{ formated: "Tomorrow 12:00 AM" }
|
||||
)
|
||||
);
|
||||
|
||||
freezeTime({ date: "2020-03-20 23:59" }, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{ date: "2020-03-21", time: "23:59", timezone: PARIS },
|
||||
{ formated: "Tomorrow 11:59 PM" }
|
||||
);
|
||||
});
|
||||
|
||||
freezeTime({ date: "2020-03-21 00:00" }, () =>
|
||||
assert.buildsCorrectDate(
|
||||
{ date: "2020-03-21", time: "23:00", timezone: PARIS },
|
||||
{ formated: "Today 11:00 PM" }
|
||||
)
|
||||
);
|
||||
|
||||
freezeTime({ date: "2020-03-22 23:59" }, () =>
|
||||
assert.buildsCorrectDate(
|
||||
{ date: "2020-03-21", time: "23:59", timezone: PARIS },
|
||||
{ formated: "Yesterday 11:59 PM" }
|
||||
)
|
||||
);
|
||||
|
||||
freezeTime({ date: "2020-03-22 23:59" }, () =>
|
||||
assert.buildsCorrectDate(
|
||||
{ date: "2020-03-21", time: "23:59", timezone: PARIS },
|
||||
{ formated: "Yesterday 11:59 PM" }
|
||||
)
|
||||
);
|
||||
|
||||
freezeTime({ date: "2020-03-22 23:59" }, () =>
|
||||
assert.buildsCorrectDate(
|
||||
{ calendar: false, date: "2020-03-21", time: "23:59", timezone: PARIS },
|
||||
{ formated: "March 21, 2020 11:59 PM" },
|
||||
"it doesn't use calendar when disabled"
|
||||
)
|
||||
);
|
||||
|
||||
freezeTime({ date: "2020-03-24 01:00" }, () =>
|
||||
assert.buildsCorrectDate(
|
||||
{ date: "2020-03-21", timezone: PARIS },
|
||||
{ formated: "March 21, 2020" },
|
||||
"it stops formating out of calendar range"
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
QUnit.test("previews", assert => {
|
||||
freezeTime({ date: "2020-03-22" }, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{ timezone: PARIS },
|
||||
{
|
||||
previews: [
|
||||
{
|
||||
current: true,
|
||||
formated: "March 22, 2020 → March 23, 2020",
|
||||
timezone: "Europe/Paris"
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
freezeTime({ date: "2020-03-22", timezone: PARIS }, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{ timezone: PARIS, timezones: [SYDNEY] },
|
||||
{
|
||||
previews: [
|
||||
{
|
||||
current: true,
|
||||
formated: "March 22, 2020 → March 23, 2020",
|
||||
timezone: "Europe/Paris"
|
||||
},
|
||||
{
|
||||
formated: "March 23, 2020 → March 23, 2020",
|
||||
timezone: "Australia/Sydney"
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
freezeTime({ date: "2020-03-22", timezone: PARIS }, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{ timezone: PARIS, displayedTimezone: LOS_ANGELES },
|
||||
{
|
||||
previews: [
|
||||
{
|
||||
current: true,
|
||||
formated: "March 22, 2020 → March 23, 2020",
|
||||
timezone: "Europe/Paris"
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
freezeTime({ date: "2020-03-22", timezone: PARIS }, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{ timezone: PARIS, isplayedTimezone: PARIS },
|
||||
{
|
||||
previews: [
|
||||
{
|
||||
current: true,
|
||||
formated: "March 22, 2020 → March 23, 2020",
|
||||
timezone: "Europe/Paris"
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
freezeTime({ date: "2020-03-22", timezone: PARIS }, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{ timezone: PARIS, timezones: [PARIS] },
|
||||
{
|
||||
previews: [
|
||||
{
|
||||
current: true,
|
||||
formated: "March 22, 2020 → March 23, 2020",
|
||||
timezone: "Europe/Paris"
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
freezeTime({ date: "2020-03-22", timezone: PARIS }, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{ time: "11:34", timezone: PARIS, timezones: [PARIS] },
|
||||
{
|
||||
previews: [
|
||||
{
|
||||
current: true,
|
||||
formated: "March 22, 2020 11:34 AM",
|
||||
timezone: "Europe/Paris"
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
freezeTime({ date: "2020-04-06", timezone: PARIS }, () => {
|
||||
assert.buildsCorrectDate(
|
||||
{ timezone: PARIS, date: "2020-04-07", timezones: [LONDON, LAGOS] },
|
||||
{
|
||||
previews: [
|
||||
{
|
||||
current: true,
|
||||
formated: "April 7, 2020 → April 8, 2020",
|
||||
timezone: "Europe/Paris"
|
||||
},
|
||||
{
|
||||
formated: "April 7, 2020 → April 7, 2020",
|
||||
timezone: "Europe/London"
|
||||
},
|
||||
{
|
||||
formated: "April 7, 2020 → April 7, 2020",
|
||||
timezone: "Africa/Lagos"
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user