commit
d19c431f16
|
@ -1,5 +1,7 @@
|
|||
# Changelog #
|
||||
|
||||
## 3.1.0 No name yet (no date yet)
|
||||
- Velocity forecasting. Create sprints according to team velocity.
|
||||
|
||||
## 3.0.0 Stellaria Borealis (2016-10-02)
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ CreateEditSprint = ($repo, $confirm, $rs, $rootscope, lightboxService, $loading,
|
|||
createSprint = true
|
||||
form = null
|
||||
$scope.newSprint = {}
|
||||
ussToAdd = null
|
||||
|
||||
resetSprint = () ->
|
||||
form.reset() if form
|
||||
|
@ -97,7 +98,10 @@ CreateEditSprint = ($repo, $confirm, $rs, $rootscope, lightboxService, $loading,
|
|||
else
|
||||
return it
|
||||
|
||||
$rootscope.$broadcast(broadcastEvent, data)
|
||||
if broadcastEvent == "sprintform:create:success" && ussToAdd
|
||||
$rootscope.$broadcast(broadcastEvent, data, ussToAdd)
|
||||
else
|
||||
$rootscope.$broadcast(broadcastEvent, data)
|
||||
|
||||
lightboxService.close($el)
|
||||
|
||||
|
@ -135,7 +139,8 @@ CreateEditSprint = ($repo, $confirm, $rs, $rootscope, lightboxService, $loading,
|
|||
|
||||
return sortedSprints[sortedSprints.length - 1]
|
||||
|
||||
$scope.$on "sprintform:create", (event, projectId) ->
|
||||
$scope.$on "sprintform:create", (event, projectId, uss) ->
|
||||
ussToAdd = uss
|
||||
resetSprint()
|
||||
|
||||
form = $el.find("form").checksley()
|
||||
|
|
|
@ -86,6 +86,7 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
|||
@showTags = false
|
||||
@activeFilters = false
|
||||
@scope.showGraphPlaceholder = null
|
||||
@displayVelocity = false
|
||||
|
||||
@.initializeEventHandlers()
|
||||
|
||||
|
@ -120,8 +121,10 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
|||
@confirm.notify("success")
|
||||
@analytics.trackEvent("userstory", "create", "bulk create userstory on backlog", 1)
|
||||
|
||||
@scope.$on "sprintform:create:success", =>
|
||||
@.loadSprints()
|
||||
@scope.$on "sprintform:create:success", (e, data, ussToMove) =>
|
||||
@.loadSprints().then () =>
|
||||
@scope.$broadcast("sprintform:create:success:callback", ussToMove)
|
||||
|
||||
@.loadProjectStats()
|
||||
@confirm.notify("success")
|
||||
@analytics.trackEvent("sprint", "create", "create sprint on backlog", 1)
|
||||
|
@ -181,6 +184,17 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
|||
toggleActiveFilters: ->
|
||||
@activeFilters = !@activeFilters
|
||||
|
||||
toggleVelocityForecasting: ->
|
||||
@displayVelocity = !@displayVelocity
|
||||
if !@displayVelocity
|
||||
@scope.visibleUserStories = _.map @scope.userstories, (it) ->
|
||||
return it.ref
|
||||
else
|
||||
@scope.visibleUserStories = _.map @.forecastedStories, (it) ->
|
||||
return it.ref
|
||||
scopeDefer @scope, =>
|
||||
@scope.$broadcast("userstories:loaded")
|
||||
|
||||
loadProjectStats: ->
|
||||
return @rs.projects.stats(@scope.projectId).then (stats) =>
|
||||
@scope.stats = stats
|
||||
|
@ -192,6 +206,7 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
|||
@scope.stats.completedPercentage = 0
|
||||
|
||||
@scope.showGraphPlaceholder = !(stats.total_points? && stats.total_milestones?)
|
||||
@.calculateForecasting()
|
||||
return stats
|
||||
|
||||
setMilestonesOrder: (sprints) ->
|
||||
|
@ -275,6 +290,7 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
|||
promise = @rs.userstories.listUnassigned(@scope.projectId, params, pageSize)
|
||||
|
||||
return promise.then (result) =>
|
||||
|
||||
userstories = result[0]
|
||||
header = result[1]
|
||||
|
||||
|
@ -283,6 +299,8 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
|||
|
||||
# NOTE: Fix order of USs because the filter orderBy does not work propertly in the partials files
|
||||
@scope.userstories = @scope.userstories.concat(_.sortBy(userstories, "backlog_order"))
|
||||
@scope.visibleUserStories = _.map @scope.userstories, (it) ->
|
||||
return it.ref
|
||||
|
||||
for it in @scope.userstories
|
||||
@.backlogOrder[it.id] = it.backlog_order
|
||||
|
@ -305,7 +323,22 @@ class BacklogController extends mixOf(taiga.Controller, taiga.PageMixin, taiga.F
|
|||
@.loadProjectStats(),
|
||||
@.loadSprints(),
|
||||
@.loadUserstories()
|
||||
])
|
||||
]).then(@.calculateForecasting)
|
||||
|
||||
calculateForecasting: ->
|
||||
stats = @scope.stats
|
||||
total_points = stats.total_points
|
||||
current_sum = stats.assigned_points
|
||||
backlog_points_sum = 0
|
||||
@forecastedStories = []
|
||||
|
||||
for us in @scope.userstories
|
||||
current_sum += us.total_points
|
||||
backlog_points_sum += us.total_points
|
||||
@forecastedStories.push(us)
|
||||
|
||||
if stats.speed > 0 && backlog_points_sum > stats.speed
|
||||
break
|
||||
|
||||
loadProject: ->
|
||||
return @rs.projects.getBySlug(@params.pslug).then (project) =>
|
||||
|
@ -545,7 +578,7 @@ module.controller("BacklogController", BacklogController)
|
|||
## Backlog Directive
|
||||
#############################################################################
|
||||
|
||||
BacklogDirective = ($repo, $rootscope, $translate) ->
|
||||
BacklogDirective = ($repo, $rootscope, $translate, $rs) ->
|
||||
## Doom line Link
|
||||
doomLineTemplate = _.template("""
|
||||
<div class="doom-line"><span><%- text %></span></div>
|
||||
|
@ -553,11 +586,13 @@ BacklogDirective = ($repo, $rootscope, $translate) ->
|
|||
|
||||
linkDoomLine = ($scope, $el, $attrs, $ctrl) ->
|
||||
reloadDoomLine = ->
|
||||
if $scope.stats? and $scope.stats.total_points? and $scope.stats.total_points != 0
|
||||
if $scope.displayVelocity
|
||||
removeDoomlineDom()
|
||||
|
||||
if $scope.stats? and $scope.stats.total_points? and $scope.stats.total_points != 0 and !$scope.displayVelocity?
|
||||
removeDoomlineDom()
|
||||
|
||||
stats = $scope.stats
|
||||
|
||||
total_points = stats.total_points
|
||||
current_sum = stats.assigned_points
|
||||
|
||||
|
@ -584,6 +619,7 @@ BacklogDirective = ($repo, $rootscope, $translate) ->
|
|||
return _.map(rowElements, (x) -> angular.element(x))
|
||||
|
||||
$scope.$on("userstories:loaded", reloadDoomLine)
|
||||
$scope.$on("userstories:forecast", removeDoomlineDom)
|
||||
$scope.$watch("stats", reloadDoomLine)
|
||||
|
||||
## Move to current sprint link
|
||||
|
@ -614,9 +650,11 @@ BacklogDirective = ($repo, $rootscope, $translate) ->
|
|||
# Update the total of points
|
||||
sprint.total_points += totalExtraPoints
|
||||
|
||||
$repo.saveAll(selectedUss).then ->
|
||||
$rs.userstories.bulkUpdateMilestone($scope.project.id, $scope.sprints[0].id, selectedUss).then =>
|
||||
$ctrl.loadSprints()
|
||||
$ctrl.loadProjectStats()
|
||||
$ctrl.toggleVelocityForecasting()
|
||||
$ctrl.calculateForecasting()
|
||||
|
||||
$el.find(".move-to-sprint").hide()
|
||||
|
||||
|
@ -626,6 +664,9 @@ BacklogDirective = ($repo, $rootscope, $translate) ->
|
|||
moveToLatestSprint = (selectedUss) ->
|
||||
moveUssToSprint(selectedUss, $scope.sprints[0])
|
||||
|
||||
$scope.$on "sprintform:create:success:callback", (e, ussToMove) ->
|
||||
_.partial(moveToCurrentSprint, ussToMove)()
|
||||
|
||||
shiftPressed = false
|
||||
lastChecked = null
|
||||
|
||||
|
@ -640,6 +681,7 @@ BacklogDirective = ($repo, $rootscope, $translate) ->
|
|||
else
|
||||
moveToSprintDom.hide()
|
||||
|
||||
|
||||
$(window).on "keydown.shift-pressed keyup.shift-pressed", (event) ->
|
||||
shiftPressed = !!event.shiftKey
|
||||
|
||||
|
@ -685,6 +727,22 @@ BacklogDirective = ($repo, $rootscope, $translate) ->
|
|||
|
||||
showHideTags($ctrl)
|
||||
|
||||
$el.on "click", ".forecasting-add-sprint", (event) ->
|
||||
ussToMoveList = $ctrl.forecastedStories
|
||||
if $scope.currentSprint
|
||||
ussToMove = _.map ussToMoveList, (us, index) ->
|
||||
us.milestone = $scope.currentSprint.id
|
||||
us.order = index
|
||||
return us
|
||||
|
||||
$scope.$apply(_.partial(moveToCurrentSprint, ussToMove))
|
||||
else
|
||||
ussToMove = _.map ussToMoveList, (us, index) ->
|
||||
us.order = index
|
||||
return us
|
||||
|
||||
$rootscope.$broadcast("sprintform:create", $scope.projectId, ussToMove)
|
||||
|
||||
showHideTags = ($ctrl) ->
|
||||
elm = angular.element("#show-tags")
|
||||
|
||||
|
@ -759,7 +817,7 @@ BacklogDirective = ($repo, $rootscope, $translate) ->
|
|||
return {link: link}
|
||||
|
||||
|
||||
module.directive("tgBacklog", ["$tgRepo", "$rootScope", "$translate", BacklogDirective])
|
||||
module.directive("tgBacklog", ["$tgRepo", "$rootScope", "$translate", "$tgResources", BacklogDirective])
|
||||
|
||||
#############################################################################
|
||||
## User story points directive
|
||||
|
|
|
@ -127,3 +127,11 @@ darkerFilter = ->
|
|||
|
||||
|
||||
module.filter("darker", darkerFilter)
|
||||
|
||||
inArray = ($filter) ->
|
||||
return (list, arrayFilter, element) ->
|
||||
if arrayFilter
|
||||
filter = $filter("filter")
|
||||
return filter list, (listItem) ->
|
||||
return arrayFilter.indexOf(listItem[element]) != -1
|
||||
module.filter("inArray", ["$filter", inArray])
|
||||
|
|
|
@ -109,6 +109,7 @@ urls = {
|
|||
"bulk-update-us-milestone": "/userstories/bulk_update_milestone"
|
||||
"bulk-update-us-miles-order": "/userstories/bulk_update_sprint_order"
|
||||
"bulk-update-us-kanban-order": "/userstories/bulk_update_kanban_order"
|
||||
"bulk-update-us-milestone": "/userstories/bulk_update_milestone"
|
||||
"userstories-filters": "/userstories/filters_data"
|
||||
"userstory-upvote": "/userstories/%s/upvote"
|
||||
"userstory-downvote": "/userstories/%s/downvote"
|
||||
|
|
|
@ -108,6 +108,17 @@ resourceProvider = ($repo, $http, $urls, $storage, $q) ->
|
|||
params = {project_id: projectId, bulk_stories: data}
|
||||
return $http.post(url, params)
|
||||
|
||||
service.bulkUpdateMilestone = (projectId, milestoneId, data) ->
|
||||
url = $urls.resolve("bulk-update-us-milestone")
|
||||
data = _.map data, (us) ->
|
||||
return {
|
||||
us_id: us.id
|
||||
order: us.order
|
||||
}
|
||||
|
||||
params = {project_id: projectId, milestone_id: milestoneId, bulk_stories: data}
|
||||
return $http.post(url, params)
|
||||
|
||||
service.listValues = (projectId, type) ->
|
||||
params = {"project": projectId}
|
||||
service.storeQueryParams(projectId, params)
|
||||
|
|
|
@ -1249,6 +1249,12 @@
|
|||
"SHOW": "Show tags",
|
||||
"HIDE": "Hide tags"
|
||||
},
|
||||
"FORECASTING": {
|
||||
"TITLE": "Velocity forecasting",
|
||||
"BACKLOG": "Display backlog",
|
||||
"NEW_SPRINT": "Candidate User Stories for your next sprint based on your velocity. Click to create a new sprint.",
|
||||
"CURRENT_SPRINT": "Candidate User Stories for your sprint based on your velocity. Click to add to current sprint."
|
||||
},
|
||||
"TABLE": {
|
||||
"COLUMN_US": "User Stories",
|
||||
"TITLE_COLUMN_POINTS": "Select view per Role"
|
||||
|
|
|
@ -36,7 +36,7 @@ div.wrapper(tg-backlog, ng-controller="BacklogController as ctrl",
|
|||
|
||||
div.backlog-menu
|
||||
div.backlog-table-options
|
||||
a.trans-button.menu-button.move-to-current-sprint.move-to-sprint.e2e-move-to-sprint(
|
||||
a.menu-button.move-to-current-sprint.move-to-sprint.e2e-move-to-sprint(
|
||||
ng-if="currentSprint"
|
||||
href=""
|
||||
title="{{'BACKLOG.MOVE_US_TO_CURRENT_SPRINT' | translate}}"
|
||||
|
@ -44,7 +44,7 @@ div.wrapper(tg-backlog, ng-controller="BacklogController as ctrl",
|
|||
)
|
||||
tg-svg(svg-icon="icon-move")
|
||||
span.text(translate="BACKLOG.MOVE_US_TO_CURRENT_SPRINT")
|
||||
a.trans-button.menu-button.move-to-latest-sprint.move-to-sprint.e2e-move-to-sprint(
|
||||
a.menu-button.move-to-latest-sprint.move-to-sprint.e2e-move-to-sprint(
|
||||
ng-if="!currentSprint"
|
||||
href=""
|
||||
title="{{'BACKLOG.MOVE_US_TO_LATEST_SPRINT' | translate}}"
|
||||
|
@ -52,33 +52,61 @@ div.wrapper(tg-backlog, ng-controller="BacklogController as ctrl",
|
|||
)
|
||||
tg-svg(svg-icon="icon-move")
|
||||
span.text(translate="BACKLOG.MOVE_US_TO_LATEST_SPRINT")
|
||||
a.trans-button.menu-button.e2e-open-filter.ng-animate-disabled(
|
||||
a.menu-button.e2e-open-filter.ng-animate-disabled(
|
||||
ng-if="!ctrl.activeFilters"
|
||||
href=""
|
||||
title="{{'BACKLOG.FILTERS.TOGGLE' | translate}}"
|
||||
id="show-filters-button"
|
||||
translate="BACKLOG.FILTERS.SHOW"
|
||||
)
|
||||
a.trans-button.menu-button.active.e2e-open-filter.ng-animate-disabled(
|
||||
a.menu-button.active.e2e-open-filter.ng-animate-disabled(
|
||||
ng-if="ctrl.activeFilters"
|
||||
href=""
|
||||
title="{{'BACKLOG.FILTERS.HIDE' | translate}}"
|
||||
id="show-filters-button"
|
||||
translate="BACKLOG.FILTERS.HIDE"
|
||||
)
|
||||
a.trans-button.menu-button(
|
||||
a.menu-button(
|
||||
ng-if="userstories.length"
|
||||
href=""
|
||||
title="{{'BACKLOG.TAGS.TOGGLE' | translate}}"
|
||||
id="show-tags"
|
||||
translate="BACKLOG.TAGS.SHOW"
|
||||
)
|
||||
a.menu-button.velocity-forecasting-btn.ng-animate-disabled.e2e-velocity-forecasting(
|
||||
ng-if="userstories.length && ctrl.displayVelocity "
|
||||
href=""
|
||||
title="{{'BACKLOG.FORECASTING.TITLE' | translate}}"
|
||||
translate="BACKLOG.FORECASTING.BACKLOG"
|
||||
ng-click="ctrl.toggleVelocityForecasting()"
|
||||
tg-check-permission="add_milestone"
|
||||
)
|
||||
a.menu-button.velocity-forecasting-btn.ng-animate-disabled.e2e-velocity-forecasting(
|
||||
ng-if="userstories.length && !ctrl.displayVelocity && stats.speed > 0"
|
||||
href=""
|
||||
title="{{'BACKLOG.FORECASTING.BACKLOG' | translate}}"
|
||||
translate="BACKLOG.FORECASTING.TITLE"
|
||||
ng-click="ctrl.toggleVelocityForecasting()"
|
||||
tg-check-permission="add_milestone"
|
||||
)
|
||||
include ../includes/components/addnewus
|
||||
|
||||
|
||||
section.backlog-table(ng-class="{'hidden': !userstories.length}")
|
||||
include ../includes/modules/backlog-table
|
||||
|
||||
div.empty-large.js-empty-backlog(ng-class="{'hidden': userstories === undefined || userstories.length}")
|
||||
|
||||
.forecasting-add-sprint.e2e-velocity-forecasting-add(ng-if="ctrl.displayVelocity")
|
||||
tg-svg(svg-icon="icon-add")
|
||||
span(
|
||||
ng-if="!currentSprint"
|
||||
translate="BACKLOG.FORECASTING.NEW_SPRINT"
|
||||
)
|
||||
span(
|
||||
ng-if="currentSprint"
|
||||
translate="BACKLOG.FORECASTING.CURRENT_SPRINT"
|
||||
)
|
||||
|
||||
.empty-large.js-empty-backlog(ng-class="{'hidden': userstories === undefined || userstories.length}")
|
||||
img(
|
||||
src="/#{v}/images/empty/empty_mex.png"
|
||||
alt="{{'BACKLOG.EMPTY' | translate}}"
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
.row.us-item-row(
|
||||
ng-repeat="us in userstories track by us.id"
|
||||
ng-repeat="us in userstories | inArray:visibleUserStories:'ref'"
|
||||
tg-bind-scope
|
||||
ng-class="{blocked: us.is_blocked}"
|
||||
tg-class-permission="{'readonly': '!modify_us'}"
|
||||
)
|
||||
|
||||
.input(tg-check-permission="modify_us")
|
||||
input(
|
||||
type="checkbox"
|
||||
|
|
|
@ -10,7 +10,7 @@ div.backlog-table-header
|
|||
|
||||
div.backlog-table-body(
|
||||
tg-backlog-sortable,
|
||||
ng-class="{'show-tags': ctrl.showTags, 'active-filters': ctrl.activeFilters}"
|
||||
ng-class="{'show-tags': ctrl.showTags, 'active-filters': ctrl.activeFilters, 'forecasted-stories': ctrl.displayVelocity}"
|
||||
infinite-scroll="ctrl.loadUserstories()"
|
||||
infinite-scroll-disabled="ctrl.disablePagination || !ctrl.firstLoadComplete"
|
||||
infinite-scroll-immediate-check='false'
|
||||
|
|
|
@ -3,7 +3,7 @@ tg-lightbox-close
|
|||
form
|
||||
h2.title(translate="LIGHTBOX.ADD_EDIT_SPRINT.TITLE")
|
||||
fieldset
|
||||
input.sprint-name(
|
||||
input.sprint-name.e2e-sprint-name(
|
||||
type="text"
|
||||
name="name"
|
||||
ng-model="newSprint.name"
|
||||
|
|
|
@ -59,6 +59,23 @@
|
|||
color: $blackish;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-button {
|
||||
@extend %button;
|
||||
border-radius: 0;
|
||||
color: $blackish;
|
||||
&:hover {
|
||||
background: $whitish;
|
||||
color: $gray;
|
||||
}
|
||||
&:visited {
|
||||
color: $blackish;
|
||||
}
|
||||
span {
|
||||
color: $blackish;
|
||||
}
|
||||
}
|
||||
|
||||
.submit-button {
|
||||
width: 100%;
|
||||
}
|
||||
|
|
|
@ -25,24 +25,16 @@
|
|||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 1rem;
|
||||
@include breakpoint(laptop) {
|
||||
flex-direction: column;
|
||||
}
|
||||
.menu-button {
|
||||
border-radius: 0;
|
||||
color: $blackish;
|
||||
display: inline-block;
|
||||
padding: .4rem 1.5rem;
|
||||
&.active,
|
||||
&:hover {
|
||||
background: $whitish;
|
||||
color: $gray;
|
||||
}
|
||||
&.active {
|
||||
&:hover {
|
||||
background: darken($whitish, 10%);
|
||||
}
|
||||
}
|
||||
&.move-to-sprint {
|
||||
display: none;
|
||||
}
|
||||
.icon-move {
|
||||
margin-right: .25rem;
|
||||
}
|
||||
}
|
||||
.button-bulk {
|
||||
margin-left: .2rem;
|
||||
|
@ -70,3 +62,23 @@
|
|||
background: $white;
|
||||
}
|
||||
}
|
||||
|
||||
.forecasting-add-sprint {
|
||||
@include font-size(small);
|
||||
background: $mass-white;
|
||||
cursor: pointer;
|
||||
padding: .5rem 0;
|
||||
text-align: center;
|
||||
&:hover {
|
||||
background: darken($mass-white, 3%);
|
||||
transition: background .2s;
|
||||
}
|
||||
.icon-add {
|
||||
@include svg-size(1.75rem);
|
||||
background: $primary-light;
|
||||
fill: $white;
|
||||
margin-right: 1rem;
|
||||
padding: .25rem;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -145,6 +145,10 @@
|
|||
}
|
||||
|
||||
.backlog-table-body {
|
||||
&.forecasted-stories {
|
||||
border: .5rem solid $mass-white;
|
||||
border-bottom: 0;
|
||||
}
|
||||
.row {
|
||||
border-bottom: 1px solid darken($whitish, 4%);
|
||||
cursor: move;
|
||||
|
|
|
@ -131,6 +131,22 @@ helper.openNewUs = function() {
|
|||
$$('.new-us a').get(0).click();
|
||||
};
|
||||
|
||||
helper.velocityForecasting = function() {
|
||||
return $$('.e2e-velocity-forecasting');
|
||||
};
|
||||
|
||||
helper.openVelocityForecasting = function() {
|
||||
$$('.e2e-velocity-forecasting').click();
|
||||
};
|
||||
|
||||
helper.createSprintFromForecasting = function() {
|
||||
$$('.e2e-velocity-forecasting-add').click();
|
||||
let sprintName = 'sprintName' + new Date().getTime();
|
||||
$('.e2e-sprint-name')
|
||||
.sendKeys(sprintName)
|
||||
.sendKeys(protractor.Key.ENTER);
|
||||
};
|
||||
|
||||
helper.openUsBacklogEdit = function(item) {
|
||||
$$('.backlog-table-body .e2e-edit').get(item).click();
|
||||
};
|
||||
|
|
|
@ -449,6 +449,43 @@ describe('backlog', function() {
|
|||
});
|
||||
});
|
||||
|
||||
describe('velocity forecasting', function() {
|
||||
it('show', async function() {
|
||||
browser.get(browser.params.glob.host + 'project/project-1/backlog');
|
||||
await utils.common.waitLoader();
|
||||
|
||||
let usCount = await backlogHelper.userStories().count();
|
||||
|
||||
await backlogHelper.openVelocityForecasting();
|
||||
utils.common.takeScreenshot('backlog', 'velocity-forecasting');
|
||||
|
||||
let newUsCount = await backlogHelper.userStories().count();
|
||||
|
||||
expect(newUsCount).is.below(usCount);
|
||||
});
|
||||
it('create sprint from forecasting', async function() {
|
||||
browser.get(browser.params.glob.host + 'project/project-1/backlog');
|
||||
await utils.common.waitLoader();
|
||||
|
||||
let sprintCount = await backlogHelper.sprintsOpen().count();
|
||||
|
||||
backlogHelper.openVelocityForecasting();
|
||||
backlogHelper.createSprintFromForecasting();
|
||||
|
||||
let newSprintCount = await backlogHelper.sprintsOpen().count();
|
||||
|
||||
expect(sprintCount).is.below(newSprintCount);
|
||||
});
|
||||
it.only('hide forecasting if no velocity', async function() {
|
||||
browser.get(browser.params.glob.host + 'project/project-5/backlog');
|
||||
await utils.common.waitLoader();
|
||||
|
||||
let forecasting = await backlogHelper.velocityForecasting();
|
||||
|
||||
expect(forecasting).to.be.empty;
|
||||
});
|
||||
});
|
||||
|
||||
describe('backlog filters', sharedFilters.bind(this, 'backlog', () => {
|
||||
return backlogHelper.userStories().count();
|
||||
}));
|
||||
|
|
Loading…
Reference in New Issue