diff --git a/aio/package.json b/aio/package.json index 3c7b97eb00..3938a2a2da 100644 --- a/aio/package.json +++ b/aio/package.json @@ -161,6 +161,7 @@ "rimraf": "^2.6.1", "semver": "^5.3.0", "shelljs": "^0.8.4", + "timezone-mock": "^1.1.3", "tree-kill": "^1.1.0", "ts-node": "^8.4.1", "tslint": "~6.1.0", diff --git a/aio/src/app/custom-elements/events/events.component.spec.ts b/aio/src/app/custom-elements/events/events.component.spec.ts index e84f25053b..a2e436fcef 100644 --- a/aio/src/app/custom-elements/events/events.component.spec.ts +++ b/aio/src/app/custom-elements/events/events.component.spec.ts @@ -1,5 +1,6 @@ import { Injector } from '@angular/core'; import { Subject } from 'rxjs'; +import * as tzMock from 'timezone-mock'; import { Duration, Event, EventsComponent } from './events.component'; import { EventsService } from './events.service'; @@ -132,86 +133,107 @@ describe('EventsComponent', () => { }); describe('getEventDates()', () => { - describe('(without workshops)', () => { - it('should correctly format the main event date', () => { - const testEvent = createMockEvent('Test', {start: '2020-06-20', end: '2020-06-20'}); - expect(component.getEventDates(testEvent)).toBe('June 20, 2020'); - }); + // Test on different timezones to ensure that event dates are processed correctly regardless of + // the user's local time. + const timezones: tzMock.TimeZone[] = [ + 'Australia/Adelaide', // UTC+9.5/10.5 + 'Brazil/East', // UTC-3 + 'UTC', // UTC + ]; - it('should correctly format the main event date spanning mupliple days', () => { - const testEvent = createMockEvent('Test', {start: '2019-09-19', end: '2019-09-21'}); - expect(component.getEventDates(testEvent)).toBe('September 19-21, 2019'); - }); + for (const tz of timezones) { + describe(`on timezone ${tz}`, () => { + // NOTE: `timezone-mock` does not work correctly if used together with Jasmine's mock clock. + beforeEach(() => tzMock.register(tz)); + afterEach(() => tzMock.unregister()); - it('should correctly format the main event date spanning mupliple months', () => { - const testEvent = createMockEvent('Test', {start: '2019-10-30', end: '2019-11-01'}); - expect(component.getEventDates(testEvent)).toBe('October 30 - November 1, 2019'); - }); - }); + describe('(without workshops)', () => { + it('should correctly format the main event date', () => { + const testEvent = createMockEvent('Test', {start: '2020-06-20', end: '2020-06-20'}); + expect(component.getEventDates(testEvent)).toBe('June 20, 2020'); + }); - describe('(with workshops)', () => { - it('should correctly format event dates with workshops after main event', () => { - const testEvent = createMockEvent( - 'Test', - {start: '2020-07-25', end: '2020-07-26'}, - {start: '2020-07-27', end: '2020-07-27'}); + it('should correctly format the main event date spanning mupliple days', () => { + const testEvent = createMockEvent('Test', {start: '2019-09-19', end: '2019-09-21'}); + expect(component.getEventDates(testEvent)).toBe('September 19-21, 2019'); + }); - expect(component.getEventDates(testEvent)) - .toBe('July 25-26 (conference), July 27 (workshops), 2020'); - }); + it('should correctly format the main event date spanning mupliple months', () => { + const testEvent = createMockEvent('Test', {start: '2019-10-30', end: '2019-11-01'}); + expect(component.getEventDates(testEvent)).toBe('October 30 - November 1, 2019'); + }); - it('should correctly format event dates with workshops before main event', () => { - const testEvent = createMockEvent( - 'Test', - {start: '2019-10-07', end: '2019-10-07'}, - {start: '2019-10-06', end: '2019-10-06'}); - - expect(component.getEventDates(testEvent)) - .toBe('October 6 (workshops), October 7 (conference), 2019'); - }); - - it('should correctly format event dates spanning multiple days', () => { - const testEvent = createMockEvent( - 'Test', - {start: '2019-08-30', end: '2019-08-31'}, - {start: '2019-08-28', end: '2019-08-29'}); - - expect(component.getEventDates(testEvent)) - .toBe('August 28-29 (workshops), August 30-31 (conference), 2019'); - }); - - it('should correctly format event dates with workshops on different month before the main event', - () => { - const testEvent = createMockEvent( - 'Test', - {start: '2020-08-01', end: '2020-08-02'}, - {start: '2020-07-30', end: '2020-07-31'}); - - expect(component.getEventDates(testEvent)) - .toBe('July 30-31 (workshops), August 1-2 (conference), 2020'); + it('should correctly format event dates at the beginning/end of the year', () => { + const testEvent = createMockEvent('Test', {start: '2021-01-01', end: '2021-12-31'}); + expect(component.getEventDates(testEvent)).toBe('January 1 - December 31, 2021'); + }); }); - it('should correctly format event dates with workshops on different month after the main event', - () => { - const testEvent = createMockEvent( - 'Test', - {start: '2020-07-30', end: '2020-07-31'}, - {start: '2020-08-01', end: '2020-08-02'}); + describe('(with workshops)', () => { + it('should correctly format event dates with workshops after main event', () => { + const testEvent = createMockEvent( + 'Test', + {start: '2020-07-25', end: '2020-07-26'}, + {start: '2020-07-27', end: '2020-07-27'}); - expect(component.getEventDates(testEvent)) - .toBe('July 30-31 (conference), August 1-2 (workshops), 2020'); + expect(component.getEventDates(testEvent)) + .toBe('July 25-26 (conference), July 27 (workshops), 2020'); + }); + + it('should correctly format event dates with workshops before main event', () => { + const testEvent = createMockEvent( + 'Test', + {start: '2019-10-07', end: '2019-10-07'}, + {start: '2019-10-06', end: '2019-10-06'}); + + expect(component.getEventDates(testEvent)) + .toBe('October 6 (workshops), October 7 (conference), 2019'); + }); + + it('should correctly format event dates spanning multiple days', () => { + const testEvent = createMockEvent( + 'Test', + {start: '2019-08-30', end: '2019-08-31'}, + {start: '2019-08-28', end: '2019-08-29'}); + + expect(component.getEventDates(testEvent)) + .toBe('August 28-29 (workshops), August 30-31 (conference), 2019'); + }); + + it('should correctly format event dates with workshops on different month before the main event', + () => { + const testEvent = createMockEvent( + 'Test', + {start: '2020-08-01', end: '2020-08-02'}, + {start: '2020-07-30', end: '2020-07-31'}); + + expect(component.getEventDates(testEvent)) + .toBe('July 30-31 (workshops), August 1-2 (conference), 2020'); + }); + + it('should correctly format event dates with workshops on different month after the main event', + () => { + const testEvent = createMockEvent( + 'Test', + {start: '2020-07-30', end: '2020-07-31'}, + {start: '2020-08-01', end: '2020-08-02'}); + + expect(component.getEventDates(testEvent)) + .toBe('July 30-31 (conference), August 1-2 (workshops), 2020'); + }); + + it('should correctly format event dates spanning multiple months', () => { + const testEvent = createMockEvent( + 'Test', + {start: '2020-07-31', end: '2020-08-01'}, + {start: '2020-07-30', end: '2020-08-01'}); + + expect(component.getEventDates(testEvent)) + .toBe('July 30 - August 1 (workshops), July 31 - August 1 (conference), 2020'); + }); }); - - it('should correctly format event dates spanning multiple months', () => { - const testEvent = createMockEvent( - 'Test', - {start: '2020-07-31', end: '2020-08-01'}, - {start: '2020-07-30', end: '2020-08-01'}); - - expect(component.getEventDates(testEvent)) - .toBe('July 30 - August 1 (workshops), July 31 - August 1 (conference), 2020'); }); - }); + } }); // Helpers diff --git a/aio/src/app/custom-elements/events/events.component.ts b/aio/src/app/custom-elements/events/events.component.ts index 9c9555054e..f3343ee9e1 100644 --- a/aio/src/app/custom-elements/events/events.component.ts +++ b/aio/src/app/custom-elements/events/events.component.ts @@ -72,7 +72,7 @@ export class EventsComponent implements OnInit { // If no work shop date create conference date string dateString = processDate(event.date); } - dateString = `${dateString}, ${new Date(event.date.end).getFullYear()}`; + dateString = `${dateString}, ${new Date(event.date.end).getUTCFullYear()}`; return dateString; } } @@ -83,14 +83,14 @@ function processDate(dates: Duration) { const endDate = new Date(dates.end); // Create a date string in the start like January 31 - let processedDate = `${MONTHS[startDate.getMonth()]} ${startDate.getDate()}`; + let processedDate = `${MONTHS[startDate.getUTCMonth()]} ${startDate.getUTCDate()}`; // If they are in different months add the string '- February 2' Making the final string January 31 - February 2 - if (startDate.getMonth() !== endDate.getMonth()) { - processedDate = `${processedDate} - ${MONTHS[endDate.getMonth()]} ${endDate.getDate()}`; - } else if (startDate.getDate() !== endDate.getDate()) { + if (startDate.getUTCMonth() !== endDate.getUTCMonth()) { + processedDate = `${processedDate} - ${MONTHS[endDate.getUTCMonth()]} ${endDate.getUTCDate()}`; + } else if (startDate.getUTCDate() !== endDate.getUTCDate()) { // If not add - date eg it will make // January 30-31 - processedDate = `${processedDate}-${endDate.getDate()}`; + processedDate = `${processedDate}-${endDate.getUTCDate()}`; } return processedDate; diff --git a/aio/yarn.lock b/aio/yarn.lock index 6196040838..eab85d307d 100644 --- a/aio/yarn.lock +++ b/aio/yarn.lock @@ -13168,6 +13168,11 @@ timers-ext@^0.1.5: es5-ext "~0.10.46" next-tick "1" +timezone-mock@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/timezone-mock/-/timezone-mock-1.1.3.tgz#f5ca25befec2cdd2d64c07ee7a5293275c06b97e" + integrity sha512-r+fz9M1tflNkF6mJK0DwmlFyNWeSCXxZ68pu2Bv+DddIHK/czOZwnasEql17VfHqP/OcZRuPq/qi6wm7eQmQow== + timsort@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4"