FEATURE: refactoring and better handling of special cases (#6666)

This commit is contained in:
Joffrey JAFFEUX 2018-11-26 14:20:32 +01:00 committed by GitHub
parent 3453707784
commit b0d08b5a8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 605 additions and 295 deletions

View File

@ -1,141 +0,0 @@
(function($) {
$.fn.applyLocalDates = function(repeat) {
function _formatTimezone(timezone) {
return timezone.replace("_", " ").split("/");
}
function processElement($element, options) {
repeat = repeat || true;
if (this.timeout) {
clearTimeout(this.timeout);
}
var relativeTime;
var dateAndTime = options.date;
if (options.time) {
dateAndTime = dateAndTime + " " + options.time;
}
if (options.timezone) {
relativeTime = moment.tz(dateAndTime, options.timezone).utc();
} else {
relativeTime = moment.utc(dateAndTime);
}
if (relativeTime < moment().utc()) {
if (options.recurring) {
var parts = options.recurring.split(".");
var count = parseInt(parts[0], 10);
var type = parts[1];
var diff = moment().diff(relativeTime, type);
var add = Math.ceil(diff + count);
relativeTime = relativeTime.add(add, type);
} else {
$element.addClass("past");
}
}
var previews = options.timezones.split("|").map(function(timezone) {
var dateTime = relativeTime.tz(timezone).format(options.format);
var timezoneParts = _formatTimezone(timezone);
if (dateTime.match(/TZ/)) {
return dateTime.replace("TZ", timezoneParts.join(": "));
} else {
var output = timezoneParts[0];
if (timezoneParts[1]) {
output += " (" + timezoneParts[1] + ")";
}
output += " " + dateTime;
return output;
}
});
var relativeTime = relativeTime.tz(options.displayedZone);
var d = function(key) {
var translated = I18n.t("discourse_local_dates.relative_dates." + key, {
time: "LT"
});
if (options.time) {
return translated
.split("LT")
.map(function(w) {
return "[" + w + "]";
})
.join("LT");
} else {
return "[" + translated.replace(" LT", "") + "]";
}
};
var relativeFormat = {
sameDay: d("today"),
nextDay: d("tomorrow"),
lastDay: d("yesterday"),
sameElse: "L"
};
if (
options.calendar &&
relativeTime.isBetween(
moment().subtract(1, "day"),
moment().add(2, "day")
)
) {
relativeTime = relativeTime.calendar(null, relativeFormat);
} else {
relativeTime = relativeTime.format(options.format);
}
var html = "<span>";
html += "<i class='fa fa-globe d-icon d-icon-globe'></i>";
html += "<span class='relative-time'></span>";
html += "</span>";
var joinedPreviews = previews.join("\n");
var displayedTime = relativeTime.replace(
"TZ",
_formatTimezone(options.displayedZone).join(": ")
);
$element
.html(html)
.attr("title", joinedPreviews)
.attr("data-tooltip", joinedPreviews)
.addClass("cooked-date")
.find(".relative-time")
.text(displayedTime);
if (repeat) {
this.timeout = setTimeout(function() {
processElement($element, options);
}, 10000);
}
}
return this.each(function() {
var $this = $(this);
var options = {};
options.time = $this.attr("data-time");
options.format =
$this.attr("data-format") || (options.time ? "LLL" : "LL");
options.date = $this.attr("data-date");
options.recurring = $this.attr("data-recurring");
options.timezones = $this.attr("data-timezones") || "Etc/UTC";
options.timezone = $this.attr("data-timezone");
options.calendar = ($this.attr("data-calendar") || "on") === "on";
options.displayedZone =
$this.attr("data-displayed-zone") || moment.tz.guess();
processElement($this, options);
});
};
})(jQuery);

View File

@ -0,0 +1,283 @@
(function($) {
$.fn.applyLocalDates = function(repeat) {
const processElement = ($element, options = {}) => {
if (this.timeout) clearTimeout(this.timeout);
repeat = repeat || true;
const utc = moment().utc();
const dateTime = options.time
? `${options.date} ${options.time}`
: options.date;
let utcDateTime;
let displayedTimezone;
if (options.time) {
displayedTimezone = options.displayedTimezone || moment.tz.guess();
} else {
displayedTimezone =
options.displayedTimezone || options.timezone || moment.tz.guess();
}
// if timezone given we convert date and time from given zone to Etc/UTC
if (options.timezone) {
utcDateTime = _applyZoneToDateTime(dateTime, options.timezone);
} else {
utcDateTime = moment.utc(dateTime);
}
if (utcDateTime < utc) {
// if event is in the past we want to bump it no next occurrence when
// recurring is set
if (options.recurring) {
utcDateTime = _applyRecurrence(utcDateTime, options.recurring);
} else {
$element.addClass("past");
}
}
// once we have the correct UTC date we want
// we adjust it to watching user timezone
const adjustedDateTime = utcDateTime.tz(displayedTimezone);
const previews = _generatePreviews(
adjustedDateTime.clone(),
displayedTimezone,
options
);
const textPreview = _generateTextPreview(previews);
const htmlPreview = _generateHtmlPreview(previews);
const formatedDateTime = _applyFormatting(
adjustedDateTime,
displayedTimezone,
options
);
const $dateTemplate = `
<span>
<i class="fa fa-globe d-icon d-icon-globe"></i>
<span class="relative-time"></span>
</span>
`;
$element
.html($dateTemplate)
.attr("title", textPreview)
.attr("data-html-tooltip", `<div class="previews">${htmlPreview}</div>`)
.addClass("cooked-date")
.find(".relative-time")
.text(formatedDateTime);
if (repeat) {
this.timeout = setTimeout(
() => processElement($element, options),
10000
);
}
};
const _formatTimezone = timezone =>
timezone
.replace("_", " ")
.replace("Etc/", "")
.split("/");
const _applyZoneToDateTime = (dateTime, timezone) => {
return moment.tz(dateTime, timezone).utc();
};
const _calendarFormats = time => {
const _translate = key => {
const translated = I18n.t(
`discourse_local_dates.relative_dates.${key}`,
{
time: "LT"
}
);
if (time) {
return translated
.split("LT")
.map(w => `[${w}]`)
.join("LT");
} else {
return `[${translated.replace(" LT", "")}]`;
}
};
return {
sameDay: _translate("today"),
nextDay: _translate("tomorrow"),
lastDay: _translate("yesterday"),
sameElse: "L"
};
};
const _applyFormatting = (dateTime, displayedTimezone, options) => {
const sameTimezone = displayedTimezone === moment.tz.guess();
const inCalendarRange = dateTime.isBetween(
moment().subtract(2, "days"),
moment().add(2, "days")
);
if (options.calendar && inCalendarRange) {
if (sameTimezone) {
if (options.time) {
dateTime = dateTime.calendar(null, _calendarFormats(options.time));
} else {
dateTime = dateTime.calendar(null, _calendarFormats(null));
}
} else {
dateTime = dateTime.format(options.format);
dateTime = dateTime.replace("TZ", "");
dateTime = `${dateTime} (${_formatTimezone(displayedTimezone).join(
": "
)})`;
}
} else {
if (options.time) {
dateTime = dateTime.format(options.format);
if (options.displayedTimezone && !sameTimezone) {
dateTime = dateTime.replace("TZ", "");
dateTime = `${dateTime} (${_formatTimezone(displayedTimezone).join(
": "
)})`;
} else {
dateTime = dateTime.replace(
"TZ",
_formatTimezone(displayedTimezone).join(": ")
);
}
} else {
dateTime = dateTime.format(options.format);
if (!sameTimezone) {
dateTime = dateTime.replace("TZ", "");
dateTime = `${dateTime} (${_formatTimezone(displayedTimezone).join(
": "
)})`;
} else {
dateTime = dateTime.replace(
"TZ",
_formatTimezone(displayedTimezone).join(": ")
);
}
}
}
return dateTime;
};
const _applyRecurrence = (dateTime, recurring) => {
const parts = recurring.split(".");
const count = parseInt(parts[0], 10);
const type = parts[1];
const diff = moment().diff(dateTime, type);
const add = Math.ceil(diff + count);
return dateTime.add(add, type);
};
const createDateTimeRange = (dateTime, timezone) => {
const startRange = dateTime.tz(timezone).format("LLL");
const separator = "→";
const endRange = dateTime
.add(24, "hours")
.tz(timezone)
.format("LLL");
return `${startRange} ${separator} ${endRange}`;
};
const _generatePreviews = (dateTime, displayedTimezone, options) => {
const previewedTimezones = [];
const watchingUserTimezone = moment.tz.guess();
if (displayedTimezone !== watchingUserTimezone) {
previewedTimezones.push({
timezone: watchingUserTimezone,
current: true,
dateTime: options.time
? dateTime.tz(watchingUserTimezone).format("LLL")
: createDateTimeRange(dateTime, watchingUserTimezone)
});
}
options.timezones
.filter(x => x !== watchingUserTimezone)
.forEach(timezone => {
previewedTimezones.push({
timezone,
dateTime: options.time
? dateTime.tz(timezone).format("LLL")
: createDateTimeRange(dateTime, timezone)
});
});
return previewedTimezones;
};
const _generateTextPreview = previews => {
return previews
.map(preview => {
const timezoneParts = _formatTimezone(preview.timezone);
if (preview.dateTime.match(/TZ/)) {
return preview.dateTime.replace(/TZ/, timezoneParts.join(": "));
} else {
let output = timezoneParts[0];
if (timezoneParts[1]) output += ` (${timezoneParts[1]})`;
return (output += ` ${preview.dateTime}`);
}
})
.join(", ");
};
const _generateHtmlPreview = previews => {
const $htmlTooltip = $("<div></div>");
const $previewTemplate = $(`
<div class='preview'>
<span class='timezone'></span>
<span class='date-time'></span>
</div>
`);
previews.forEach(preview => {
const $template = $previewTemplate.clone();
if (preview.current) $template.addClass("current");
$template
.find(".timezone")
.text(_formatTimezone(preview.timezone).join(": "));
$template.find(".date-time").text(preview.dateTime);
$htmlTooltip.append($template);
});
return $htmlTooltip.html();
};
return this.each(function() {
const $element = $(this);
const options = {};
options.time = $element.attr("data-time");
options.date = $element.attr("data-date");
options.recurring = $element.attr("data-recurring");
options.timezones = (
$element.attr("data-timezones") ||
Discourse.SiteSettings.discourse_local_dates_default_timezones ||
"Etc/UTC"
).split("|");
options.timezone = $element.attr("data-timezone");
options.calendar = ($element.attr("data-calendar") || "on") === "on";
options.displayedTimezone = $element.attr("data-displayed-timezone");
options.format =
$element.attr("data-format") || (options.time ? "LLL" : "LL");
processElement($element, options);
});
};
})(jQuery);

View File

@ -14,18 +14,13 @@ export default Ember.Component.extend({
formats: null,
recurring: null,
advancedMode: false,
isValid: true,
init() {
this._super();
this.set("date", moment().format(this.dateFormat));
this.set("format", `LLL`);
this.set(
"timezones",
(this.siteSettings.discourse_local_dates_default_timezones || "")
.split("|")
.filter(f => f)
);
this.set("timezones", []);
this.set(
"formats",
(this.siteSettings.discourse_local_dates_default_formats || "")
@ -34,10 +29,9 @@ export default Ember.Component.extend({
);
},
didInsertElement() {
this._super();
this._setConfig();
@observes("date", "time", "toDate", "toTime")
_resetFormValidity() {
this.set("isValid", true);
},
@computed
@ -74,44 +68,30 @@ export default Ember.Component.extend({
return moment.tz.names();
},
@observes(
"date",
"time",
"toDate",
"toTime",
"recurring",
"format",
"timezones"
)
_setConfig() {
const toTime = this.get("toTime");
getConfig(range) {
const endOfRange = range && range === "end";
const time = endOfRange ? this.get("toTime") : this.get("time");
let date = endOfRange ? this.get("toDate") : this.get("date");
if (toTime && !this.get("toDate")) {
this.set("toDate", moment().format(this.dateFormat));
if (endOfRange && time && !date) {
date = moment().format(this.dateFormat);
}
const date = this.get("date");
const toDate = this.get("toDate");
const time = this.get("time");
const recurring = this.get("recurring");
const format = this.get("format");
const timezones = this.get("timezones");
const timeInferred = time ? false : true;
const toTimeInferred = toTime ? false : true;
const timezone = this.get("currentUserTimezone");
let dateTime;
if (!timeInferred) {
dateTime = moment.tz(`${date} ${time}`, timezone).utc();
dateTime = moment.tz(`${date} ${time}`, timezone);
} else {
dateTime = moment.tz(date, timezone).utc();
if (endOfRange) {
dateTime = moment.tz(date, timezone).endOf("day");
} else {
dateTime = moment.tz(date, timezone);
}
let toDateTime;
if (!toTimeInferred) {
toDateTime = moment.tz(`${toDate} ${toTime}`, timezone);
} else {
toDateTime = moment.tz(toDate, timezone).endOf("day");
}
let config = {
@ -127,82 +107,64 @@ export default Ember.Component.extend({
config.time = dateTime.format(this.timeFormat);
}
if (!toTimeInferred) {
config.toTime = toDateTime.format(this.timeFormat);
if (timeInferred) {
config.displayedTimezone = this.get("currentUserTimezone");
}
if (toDate) {
config.toDate = toDateTime.format(this.dateFormat);
}
if (
timeInferred &&
toTimeInferred &&
this.get("formats").includes(format)
) {
if (timeInferred && this.get("formats").includes(format)) {
config.format = "LL";
}
if (toDate) {
config.toDateTime = toDateTime;
}
if (
!timeInferred &&
!toTimeInferred &&
date === moment().format(this.dateFormat) &&
date === toDate &&
this.get("formats").includes(format)
) {
config.format = "LT";
}
this.set("config", config);
return config;
},
getTextConfig(config) {
_generateDateMarkup(config) {
let text = `[date=${config.date}`;
if (config.recurring) text += `recurring=${config.recurring} `;
if (config.time) {
text += ` time=${config.time} `;
}
if (config.format && config.format.length) {
text += ` format="${config.format}" `;
text += `timezones="${config.timezones.join("|")}"`;
text += `]`;
if (config.toDate) {
text += ` → `;
text += `[date=${config.toDate} `;
if (config.toTime) {
text += `time=${config.toTime} `;
}
text += `format="${config.format}" `;
text += `timezones="${config.timezones.join("|")}"`;
text += `]`;
if (config.timezone) {
text += ` timezone="${config.timezone}"`;
}
if (config.timezones && config.timezones.length) {
text += ` timezones="${config.timezones.join("|")}"`;
}
text += `]`;
return text;
},
@computed("config.dateTime", "config.toDateTime")
validDate(dateTime, toDateTime) {
if (!dateTime) return false;
valid(isRange) {
const fromConfig = this.getConfig(isRange ? "start" : null);
if (toDateTime) {
if (!toDateTime.isValid()) {
if (!fromConfig.dateTime || !fromConfig.dateTime.isValid()) {
this.set("isValid", false);
return false;
}
if (toDateTime.diff(dateTime) < 0) {
if (isRange) {
const toConfig = this.getConfig("end");
if (
!toConfig.dateTime ||
!toConfig.dateTime.isValid() ||
toConfig.dateTime.diff(fromConfig.dateTime) < 0
) {
this.set("isValid", false);
return false;
}
}
return dateTime.isValid();
this.set("isValid", true);
return true;
},
@computed("advancedMode")
@ -218,10 +180,23 @@ export default Ember.Component.extend({
},
save() {
const isRange =
this.get("date") && (this.get("toDate") || this.get("toTime"));
if (this.valid(isRange)) {
this._closeModal();
const textConfig = this.getTextConfig(this.get("config"));
this.get("toolbarEvent").addText(textConfig);
let text = this._generateDateMarkup(
this.getConfig(isRange ? "start" : null)
);
if (isRange) {
text += ` → `;
text += this._generateDateMarkup(this.getConfig("end"));
}
this.get("toolbarEvent").addText(text);
}
},
fillFormat(format) {

View File

@ -53,7 +53,7 @@
<span class="preview">{{currentUserTimezone}}</span>
</div>
{{#unless validDate}}
{{#unless isValid}}
<span class="validation-error">{{i18n "discourse_local_dates.create.form.invalid_date"}}</span>
{{/unless}}
@ -111,7 +111,7 @@
{{/d-modal-body}}
<div class="modal-footer discourse-local-dates-create-modal-footer">
{{#if validDate}}
{{#if isValid}}
{{d-button class="btn btn-default"
action="save"
label="discourse_local_dates.create.form.insert"}}

View File

@ -9,7 +9,7 @@ function addLocalDate(buffer, matches, state) {
timezone: null,
format: null,
timezones: null,
displayedZone: null
displayedTimezone: null
};
let parsed = parseBBCodeTag(
@ -25,13 +25,20 @@ function addLocalDate(buffer, matches, state) {
config.timezone = parsed.attrs.timezone;
config.recurring = parsed.attrs.recurring;
config.timezones = parsed.attrs.timezones;
config.displayedZone = parsed.attrs.displayedZone;
config.displayedTimezone = parsed.attrs.displayedTimezone;
token = new state.Token("span_open", "span", 1);
token.attrs = [
["class", "discourse-local-date"],
["data-date", state.md.utils.escapeHtml(config.date)]
];
token.attrs = [["data-date", state.md.utils.escapeHtml(config.date)]];
if (!config.date.match(/\d{4}-\d{2}-\d{2}/)) {
closeBuffer(buffer, state, moment.invalid().format());
return;
}
if (config.time && !config.time.match(/\d{2}:\d{2}(?::\d{2})?/)) {
closeBuffer(buffer, state, moment.invalid().format());
return;
}
let dateTime = config.date;
if (config.time) {
@ -39,6 +46,13 @@ function addLocalDate(buffer, matches, state) {
dateTime = `${dateTime} ${config.time}`;
}
if (!moment(dateTime).isValid()) {
closeBuffer(buffer, state, moment.invalid().format());
return;
}
token.attrs.push(["class", "discourse-local-date"]);
if (config.format) {
token.attrs.push(["data-format", state.md.utils.escapeHtml(config.format)]);
}
@ -50,21 +64,28 @@ function addLocalDate(buffer, matches, state) {
]);
}
if (config.displayedZone) {
if (
config.displayedTimezone &&
moment.tz.names().includes(config.displayedTimezone)
) {
token.attrs.push([
"data-displayed-zone",
state.md.utils.escapeHtml(config.displayedZone)
"data-displayed-timezone",
state.md.utils.escapeHtml(config.displayedTimezone)
]);
}
if (config.timezones) {
const timezones = config.timezones.split("|").filter(timezone => {
return moment.tz.names().includes(timezone);
});
token.attrs.push([
"data-timezones",
state.md.utils.escapeHtml(config.timezones)
state.md.utils.escapeHtml(timezones.join("|"))
]);
}
if (config.timezone) {
if (config.timezone && moment.tz.names().includes(config.timezone)) {
token.attrs.push([
"data-timezone",
state.md.utils.escapeHtml(config.timezone)
@ -95,8 +116,14 @@ function addLocalDate(buffer, matches, state) {
}
token.attrs.push(["data-email-preview", emailPreview]);
closeBuffer(buffer, state, dateTime.utc().format(config.format));
}
function closeBuffer(buffer, state, text) {
let token;
token = new state.Token("text", "", 0);
token.content = dateTime.utc().format(config.format);
token.content = text;
buffer.push(token);
token = new state.Token("span_close", "span", -1);

View File

@ -18,6 +18,29 @@
}
}
.discourse-local-date + #discourse-tooltip {
.tooltip-content {
max-width: 360px;
padding: 0.5em;
.previews {
.preview {
display: flex;
flex-direction: column;
padding: 5px;
.timezone {
font-weight: 700;
}
&.current {
background: $tertiary-low;
}
}
}
}
}
.discourse-local-dates-create-modal-footer {
display: flex;
align-items: center;

View File

@ -4,7 +4,7 @@
# author: Joffrey Jaffeux
hide_plugin if self.respond_to?(:hide_plugin)
register_asset "javascripts/discourse-local-dates.js"
register_asset "javascripts/discourse-local-dates.js.no-module.es6"
register_asset "stylesheets/common/discourse-local-dates.scss"
register_asset "moment.js", :vendored_core_pretty_text
register_asset "moment-timezone.js", :vendored_core_pretty_text

View File

@ -1,9 +1,10 @@
require 'rails_helper'
def generate_html(text, opts = {})
output = "<p><span class=\"discourse-local-date\""
output = "<p><span"
output += " data-date=\"#{opts[:date]}\"" if opts[:date]
output += " data-time=\"#{opts[:time]}\"" if opts[:time]
output += " class=\"discourse-local-date\""
output += " data-format=\"#{opts[:format]}\"" if opts[:format]
output += " data-email-preview=\"#{opts[:email_preview]}\"" if opts[:email_preview]
output += ">"

View File

@ -17,15 +17,15 @@ test("composer bbcode", async assert => {
await fillIn(
".d-editor-input",
'[date=2017-10-23 time=01:30:00 displayedZone="America/Chicago" format="LLLL" calendar="off" recurring="1.weeks" timezone="Asia/Calcutta" timezones="Europe/Paris|America/Los_Angeles"]'
'[date=2017-10-23 time=01:30:00 displayedTimezone="America/Chicago" format="LLLL" calendar="off" recurring="1.weeks" timezone="Asia/Calcutta" timezones="Europe/Paris|America/Los_Angeles"]'
);
assert.equal(getAttr("date"), "2017-10-23", "it has the correct date");
assert.equal(getAttr("time"), "01:30:00", "it has the correct time");
assert.equal(
getAttr("displayed-zone"),
getAttr("displayed-timezone"),
"America/Chicago",
"it has the correct displayed zone"
"it has the correct displayed timezone"
);
assert.equal(getAttr("format"), "LLLL", "it has the correct format");
assert.equal(

View File

@ -16,6 +16,7 @@ acceptance("Local Dates", {
const DEFAULT_DATE = "2018-06-20";
const DEFAULT_ZONE = "Europe/Paris";
const DEFAULT_ZONE_FORMATED = DEFAULT_ZONE.split("/").join(": ");
function advance(count, unit = "days") {
return moment(DEFAULT_DATE)
@ -54,56 +55,72 @@ function generateHTML(options = {}) {
output += ` data-date="${options.date || DEFAULT_DATE}"`;
if (options.format) output += ` data-format="${options.format}"`;
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.displayedZone)
output += ` data-displayed-zone="${options.displayedZone}"`;
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: "00:00" });
const html = generateHTML({ date: advance(3), time: "02:00" });
const transformed = $(html).applyLocalDates();
assert.equal(
transformed.text(),
transformed.text().trim(),
"June 23, 2018 2:00 AM",
"it uses moment LLL format"
);
});
test("default format - no time specified", assert => {
const html = generateHTML({ date: advance(3) });
const transformed = $(html).applyLocalDates();
let html = generateHTML({ date: advance(3) });
let transformed = $(html).applyLocalDates();
assert.equal(
transformed.text(),
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"
);
});
});
test("today", assert => {
const html = generateHTML({ time: "14:00" });
const html = generateHTML({ time: "16:00" });
const transformed = $(html).applyLocalDates();
assert.equal(transformed.text(), "Today 4:00 PM", "it display Today");
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(), "Today", "it display Today without time");
assert.equal(
transformed.text().trim(),
"Today",
"it display Today without time"
);
});
test("yesterday", assert => {
const html = generateHTML({ date: rewind(1), time: "14:00" });
const html = generateHTML({ date: rewind(1), time: "16:00" });
const transformed = $(html).applyLocalDates();
assert.equal(
transformed.text(),
transformed.text().trim(),
"Yesterday 4:00 PM",
"it displays yesterday"
);
@ -114,17 +131,21 @@ QUnit.skip("yesterday - no time", assert => {
const transformed = $(html).applyLocalDates();
assert.equal(
transformed.text(),
transformed.text().trim(),
"Yesterday",
"it displays yesterday without time"
);
});
test("tomorrow", assert => {
const html = generateHTML({ date: advance(1), time: "14:00" });
const html = generateHTML({ date: advance(1), time: "16:00" });
const transformed = $(html).applyLocalDates();
assert.equal(transformed.text(), "Tomorrow 4:00 PM", "it displays tomorrow");
assert.equal(
transformed.text().trim(),
"Tomorrow 4:00 PM",
"it displays tomorrow"
);
});
test("tomorrow - no time", assert => {
@ -132,7 +153,7 @@ test("tomorrow - no time", assert => {
const transformed = $(html).applyLocalDates();
assert.equal(
transformed.text(),
transformed.text().trim(),
"Tomorrow",
"it displays tomorrow without time"
);
@ -142,35 +163,39 @@ test("today - no time with different zones", assert => {
const html = generateHTML();
let transformed = $(html).applyLocalDates();
assert.equal(transformed.text(), "Today", "it displays today without time");
assert.equal(
transformed.text().trim(),
"Today",
"it displays today without time"
);
freezeDateAndZone(rewind(12, "hours"), "Pacific/Auckland", () => {
transformed = $(html).applyLocalDates();
assert.equal(
transformed.text(),
"Tomorrow",
"it displays Tomorrow without time"
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: "14:00" });
const html = generateHTML({ calendar: "off", time: "16:00" });
const transformed = $(html).applyLocalDates();
assert.equal(
transformed.text(),
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: "14:00" });
const html = generateHTML({ recurring: "1.week", time: "16:00" });
let transformed = $(html).applyLocalDates();
assert.equal(
transformed.text(),
transformed.text().trim(),
"Today 4:00 PM",
"it displays the next occurrence"
);
@ -179,28 +204,13 @@ test("recurring", assert => {
transformed = $(html).applyLocalDates();
assert.equal(
transformed.text(),
transformed.text().trim(),
"June 27, 2018 4:00 PM",
"it displays the next occurrence"
);
});
});
test("displayedZone", assert => {
const html = generateHTML({
date: advance(3),
displayedZone: "Etc/UTC",
time: "14:00"
});
const transformed = $(html).applyLocalDates();
assert.equal(
transformed.text(),
"June 23, 2018 2:00 PM",
"it forces display in the given timezone"
);
});
test("format", assert => {
const html = generateHTML({
date: advance(3),
@ -209,12 +219,144 @@ test("format", assert => {
const transformed = $(html).applyLocalDates();
assert.equal(
transformed.text(),
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 (America: 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 doesnt 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 doesnt display timezone and doesnt 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 (America: Chicago)",
"it uses timezone when displayedTimezone is not set"
);
html = generateHTML();
transformed = $(html).applyLocalDates();
assert.equal(
transformed.text().trim(),
"Today",
"it uses users 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 (Pacific: 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 creates a range adjusted to watching user timezone"
);
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.notOk(
exists(currentUserPreview),
"it doesnt create entry if watching user has the same timezone than creator"
);
});
html = generateHTML({ timezone: "America/Chicago", time: "14:00:00" });
transformed = $(html).applyLocalDates();
htmlToolip = transformed.attr("data-html-tooltip");
const $preview = $(htmlToolip)
.find(".preview")
.first();
dateTime = $preview.find(".date-time").text();
timezone = $preview.find(".timezone").text();
assert.ok(
!exists(".preview.current"),
"doesnt create current timezone when displayed timezone equals watching user timezone"
);
assert.equal(
dateTime,
"June 20, 2018 7:00 PM",
"it doesnt create range if time has been set"
);
assert.equal(timezone, "UTC", "Etc/UTC is rewritten to UTC");
});
test("test utils", assert => {
assert.equal(
moment().format("LLLL"),