TimeFixer Initializer Migration (#19268)

* init

* remove from asset pipeline and add tests

* add utc date conversion test

* try removing last tests

* add some more tests

* add tests for more coverage

* add yet more tests

* separate descibe statments

* add dt test back

* more test cleanup

* include pack js files

* add jest back

* Include /packs/ in code coverage metric

* derp

* revert jest

* reformat some of the test accordingly

* try e2e

* fix cypress test

---------

Co-authored-by: Mac Siri <mac@forem.com>
Co-authored-by: Mac Siri <krairit.siri@gmail.com>
This commit is contained in:
Lawrence 2023-04-27 20:54:39 -05:00 committed by GitHub
parent 6236d8ec69
commit 93a70815b3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 277 additions and 15 deletions

View file

@ -3,7 +3,7 @@
initializeAllTagEditButtons, initializeUserFollowButts,
initializeCommentsPage,
initializeSettings, initializeRuntimeBanner,
initializeTimeFixer, initializeCreditsPage,
initializeCreditsPage,
initializeOnboardingTaskCard,
initScrolling, nextPage:writable,
fetching:writable, done:writable, initializePaymentPointers,
@ -14,7 +14,6 @@ function callInitializers() {
initializePaymentPointers();
initializeCommentsPage();
initializeSettings();
initializeTimeFixer();
initializeCreditsPage();
initializeOnboardingTaskCard();
}

View file

@ -1,5 +1,6 @@
import { initializeCommentDate } from './initializers/initializeCommentDate';
import { initializeCommentPreview } from './initializers/initializeCommentPreview';
import { initializeTimeFixer } from './initializers/initializeTimeFixer';
import { initializeNotifications } from './initializers/initializeNotifications';
import { initializeDateHelpers } from './initializers/initializeDateTimeHelpers';
import {
@ -10,6 +11,7 @@ import {
initializeCommentDate();
initializeCommentPreview();
initializeNotifications();
initializeTimeFixer();
initializeDateHelpers();
InstantClick.on('change', () => {

View file

@ -0,0 +1,209 @@
import {
initializeTimeFixer,
convertUtcDate,
convertUtcTime,
formatDateTime,
updateLocalDateTime,
convertCalEvent,
} from '../initializeTimeFixer';
describe('initializeTimeFixer', () => {
beforeEach(() => {
const utcTimeClassDiv = document.createElement('div');
const utcDateClassDiv = document.createElement('div');
const utcDiv = document.createElement('div');
utcTimeClassDiv.classList.add('utc-time');
utcDateClassDiv.classList.add('utc-date');
utcDiv.classList.add('utc');
utcTimeClassDiv.dataset.datetime = 823230245000;
});
test('should call event listener when preview button exist', async () => {
const button = document.createElement('button');
button.classList.add('preview-toggle');
button.addEventListener = jest.fn();
initializeTimeFixer();
expect(button.addEventListener).not.toHaveBeenCalled();
});
test('should call updateLocalDateTime', async () => {
const updateLocalDateTime = jest.fn();
initializeTimeFixer();
expect(updateLocalDateTime).not.toHaveBeenCalled();
});
test('should call convertUtcDate', async () => {
const convertUtcDate = jest.fn();
initializeTimeFixer();
expect(convertUtcDate).not.toHaveBeenCalled();
});
test('should convert Utc Dates', async () => {
const utcDate = Date.UTC(96, 1, 2, 3, 4, 5);
const dateConversion = await convertUtcDate(utcDate);
// const formatDateTime = jest.fn();
expect(dateConversion).toContain('Feb 2');
});
test('convertUtcDate function with different options', () => {
const utcDate = 917924645000;
const options1 = {
month: 'short',
day: 'numeric',
};
expect(convertUtcDate(utcDate, options1)).toBe('Feb 2');
const options2 = {
year: 'numeric',
month: 'long',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
timeZoneName: 'short',
};
expect(convertUtcDate(utcDate, options2)).toBe('Feb 2');
});
test('convertUtcTime function with different options', () => {
const utcTime = 917924645000;
const options1 = {
hour: 'numeric',
minute: 'numeric',
timeZoneName: 'short',
};
expect(convertUtcTime(utcTime, options1)).toBe('3:04 AM UTC');
const options2 = {
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
timeZoneName: 'short',
};
expect(convertUtcTime(utcTime, options2)).toBe('3:04 AM UTC');
});
test('formatDateTime function with different options and values', () => {
const options1 = {
hour: 'numeric',
minute: 'numeric',
timeZoneName: 'short',
};
const value1 = new Date(917924645000);
expect(formatDateTime(options1, value1)).toBe('3:04 AM UTC');
const options2 = {
year: 'numeric',
month: 'short',
day: 'numeric',
};
const value2 = new Date(917924645000);
expect(formatDateTime(options2, value2)).toBe('Feb 2, 1999');
});
});
describe('formatDateTime', () => {
it('formats the date time with given options', () => {
const options = {
month: 'short',
day: 'numeric',
year: 'numeric',
hour: 'numeric',
minute: 'numeric',
};
const value = new Date('2022-04-13T12:34:56Z');
const expected = 'Apr 13, 2022, 12:34 PM';
expect(formatDateTime(options, value)).toEqual(expected);
});
});
describe('convertUtcTime', () => {
it('converts the UTC time to local time with proper format', () => {
const utcTime = 917924645000;
const expected = '3:04 AM UTC';
expect(convertUtcTime(utcTime)).toEqual(expected);
});
});
describe('convertUtcDate', () => {
it('converts the UTC date to local date with proper format', () => {
const utcDate = 917924645000;
const expected = expect.stringMatching(/^\w{3} \d{1,2}$/);
expect(convertUtcDate(utcDate)).toEqual(expected);
});
});
describe('updateLocalDateTime', () => {
it('updates the innerHTML of given elements with local time', () => {
document.body.innerHTML = `
<div>
<span class="utc-time" data-datetime=917924645000></span>
<span class="utc-date" data-datetime=917924645000></span>
<span class="utc">917924645000</span>
</div>
`;
const utcTimeElements = document.querySelectorAll('.utc-time');
const utcDateElements = document.querySelectorAll('.utc-date');
const utcElements = document.querySelectorAll('.utc');
updateLocalDateTime(
utcTimeElements,
convertUtcTime,
(element) => element.dataset.datetime,
);
updateLocalDateTime(
utcDateElements,
convertUtcDate,
(element) => element.dataset.datetime,
);
updateLocalDateTime(
utcElements,
convertCalEvent,
(element) => element.innerHTML,
);
expect(utcTimeElements[0].innerHTML).toEqual('3:04 AM UTC');
expect(utcDateElements[0].innerHTML).toEqual(
expect.stringMatching(/^\w{3} \d{1,2}$/),
);
expect(utcElements[0].innerHTML).toEqual('Tuesday, February 2 at 3:04 AM');
});
});
// eslint-disable-next-line jest/no-identical-title
describe('formatDateTime', () => {
it('should format a date and time using the specified options', () => {
const options = {
weekday: 'short',
year: 'numeric',
month: 'short',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
hour12: true,
};
const value = new Date(1682636630);
const expected = 'Tue, Jan 20, 1970, 11:23 AM';
expect(formatDateTime(options, value)).toBe(expected);
});
});
describe('convertCalEvent', () => {
it('should convert UTC to a formatted date and time string', () => {
const utc = 1682636630;
const expected = 'Tuesday, January 20 at 11:23 AM';
expect(convertCalEvent(utc)).toBe(expected);
});
});

View file

@ -1,12 +1,10 @@
'use strict';
function formatDateTime(options, value) {
return new Intl.DateTimeFormat('en-US', options).format(value);
}
function convertUtcTime(utcTime) {
var time = new Date(utcTime);
var options = {
const time = new Date(Number(utcTime));
const options = {
hour: 'numeric',
minute: 'numeric',
timeZoneName: 'short',
@ -15,8 +13,8 @@ function convertUtcTime(utcTime) {
}
function convertUtcDate(utcDate) {
var date = new Date(utcDate);
var options = {
const date = new Date(Number(utcDate));
const options = {
month: 'short',
day: 'numeric',
};
@ -24,8 +22,8 @@ function convertUtcDate(utcDate) {
}
function convertCalEvent(utc) {
var date = new Date(utc);
var options = {
const date = new Date(Number(utc));
const options = {
weekday: 'long',
month: 'long',
day: 'numeric',
@ -37,8 +35,8 @@ function convertCalEvent(utc) {
}
function updateLocalDateTime(elements, convertCallback, getUtcDateTime) {
var local;
for (var i = 0; i < elements.length; i += 1) {
let local;
for (let i = 0; i < elements.length; i += 1) {
local = convertCallback(getUtcDateTime(elements[i]));
// eslint-disable-next-line no-param-reassign
elements[i].innerHTML = local;
@ -46,9 +44,9 @@ function updateLocalDateTime(elements, convertCallback, getUtcDateTime) {
}
function initializeTimeFixer() {
var utcTime = document.getElementsByClassName('utc-time');
var utcDate = document.getElementsByClassName('utc-date');
var utc = document.getElementsByClassName('utc');
const utcTime = document.getElementsByClassName('utc-time');
const utcDate = document.getElementsByClassName('utc-date');
const utc = document.getElementsByClassName('utc');
if (!utc) {
return;
@ -66,3 +64,12 @@ function initializeTimeFixer() {
);
updateLocalDateTime(utc, convertCalEvent, (element) => element.innerHTML);
}
export {
initializeTimeFixer,
updateLocalDateTime,
convertUtcDate,
convertUtcTime,
formatDateTime,
convertCalEvent,
};

View file

@ -0,0 +1,45 @@
const timeHtml = `
<div>
<h1>This is a test campaign</h1>
<button id="js-hero-banner__x">Dismiss</button>
<div class="utc-time" data-datetime=823230245000></div>
<div class="utc-date" data-datetime=823230245000></div>
<div class="utc">823230245000</div>
</div>
`;
describe('Time Fixer', () => {
beforeEach(() => {
cy.testSetup();
cy.fixture('users/adminUser.json').as('user');
cy.get('@user').then((user) => {
cy.loginUser(user).then(() => {
cy.createHtmlVariant({
name: 'TestTimeHtml',
html: timeHtml,
approved: true,
}).then(() => {
cy.setCampaign({
display_name: 'Test Time Campaign',
hero_html_variant_name: 'TestTimeHtml',
}).then(() => {
cy.visit('/');
});
});
});
});
});
afterEach(() => {
// Dismissing a banner sets a flag in local storage that we want to ensure is removed after each test
// cy.visit('/404');
cy.clearLocalStorage();
});
context('when utc exist on the page', () => {
it('displays proper time', () => {
cy.get('.utc').as('utcTime').should('exist');
});
});
});