Commit 864b69e0 authored by Wei-Meng Lee's avatar Wei-Meng Lee Committed by Mike Greiling

Test for right start/end dates in east timezone

Make use of timezone-mock to test for US/Pacific time
parent c2f3ac73
......@@ -8,19 +8,29 @@ export default class BurndownChartData {
this.burndownEvents = this.processRawEvents(burndownEvents);
// determine when to stop burndown chart
const today = dateFormat(new Date(), this.dateFormatMask);
const today = dateFormat(Date.now(), this.dateFormatMask);
this.endDate = today < this.dueDate ? today : this.dueDate;
// Make sure we get the burndown chart local start and end dates! new Date()
// and dateFormat() both convert the date at midnight UTC to the browser's
// timezone, leading to incorrect chart start and end points. Using
// new Date('YYYY-MM-DDTHH:MM:SS') gets the user's local date at midnight.
this.localStartDate = new Date(`${this.startDate}T00:00:00`);
this.localEndDate = new Date(`${this.endDate}T00:00:00`);
}
generate() {
let openIssuesCount = 0;
let openIssuesWeight = 0;
let carriedIssuesCount = 0;
let carriedIssuesWeight = 0;
const chartData = [];
for (
let date = new Date(this.startDate);
date <= new Date(this.endDate);
let date = this.localStartDate;
date <= this.localEndDate;
date.setDate(date.getDate() + 1)
) {
const dateString = dateFormat(date, this.dateFormatMask);
......@@ -38,6 +48,25 @@ export default class BurndownChartData {
openIssuesCount += openedIssuesToday.count - closedIssuesToday.count;
openIssuesWeight += openedIssuesToday.weight - closedIssuesToday.weight;
// Due to timezone differences or unforeseen bugs/errors in the source or
// processed data, it is possible that we end up with a negative issue or
// weight count on an given date. To mitigate this, we reset the current
// date's counters to 0 and carry forward the negative count to a future
// date until the total is positive again.
if (openIssuesCount < 0 || openIssuesWeight < 0) {
carriedIssuesCount = openIssuesCount;
carriedIssuesWeight = openIssuesWeight;
openIssuesCount = 0;
openIssuesWeight = 0;
} else if (carriedIssuesCount < 0 || carriedIssuesWeight < 0) {
openIssuesCount += carriedIssuesCount;
openIssuesWeight += carriedIssuesWeight;
carriedIssuesCount = 0;
carriedIssuesWeight = 0;
}
chartData.push([dateString, openIssuesCount, openIssuesWeight]);
}
......@@ -46,14 +75,14 @@ export default class BurndownChartData {
// Process raw milestone events:
// 1. Set event creation date to milestone start date if created before milestone start
// 2. Convert event creation date to local timezone
// 2. Convert event creation datetime to date in local timezone
processRawEvents(events) {
return events.map(event => ({
...event,
created_at: dateFormat(
new Date(event.created_at) < new Date(this.startDate) ? this.startDate : event.created_at,
this.dateFormatMask,
),
created_at:
dateFormat(event.created_at, this.dateFormatMask) < this.startDate
? this.startDate
: dateFormat(event.created_at, this.dateFormatMask),
}));
}
......
---
title: Fix x-axis burndown chart offset by timezone
merge_request: 15690
author:
type: fixed
import dateFormat from 'dateformat';
import timezoneMock from 'timezone-mock';
import BurndownChartData from 'ee/burndown_chart/burndown_chart_data';
describe('BurndownChartData', () => {
......@@ -30,6 +31,24 @@ describe('BurndownChartData', () => {
]);
});
describe('when viewing in a timezone in the west', () => {
beforeAll(() => {
timezoneMock.register('US/Pacific');
});
afterAll(() => {
timezoneMock.unregister();
});
it('has the right start and end dates', () => {
expect(burndownChartData.generate()).toEqual([
['2017-03-01', 1, 2],
['2017-03-02', 3, 6],
['2017-03-03', 3, 6],
]);
});
});
describe('when issues are created before start date', () => {
beforeAll(() => {
milestoneEvents.push({
......@@ -49,22 +68,41 @@ describe('BurndownChartData', () => {
});
describe('when viewing before due date', () => {
const realDateNow = Date.now;
beforeAll(() => {
const today = new Date(2017, 2, 2);
// eslint-disable-next-line no-global-assign
Date = class extends Date {
constructor(date) {
super(date || today);
}
};
const today = jest.fn(() => new Date(2017, 2, 2));
global.Date.now = today;
});
afterAll(() => {
global.Date.now = realDateNow;
});
it('counts until today if milestone due date > date today', () => {
const chartData = burndownChartData.generate();
expect(dateFormat(new Date(), 'yyyy-mm-dd')).toEqual('2017-03-02');
expect(dateFormat(Date.now(), 'yyyy-mm-dd')).toEqual('2017-03-02');
expect(chartData[chartData.length - 1][0]).toEqual('2017-03-02');
});
});
describe('when first two days of milestone have negative issue count', () => {
beforeAll(() => {
milestoneEvents.push(
{ created_at: '2017-03-01T00:00:00.000Z', weight: 2, action: 'closed' },
{ created_at: '2017-03-01T00:00:00.000Z', weight: 2, action: 'closed' },
{ created_at: '2017-03-01T00:00:00.000Z', weight: 2, action: 'closed' },
);
});
it('sets first two dates data to 0 and carries forward negative total to the third day', () => {
expect(burndownChartData.generate()).toEqual([
['2017-03-01', 0, 0],
['2017-03-02', 0, 0],
['2017-03-03', 1, 2],
]);
});
});
});
});
......@@ -11815,6 +11815,11 @@ timers-browserify@^2.0.4:
dependencies:
setimmediate "^1.0.4"
timezone-mock@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/timezone-mock/-/timezone-mock-1.0.8.tgz#1b9f7af13f2bf84b7aa3d3d6e24aa17255b6037d"
integrity sha512-7dgx34HJPY8O/c5dbqG+I9S3TVDjrfssXmS8BNqiy8sdYvYDfM7shHpNA6VTDQWcDGyv43bE3El6YuFDQf1X3g==
tiny-emitter@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.0.2.tgz#82d27468aca5ade8e5fd1e6d22b57dd43ebdfb7c"
......
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