Commit 5957b12d authored by Hannah Stepanek's avatar Hannah Stepanek

Cleanup util time tests

- Use now variable instead of walking the clock.
- Use iso format instead of seconds.
- Pass a Date object instead of an iso format to time.<methods>so
the methods off the Date object can be mocked in order to avoid
timezone specific tests. Since methods like getFullYear output the
year in whatever timezone the operating system is set to, these
methods must be mocked/mapped to their UTC equivalents when testing
such as getUTCFullYear.
- Remove offseting of time based on timezone as this is now covered
by mocking the getFullYear method and not needed for the decayInterval
as that only cares about time deltas.
parent fee4bac3
...@@ -17,10 +17,10 @@ function Timestamp({ className, href, timestamp }) { ...@@ -17,10 +17,10 @@ function Timestamp({ className, href, timestamp }) {
const [now, setNow] = useState(new Date()); const [now, setNow] = useState(new Date());
// Fuzzy, relative timestamp (eg. '6 days ago') // Fuzzy, relative timestamp (eg. '6 days ago')
const relativeTimestamp = useMemo(() => toFuzzyString(timestamp, now), [ const relativeTimestamp = useMemo(
timestamp, () => toFuzzyString(timestamp ? new Date(timestamp) : null, now),
now, [timestamp, now]
]); );
// Absolute timestamp (eg. 'Tue 22nd Dec 2015, 16:00') // Absolute timestamp (eg. 'Tue 22nd Dec 2015, 16:00')
const absoluteTimestamp = useMemo(() => formatDate(new Date(timestamp)), [ const absoluteTimestamp = useMemo(() => formatDate(new Date(timestamp)), [
......
This diff is collapsed.
...@@ -55,8 +55,14 @@ function nHr(date, now) { ...@@ -55,8 +55,14 @@ function nHr(date, now) {
// Cached DateTimeFormat instances, // Cached DateTimeFormat instances,
// because instantiating a DateTimeFormat is expensive. // because instantiating a DateTimeFormat is expensive.
const formatters = {}; let formatters = {};
/**
* Clears the cache of formatters.
*/
function clearFormatters() {
formatters = {};
}
/** /**
* Efficiently return `date` formatted with `options`. * Efficiently return `date` formatted with `options`.
* *
...@@ -139,10 +145,15 @@ const BREAKPOINTS = [ ...@@ -139,10 +145,15 @@ const BREAKPOINTS = [
}, },
]; ];
/**
* Returns a dict that describes how to format the date based on the delta
* between date and now.
*
* @param {Date} date - The date to consider as the timestamp to format.
* @param {Date} now - The date to consider as the current time.
* @return {breakpoint} A dict that describes how to format the date.
*/
function getBreakpoint(date, now) { function getBreakpoint(date, now) {
// Turn the given ISO 8601 string into a Date object.
date = new Date(date);
let breakpoint; let breakpoint;
for (let i = 0; i < BREAKPOINTS.length; i++) { for (let i = 0; i < BREAKPOINTS.length; i++) {
breakpoint = BREAKPOINTS[i]; breakpoint = BREAKPOINTS[i];
...@@ -154,12 +165,12 @@ function getBreakpoint(date, now) { ...@@ -154,12 +165,12 @@ function getBreakpoint(date, now) {
return null; return null;
} }
function nextFuzzyUpdate(date) { function nextFuzzyUpdate(date, now) {
if (!date) { if (!date) {
return null; return null;
} }
let secs = getBreakpoint(date, new Date()).nextUpdate; let secs = getBreakpoint(date, now).nextUpdate;
if (secs === null) { if (secs === null) {
return null; return null;
...@@ -183,12 +194,15 @@ function nextFuzzyUpdate(date) { ...@@ -183,12 +194,15 @@ function nextFuzzyUpdate(date) {
* This can be used to refresh parts of a UI whose * This can be used to refresh parts of a UI whose
* update frequency depends on the age of a timestamp. * update frequency depends on the age of a timestamp.
* *
* @param {String} date - An ISO 8601 date string timestamp to format.
* @param {Date} callback - A callback function to call when the timestamp changes.
* @return {Function} A function that cancels the automatic refresh. * @return {Function} A function that cancels the automatic refresh.
*/ */
function decayingInterval(date, callback) { function decayingInterval(date, callback) {
let timer; let timer;
const timeStamp = date ? new Date(date) : null;
const update = function() { const update = function() {
const fuzzyUpdate = nextFuzzyUpdate(date); const fuzzyUpdate = nextFuzzyUpdate(timeStamp, new Date());
if (fuzzyUpdate === null) { if (fuzzyUpdate === null) {
return; return;
} }
...@@ -208,18 +222,20 @@ function decayingInterval(date, callback) { ...@@ -208,18 +222,20 @@ function decayingInterval(date, callback) {
/** /**
* Formats a date as a string relative to the current date. * Formats a date as a string relative to the current date.
* *
* @param {number} date - The absolute timestamp to format. * @param {Date} date - The date to consider as the timestamp to format.
* @param {Date} [now] - The date to consider as the current time. * @param {Date} now - The date to consider as the current time.
* @param {Object} Intl - JS internationalization API implementation.
* @return {string} A 'fuzzy' string describing the relative age of the date. * @return {string} A 'fuzzy' string describing the relative age of the date.
*/ */
function toFuzzyString(date, now = new Date(), Intl) { function toFuzzyString(date, now, Intl) {
if (!date) { if (!date) {
return ''; return '';
} }
return getBreakpoint(date, now).format(new Date(date), now, Intl); return getBreakpoint(date, now).format(date, now, Intl);
} }
module.exports = { module.exports = {
clearFormatters: clearFormatters,
decayingInterval: decayingInterval, decayingInterval: decayingInterval,
nextFuzzyUpdate: nextFuzzyUpdate, nextFuzzyUpdate: nextFuzzyUpdate,
toFuzzyString: toFuzzyString, toFuzzyString: toFuzzyString,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment