Commit c07e0377 authored by Bryce Johnson's avatar Bryce Johnson

Round out tests for time tracking component.

parent 997def72
......@@ -125,7 +125,8 @@
</div>
<div class='title hide-collapsed'>
Time tracking
<div class='help-button pull-right' v-if='showHelp' v-on:click='toggleHelpState(true)'>
<div class='help-button pull-right' v-if='!showHelp' v-on:click='toggleHelpState(true)'>
<i class='fa fa-question-circle'></i>
</div>
</div>
<div class='time-tracking-content hide-collapsed'>
......@@ -159,6 +160,7 @@
</div>
<div class='time-tracking-help-state' v-if='showHelp'>
<div class='close-help-button pull-right' v-on:click='toggleHelpState(false)'>
<i class='fa fa-close'></i>
</div>
<div class='time-tracking-info'>
<h4>Track time with slash commands</h4>
......@@ -171,6 +173,7 @@
<code>/spend</code>
will update the sum of the time spent.
</p>
<a class='btn btn-default learn-more-button' href='http://example.com/time-tracking-url'> Learn more </a>
</div>
</div>
</div>
......
......@@ -74,7 +74,7 @@
= dropdown_tag('Milestone', options: { title: 'Assign milestone', toggle_class: 'js-milestone-select js-extra-options', filter: true, dropdown_class: 'dropdown-menu-selectable', placeholder: 'Search milestones', data: { show_no: true, field_name: "#{issuable.to_ability_name}[milestone_id]", project_id: @project.id, issuable_id: issuable.id, milestones: namespace_project_milestones_path(@project.namespace, @project, :json), ability_name: issuable.to_ability_name, issue_update: issuable_json_path(issuable), use_id: true }})
// TODO: Need to add check for time_estimated - if issuable.has_attribute?(:time_estimated) once hooked up to backend
- if issuable.has_attribute?(:time_estimate)
#issuable-time-tracker.block{ issuable: issuable.to_json() }
#issuable-time-tracker.block
%issuable-time-tracker{ ':time_estimate' => 'issuable.time_estimate', ':time_spent' => 'issuable.time_spent' }
- if issuable.has_attribute?(:due_date)
.block.due_date
......
/* eslint-disable */
//= require jquery
//= require vue
//= require vue-resource
//= require directives/tooltip_title
//= require issuable_time_tracker
//= require directives/tooltip_title
((gl) => {
function initComponent({time_estimate = 100000, time_spent = 5000}) {
fixture.set(`<div id="mock-container"><issuable-time-tracker :time_estimate='${time_estimate}', :time_spent='${time_spent}'></issuable-time-tracker></div>`);
const elem = document.getElementById('mock-container');
debugger;
const comp = new Vue({
el: elem,
propsData: { time_estimate: time_estimate, time_spent: time_estimate },
});
function initComponent(time_estimate = 100000, time_spent = 5000 ) {
fixture.set(`
<div>
<div id="mock-container"></div>
</div>
`);
return comp;
}
describe('Issuable Time Tracker', function() {
this.initialData = {
time_estimate,
time_spent
};
this.timeTracker = new gl.IssuableTimeTracker({
el: '#mock-container',
propsData: this.initialData
});
}
((gl) => {
describe('Issuable Time Tracker', function() {
describe('Initialization', function() {
beforeEach(function() {
this.initialData = { time_estimate: 100000, time_spent: 50000 };
this.timeTracker = initComponent(this.initialData);
initComponent.apply(this);
});
it('should return something defined', function() {
......@@ -30,13 +34,10 @@
});
it ('should correctly set time_estimate', function() {
expect(this.timeTracker.$data.time_estimate).toBeDefined();
expect(this.timeTracker.$data.time_estimate).toBe(this.initialData.time_estimate);
expect(this.timeTracker.time_estimate).toBe(this.initialData.time_estimate);
});
it ('should correctly set time_spent', function() {
expect(this.timeTracker.$data.time_spent).toBeDefined();
expect(this.timeTracker.$data.time_spent).toBe(this.initialData.time_spent);
expect(this.timeTracker.time_spent).toBe(this.initialData.time_spent);
});
});
......@@ -44,109 +45,167 @@
describe('Panes', function() {
describe('Comparison pane', function() {
beforeEach(function() {
this.initialData = { time_estimate: 100000, time_spent: 50000 };
this.timeTracker = initComponent(this.initialData);
initComponent.apply(this);
});
it('should show the "Comparison" pane when time_estimate and time_spent are truthy', function() {
const $comparisonPane = $('.time-tracking-pane-compare');
const $comparisonPane = this.timeTracker.$el.querySelector('.time-tracking-pane-compare');
expect(this.timeTracker.showComparison).toBe(true);
expect($comparisonPane).toBeVisible();
});
it('should not show panes besides the "Comparison" pane when time_estimate and time_spent are truthy', function() {
const $comparisonPane = $('.time-tracking-pane-compare');
it('should display the human readable version of time estimated', function() {
const estimateText = this.timeTracker.$el.querySelector('.time-tracking-pane-compare .estimated .compare-value').innerText;
const correctText = '0w 3d 3h 46m';
expect(estimateText).toBe(correctText);
});
it('should display the human readable version of time spent', function() {
const spentText = this.timeTracker.$el.querySelector('.time-tracking-pane-compare .compare-value.spent').innerText;
const correctText = '0w 0d 1h 23m';
expect($comparisonPane.siblings()).toBeHidden();
expect(spentText).toBe(correctText);
});
describe('Remaining meter', function() {
it('should display the remaining meter with the correct width', function() {
const meterWidth = this.timeTracker.$el.querySelector('.time-tracking-pane-compare .meter-fill').style.width;
const correctWidth = '5%';
expect(meterWidth).toBe(correctWidth);
});
it('should display the remaining meter with the correct background color when within estimate', function() {
const styledMeter = $(this.timeTracker.$el).find('.time-tracking-pane-compare .within_estimate .meter-fill');
expect(styledMeter.length).toBe(1);
});
it('should display the remaining meter with the correct background color when over estimate', function() {
this.timeTracker.time_estimate = 1;
this.timeTracker.time_spent = 2;
Vue.nextTick(() => {
const styledMeter = $(this.timeTracker.$el).find('.time-tracking-pane-compare .over_estimate .meter-fill');
expect(styledMeter.length).toBe(1);
});
});
});
});
describe("Estimate only pane", function() {
beforeEach(function() {
const time_estimate = 100000;
const time_spent = 0;
const timeTrackingComponent = Vue.extend(gl.IssuableTimeTracker);
const initialData = this.initialData = { time_estimate, time_spent };
this.timeTracker = new timeTrackingComponent({
data: initialData
}).$mount();
initComponent.apply(this, [10000, 0]);
});
// Look for the value
it('should only show the "Estimate only" pane when time_estimate is truthy and time_spent is falsey', function() {
const $estimateOnlyPane = $('.time-tracking-estimate-only');
const $estimateOnlyPane = this.timeTracker.$el.querySelector('.time-tracking-estimate-only');
expect(this.timeTracker.showEstimateOnly).toBe(true);
expect($estimateOnlyPane).toBeVisible();
});
it('should display the human readable version of time estimated', function() {
const estimateText = this.timeTracker.$el.querySelector('.time-tracking-estimate-only').innerText;
const correctText = 'Estimated: 0w 0d 2h 46m';
expect(estimateText).toBe(correctText);
});
});
describe('Spent only pane', function() {
beforeEach(function() {
const time_estimate = 0;
const time_spent = 50000;
const timeTrackingComponent = Vue.extend(gl.IssuableTimeTracker);
const initialData = this.initialData = { time_estimate, time_spent };
this.timeTracker = new timeTrackingComponent({
data: initialData
}).$mount();
initComponent.apply(this, [0, 5000]);
});
// Look for the value
it('should only show the "Spent only" pane when time_estimate is falsey and time_spent is truthy', function() {
const $spentOnlyPane = $('.time-tracking-spend-only');
const $spentOnlyPane = this.timeTracker.$el.querySelector('.time-tracking-spend-only');
expect(this.timeTracker.showSpentOnly).toBe(true);
expect($spentOnlyPane).toBeVisible();
});
it('should display the human readable version of time spent', function() {
const spentText = this.timeTracker.$el.querySelector('.time-tracking-spend-only').innerText;
const correctText = 'Spent: 0w 0d 1h 23m';
expect(spentText).toBe(correctText);
});
});
describe('No time tracking pane', function() {
beforeEach(function() {
const time_estimate = 0;
const time_spent = 0;
const timeTrackingComponent = Vue.extend(gl.IssuableTimeTracker);
const initialData = this.initialData = { time_estimate, time_spent };
this.timeTracker = new timeTrackingComponent({
data: initialData
}).$mount();
initComponent.apply(this, [0, 0]);
});
// Look for The text
it('should only show the "No time tracking" pane when both time_estimate and time_spent are falsey', function() {
const $noTrackingPane = $('.time-tracking-no-tracking');
const $noTrackingPane = this.timeTracker.$el.querySelector('.time-tracking-no-tracking');
expect(this.timeTracker.showNoTimeTracking).toBe(true);
expect($noTrackingPane).toBeVisible();
});
it('should display the status text', function() {
const noTrackingText = this.timeTracker.$el.querySelector('.time-tracking-no-tracking .no-value').innerText;
const correctText = 'No estimate or time spent';
expect(noTrackingText).toBe(correctText);
});
});
describe("Help pane", function() {
beforeEach(function() {
const time_estimate = 100000;
const time_spent = 50000;
const timeTrackingComponent = Vue.extend(gl.IssuableTimeTracker);
const initialData = this.initialData = { time_estimate, time_spent };
this.timeTracker = new timeTrackingComponent({
data: initialData
}).$mount();
initComponent.apply(this, [0, 0]);
});
// close button
// link to help
it('should only not show the "Help" pane by default', function() {
const $helpPane = $('.time-tracking-help-state');
it('should not show the "Help" pane by default', function() {
const $helpPane = this.timeTracker.$el.querySelector('.time-tracking-help-state');
expect(this.timeTracker.showHelp).toBe(false);
expect($helpPane).toBeHidden();
expect($helpPane).toBeNull();
});
it('should link to the correct documentation', function(done) {
const correctUrl = 'http://example.com/time-tracking-url';
$(this.timeTracker.$el).find('.help-button').click();
Vue.nextTick(() => {
const currentHref = $(this.timeTracker.$el).find('.learn-more-button').attr('href');
expect(currentHref).toBe(correctUrl);
done();
});
});
it('should show the "Help" pane when help button is clicked', function(done) {
$(this.timeTracker.$el).find('.help-button').click();
Vue.nextTick(() => {
const $helpPane = this.timeTracker.$el.querySelector('.time-tracking-help-state');
expect(this.timeTracker.showHelp).toBe(true);
expect($helpPane).toBeVisible();
done();
});
});
it('should only show the "Help" pane when toggled', function() {
const $helpPane = $('.time-tracking-help-state');
it('should not show the "Help" pane when help button is clicked and then closed', function(done) {
$(this.timeTracker.$el).find('.help-button').click();
Vue.nextTick(() => {
$(this.timeTracker.$el).find('.close-help-button').click();
expect(this.timeTracker.showHelp).toBe(true);
expect($helpPane).toBeVisible();
Vue.nextTick(() => {
const $helpPane = this.timeTracker.$el.querySelector('.time-tracking-help-state');
expect(this.timeTracker.showHelp).toBe(false);
expect($helpPane).toBeNull();
done();
});
});
});
});
});
......@@ -159,28 +218,140 @@
});
describe('Methods', function() {
// parseSeconds
});
});
beforeEach(function() {
initComponent.apply(this);
});
// show the correct pane
// parse second
// seconds to minutes
// stringify a time value
// the percent is being calculated and displayed correctly on the compare meter
// differ works, if needed
// whether values that are important are actually display
it('should parse a time diff based on total minutes', function() {
});
describe('parseSeconds', function() {
it('should correctly parse a negative value', function() {
const parser = this.timeTracker.parseSeconds;
it('should stringify a time value', function() {
});
const zeroSeconds = parser(-1000);
it('should abbreviate a stringified value', function() {
});
expect(zeroSeconds.minutes).toBe(16);
expect(zeroSeconds.hours).toBe(0);
expect(zeroSeconds.days).toBe(0);
expect(zeroSeconds.weeks).toBe(0);
});
it('should correctly parse a zero value', function() {
const parser = this.timeTracker.parseSeconds;
const zeroSeconds = parser(0);
expect(zeroSeconds.minutes).toBe(0);
expect(zeroSeconds.hours).toBe(0);
expect(zeroSeconds.days).toBe(0);
expect(zeroSeconds.weeks).toBe(0);
});
it('should correctly parse a small non-zero second values', function() {
const parser = this.timeTracker.parseSeconds;
const subOneMinute = parser(10);
expect(subOneMinute.minutes).toBe(0);
expect(subOneMinute.hours).toBe(0);
expect(subOneMinute.days).toBe(0);
expect(subOneMinute.weeks).toBe(0);
const aboveOneMinute = parser(100);
expect(aboveOneMinute.minutes).toBe(1);
expect(aboveOneMinute.hours).toBe(0);
expect(aboveOneMinute.days).toBe(0);
expect(aboveOneMinute.weeks).toBe(0);
const manyMinutes = parser(1000);
expect(manyMinutes.minutes).toBe(16);
expect(manyMinutes.hours).toBe(0);
expect(manyMinutes.days).toBe(0);
expect(manyMinutes.weeks).toBe(0);
});
it('should correctly parse large second values', function() {
const parser = this.timeTracker.parseSeconds;
const aboveOneHour = parser(4800);
expect(aboveOneHour.minutes).toBe(20);
expect(aboveOneHour.hours).toBe(1);
expect(aboveOneHour.days).toBe(0);
expect(aboveOneHour.weeks).toBe(0);
const aboveOneDay = parser(110000);
it('should toggle the help state', function() {
expect(aboveOneDay.minutes).toBe(33);
expect(aboveOneDay.hours).toBe(6);
expect(aboveOneDay.days).toBe(3);
expect(aboveOneDay.weeks).toBe(0);
const aboveOneWeek = parser(25000000);
expect(aboveOneWeek.minutes).toBe(26);
expect(aboveOneWeek.hours).toBe(0);
expect(aboveOneWeek.days).toBe(3);
expect(aboveOneWeek.weeks).toBe(173);
});
});
describe('stringifyTime', function() {
it('should stringify values with all non-zero units', function() {
const timeObject = {
weeks: 1,
days: 4,
hours: 7,
minutes: 20
};
const timeString = this.timeTracker.stringifyTime(timeObject);
expect(timeString).toBe('1w 4d 7h 20m');
});
it('should stringify values with some non-zero units', function() {
const timeObject = {
weeks: 0,
days: 4,
hours: 0,
minutes: 20
};
const timeString = this.timeTracker.stringifyTime(timeObject);
expect(timeString).toBe('0w 4d 0h 20m');
});
it('should stringify values with no non-zero units', function() {
const timeObject = {
weeks: 0,
days: 0,
hours: 0,
minutes: 0
};
const timeString = this.timeTracker.stringifyTime(timeObject);
expect(timeString).toBe('0w 0d 0h 0m');
});
});
describe('abbreviateTime', function() {
it('should abbreviate stringified times for weeks', function() {
const fullTimeString = '1w 3d 4h 5m';
expect(this.timeTracker.abbreviateTime(fullTimeString)).toBe('1w');
});
it('should abbreviate stringified times for non-weeks', function() {
const fullTimeString = '0w 3d 4h 5m';
expect(this.timeTracker.abbreviateTime(fullTimeString)).toBe('3d');
});
});
});
});
});
})(window.gl || (window.gl = {}));
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