Merge pull request #445 from opf/feature/add_server_side_timeline_filters
Feature/add server side timeline filterspull/462/head
commit
d00823f0f6
@ -0,0 +1,78 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2013 the OpenProject Foundation (OPF) |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License version 3. |
||||
# |
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||
# Copyright (C) 2010-2013 the ChiliProject Team |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License |
||||
# as published by the Free Software Foundation; either version 2 |
||||
# of the License, or (at your option) any later version. |
||||
# |
||||
# This program is distributed in the hope that it will be useful, |
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
# GNU General Public License for more details. |
||||
# |
||||
# You should have received a copy of the GNU General Public License |
||||
# along with this program; if not, write to the Free Software |
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
# |
||||
# See doc/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
# resolves either a given status (show) or returns a list of available statuses |
||||
# if the controller is called nested inside a project, it returns only the |
||||
# statuses that can be reached by the workflows of the project |
||||
module Api |
||||
module V2 |
||||
|
||||
class StatusesController < ApplicationController |
||||
include ::Api::V2::ApiController |
||||
rescue_from ActiveRecord::RecordNotFound, with: lambda{render_404} |
||||
|
||||
unloadable |
||||
|
||||
before_filter :require_login |
||||
before_filter :resolve_project |
||||
accept_key_auth :index, :show |
||||
|
||||
|
||||
|
||||
def index |
||||
if @project |
||||
@statuses = Type.issue_statuses(@project.types.map(&:id)) |
||||
else |
||||
visible_type_ids = Project.visible |
||||
.includes(:types) |
||||
.map(&:types).flatten |
||||
.map(&:id) |
||||
@statuses = Type.issue_statuses(visible_type_ids) |
||||
end |
||||
|
||||
respond_to do |format| |
||||
format.api |
||||
end |
||||
end |
||||
|
||||
def show |
||||
@status = IssueStatus.find(params[:id]) |
||||
|
||||
respond_to do |format| |
||||
format.api |
||||
end |
||||
end |
||||
|
||||
protected |
||||
def resolve_project |
||||
@project = Project.find(params[:project_id]) if params[:project_id] |
||||
end |
||||
end |
||||
end |
||||
|
||||
end |
@ -0,0 +1,34 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2013 the OpenProject Foundation (OPF) |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License version 3. |
||||
# |
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||
# Copyright (C) 2010-2013 the ChiliProject Team |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License |
||||
# as published by the Free Software Foundation; either version 2 |
||||
# of the License, or (at your option) any later version. |
||||
# |
||||
# This program is distributed in the hope that it will be useful, |
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
# GNU General Public License for more details. |
||||
# |
||||
# You should have received a copy of the GNU General Public License |
||||
# along with this program; if not, write to the Free Software |
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
# |
||||
# See doc/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
api.array :statuses, :size => @statuses.size do |
||||
@statuses.each do |status| |
||||
render(:partial => '/api/v2/statuses/status.api', |
||||
:object => status) |
||||
end |
||||
end |
@ -0,0 +1,30 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2013 the OpenProject Foundation (OPF) |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License version 3. |
||||
# |
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||
# Copyright (C) 2010-2013 the ChiliProject Team |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License |
||||
# as published by the Free Software Foundation; either version 2 |
||||
# of the License, or (at your option) any later version. |
||||
# |
||||
# This program is distributed in the hope that it will be useful, |
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
# GNU General Public License for more details. |
||||
# |
||||
# You should have received a copy of the GNU General Public License |
||||
# along with this program; if not, write to the Free Software |
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
# |
||||
# See doc/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
render(:partial => '/api/v2/reported_project_statuses/status.api', |
||||
:object => @status) |
@ -0,0 +1,209 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2013 the OpenProject Foundation (OPF) |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License version 3. |
||||
# |
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||
# Copyright (C) 2010-2013 the ChiliProject Team |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License |
||||
# as published by the Free Software Foundation; either version 2 |
||||
# of the License, or (at your option) any later version. |
||||
# |
||||
# This program is distributed in the hope that it will be useful, |
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
# GNU General Public License for more details. |
||||
# |
||||
# You should have received a copy of the GNU General Public License |
||||
# along with this program; if not, write to the Free Software |
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
# |
||||
# See doc/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
Feature: Filtering work packages via the api |
||||
Background: |
||||
Given there is 1 project with the following: |
||||
| identifier | sample_project | |
||||
| name | sample_project | |
||||
And I am working in project "sample_project" |
||||
And the project "sample_project" has the following types: |
||||
| name | position | |
||||
| Bug | 1 | |
||||
| Task | 2 | |
||||
| Story | 3 | |
||||
| Epic | 4 | |
||||
And there is a default issuepriority with: |
||||
| name | Normal | |
||||
And there is a issuepriority with: |
||||
| name | High | |
||||
And there is a issuepriority with: |
||||
| name | Immediate | |
||||
And there are the following issue status: |
||||
| name | is_closed | is_default | |
||||
| New | false | true | |
||||
| In Progress | false | true | |
||||
| Closed | false | true | |
||||
|
||||
And the project uses the following modules: |
||||
| timelines | |
||||
And there is a role "member" |
||||
And the role "member" may have the following rights: |
||||
| edit_work_packages | |
||||
| view_projects | |
||||
| view_reportings | |
||||
| view_timelines | |
||||
| view_work_packages | |
||||
|
||||
And there is 1 user with the following: |
||||
| login | bob | |
||||
And there is 1 user with the following: |
||||
| login | peter | |
||||
And there is 1 user with the following: |
||||
| login | pamela | |
||||
And the user "bob" is a "member" in the project "sample_project" |
||||
And the user "peter" is a "member" in the project "sample_project" |
||||
And the user "pamela" is a "member" in the project "sample_project" |
||||
And I am already logged in as "bob" |
||||
|
||||
Scenario: Call the endpoint of the api without filters |
||||
Given there are the following work packages in project "sample_project": |
||||
| subject | type | |
||||
| work_package#1 | Bug | |
||||
| work_package#2 | Story | |
||||
When I call the work_package-api on project "sample_project" requesting format "json" without any filters |
||||
Then the json-response should include 2 work packages |
||||
And the json-response should contain a work_package "work_package#1" |
||||
And the json-response should contain a work_package "work_package#2" |
||||
|
||||
Scenario: Call the api filtering for type |
||||
Given there are the following work packages in project "sample_project": |
||||
| subject | type | parent | |
||||
| work_package#1 | Bug | | |
||||
| work_package#1.1 | Bug | work_package#1 | |
||||
| work_package#2 | Story | | |
||||
| work_package#2.1 | Story | work_package#2 | |
||||
| work_package#3 | Epic | | |
||||
| work_package#3.1 | Story | work_package#3 | |
||||
When I call the work_package-api on project "sample_project" requesting format "json" filtering for type "Bug" |
||||
Then the json-response should include 2 work packages |
||||
Then the json-response should not contain a work_package "work_package#2" |
||||
And the json-response should contain a work_package "work_package#1" |
||||
|
||||
Scenario: Call the api filtering for status |
||||
Given there are the following work packages in project "sample_project": |
||||
| subject | type | status | |
||||
| work_package#1 | Bug | New | |
||||
| work_package#2 | Story | In Progress | |
||||
| work_package#3 | Epic | Closed | |
||||
|
||||
When I call the work_package-api on project "sample_project" requesting format "json" filtering for status "In Progress" |
||||
Then the json-response should include 1 work package |
||||
Then the json-response should contain a work_package "work_package#2" |
||||
And the json-response should not contain a work_package "work_package#1" |
||||
|
||||
Scenario: Filtering multiple types |
||||
Given there are the following work packages in project "sample_project": |
||||
| subject | type | parent | |
||||
| work_package#1 | Bug | | |
||||
| work_package#1.1 | Bug | work_package#1 | |
||||
| work_package#3 | Epic | | |
||||
| work_package#3.1 | Story | work_package#3 | |
||||
When I call the work_package-api on project "sample_project" requesting format "json" filtering for type "Bug,Epic" |
||||
Then the json-response should include 3 work packages |
||||
And the json-response should contain a work_package "work_package#1" |
||||
And the json-response should contain a work_package "work_package#3" |
||||
And the json-response should not contain a work_package "work_package#3.1" |
||||
|
||||
Scenario: Filter out children of work packages, if they don't have the right type |
||||
Given there are the following work packages in project "sample_project": |
||||
| subject | type | parent | |
||||
| work_package#3 | Epic | | |
||||
| work_package#3.1 | Story | work_package#3 | |
||||
When I call the work_package-api on project "sample_project" requesting format "json" filtering for type "Epic" |
||||
Then the json-response should include 1 work package |
||||
And the json-response should contain a work_package "work_package#3" |
||||
And the json-response should not contain a work_package "work_package#3.1" |
||||
|
||||
Scenario: Filter out parents of work packages, if they don't have the right type |
||||
Given there are the following work packages in project "sample_project": |
||||
| subject | type | |
||||
| work_package#1 | Bug | |
||||
| work_package#2 | Story | |
||||
When I call the work_package-api on project "sample_project" requesting format "json" filtering for type "Story" |
||||
Then the json-response should include 1 work package |
||||
And the json-response should not contain a work_package "work_package#1" |
||||
And the json-response should contain a work_package "work_package#2" |
||||
|
||||
|
||||
Scenario: correctly export parent-child-relations |
||||
Given there are the following work packages in project "sample_project": |
||||
| subject | type | parent | |
||||
| work_package#1 | Epic | | |
||||
| work_package#1.1 | Story | work_package#1 | |
||||
| work_package#2 | Task | work_package#1.1 | |
||||
When I call the work_package-api on project "sample_project" requesting format "json" without any filters |
||||
Then the json-response should include 3 work packages |
||||
And the json-response should say that "work_package#1" is parent of "work_package#1.1" |
||||
|
||||
Scenario: Move parent-relations up the ancestor-chain, when intermediate packages are fitered |
||||
Given there are the following work packages in project "sample_project": |
||||
| subject | type | parent | |
||||
| work_package#1 | Epic | | |
||||
| work_package#1.1 | Story | work_package#1 | |
||||
| work_package#1.1.1 | Task | work_package#1.1 | |
||||
When I call the work_package-api on project "sample_project" requesting format "json" filtering for type "Epic,Task" |
||||
Then the json-response should include 2 work packages |
||||
And the json-response should not contain a work_package "work_package#1.1" |
||||
And the json-response should contain a work_package "work_package#1" |
||||
And the json-response should contain a work_package "work_package#1.1.1" |
||||
And the json-response should say that "work_package#1" is parent of "work_package#1.1.1" |
||||
|
||||
Scenario: The parent should be rewired to the first ancestor present in the filtered set |
||||
Given there are the following work packages in project "sample_project": |
||||
| subject | type | parent | |
||||
| work_package#1 | Epic | | |
||||
| work_package#1.1 | Task | work_package#1 | |
||||
| work_package#1.1.1 | Bug | work_package#1.1 | |
||||
| work_package#1.1.1.1 | Task | work_package#1.1.1 | |
||||
|
||||
When I call the work_package-api on project "sample_project" requesting format "json" filtering for type "Epic,Task" |
||||
Then the json-response should include 3 work packages |
||||
And the json-response should say that "work_package#1.1" is parent of "work_package#1.1.1.1" |
||||
|
||||
Scenario: When all ancestors are filtered, the work_package should have no parent |
||||
Given there are the following work packages in project "sample_project": |
||||
| subject | type | parent | |
||||
| work_package#1 | Epic | | |
||||
| work_package#1.1 | Story | work_package#1 | |
||||
| work_package#1.1.1 | Task | work_package#1.1 | |
||||
When I call the work_package-api on project "sample_project" requesting format "json" filtering for type "Task" |
||||
Then the json-response should include 1 work packages |
||||
And the json-response should say that "work_package#1.1.1" has no parent |
||||
|
||||
Scenario: Children are filtered out |
||||
Given there are the following work packages in project "sample_project": |
||||
| subject | type | parent | |
||||
| work_package#1 | Epic | | |
||||
| work_package#1.1 | Task | work_package#1 | |
||||
| work_package#1.2 | Story | work_package#1 | |
||||
When I call the work_package-api on project "sample_project" requesting format "json" filtering for type "Epic,Story" |
||||
And the json-response should say that "work_package#1" has 1 child |
||||
|
||||
Scenario: Filtering for responsibles |
||||
Given there are the following work packages in project "sample_project": |
||||
| subject | type | responsible | |
||||
| work_package#1 | Task | bob | |
||||
| work_package#2 | Task | peter | |
||||
| work_package#3 | Task | pamela | |
||||
When I call the work_package-api on project "sample_project" requesting format "json" filtering for responsible "peter" |
||||
Then the json-response should include 1 work package |
||||
And the json-response should not contain a work_package "work_package#1" |
||||
And the json-response should contain a work_package "work_package#2" |
||||
|
||||
|
@ -0,0 +1,150 @@ |
||||
#encoding: utf-8 |
||||
|
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2013 the OpenProject Foundation (OPF) |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License version 3. |
||||
# |
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||
# Copyright (C) 2010-2013 the ChiliProject Team |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License |
||||
# as published by the Free Software Foundation; either version 2 |
||||
# of the License, or (at your option) any later version. |
||||
# |
||||
# This program is distributed in the hope that it will be useful, |
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
# GNU General Public License for more details. |
||||
# |
||||
# You should have received a copy of the GNU General Public License |
||||
# along with this program; if not, write to the Free Software |
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
# |
||||
# See doc/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
require "benchmark" |
||||
|
||||
When(/^I call the work_package\-api on project "(.*?)" requesting format "(.*?)" without any filters$/) do |project_name, format| |
||||
|
||||
@project = Project.find(project_name) |
||||
@unfiltered_benchmark = Benchmark.measure("Unfiltered Results") do |
||||
visit api_v2_project_planning_elements_path(project_id: project_name, format: format) |
||||
end |
||||
|
||||
end |
||||
|
||||
Then(/^the json\-response should include (\d+) work package(s?)$/) do |number_of_wps, plural| |
||||
expect(work_package_names.size).to eql number_of_wps.to_i |
||||
end |
||||
|
||||
Then(/^the json\-response should( not)? contain a work_package "(.*?)"$/) do |negation, work_package_name| |
||||
if negation |
||||
expect(work_package_names).not_to include work_package_name |
||||
else |
||||
expect(work_package_names).to include work_package_name |
||||
end |
||||
|
||||
end |
||||
|
||||
And(/^the json\-response should say that "(.*?)" is parent of "(.*?)"$/) do |parent_name, child_name| |
||||
child = decoded_json["planning_elements"].select {|wp| wp["name"] == child_name}.first |
||||
expect(child["parent"]["name"]).to eql parent_name |
||||
end |
||||
|
||||
And(/^the json\-response should say that "(.*?)" has no parent$/) do |child_name| |
||||
child = decoded_json["planning_elements"].select {|wp| wp["name"] == child_name}.first |
||||
expect(child["parent"]).to be_nil |
||||
end |
||||
|
||||
And(/^the json\-response should say that "(.*?)" has (\d+) child(ren)?$/) do |parent_name, nr_of_children,plural| |
||||
parent = decoded_json["planning_elements"].select {|wp| wp["name"] == parent_name}.first |
||||
expect(parent["children"].size).to eql nr_of_children.to_i |
||||
end |
||||
|
||||
|
||||
When(/^I call the work_package\-api on project "(.*?)" requesting format "(.*?)" filtering for status "(.*?)"$/) do |project_name, format, status_names| |
||||
statuses = IssueStatus.where(name: status_names.split(',')) |
||||
|
||||
get_filtered_json(project_name: project_name, |
||||
format: format, |
||||
filters: [:status_id], |
||||
operators: {status_id: "="}, |
||||
values: {status_id: statuses.map(&:id)} ) |
||||
end |
||||
|
||||
Then(/^I call the work_package\-api on project "(.*?)" requesting format "(.*?)" filtering for type "(.*?)"$/) do |project_name, format, type_names| |
||||
types = Project.find_by_identifier(project_name).types.where(name: type_names.split(",")) |
||||
|
||||
get_filtered_json(project_name: project_name, |
||||
format: format, |
||||
filters: [:type_id], |
||||
operators: {type_id: "="}, |
||||
values: {type_id: types.map(&:id)} ) |
||||
|
||||
|
||||
end |
||||
|
||||
When(/^I call the work_package\-api on project "(.*?)" requesting format "(.*?)" filtering for responsible "(.*?)"$/) do |project_name, format, responsible_names| |
||||
responsibles = User.where(login: responsible_names.split(',')) |
||||
|
||||
get_filtered_json(project_name: project_name, |
||||
format: format, |
||||
filters: [:responsible_id], |
||||
operators: {responsible_id: "="}, |
||||
values: {responsible_id: responsibles.map(&:id)} ) |
||||
|
||||
end |
||||
|
||||
|
||||
And(/^there are (\d+) work packages of type "(.*?)" in project "(.*?)"$/) do |nr_of_wps, type_name, project_name| |
||||
project = Project.find_by_identifier(project_name) |
||||
type = project.types.find_by_name(type_name) |
||||
|
||||
FactoryGirl.create_list(:work_package, nr_of_wps.to_i, project: project, type: type) |
||||
|
||||
end |
||||
|
||||
|
||||
And(/^the time to get the unfiltered results should not exceed (\d+)\.(\d+)s$/) do |seconds,milliseconds| |
||||
puts "----Unfiltered Benchmark----" |
||||
puts @unfiltered_benchmark |
||||
@unfiltered_benchmark.total.should < "#{seconds}.#{milliseconds}".to_f |
||||
end |
||||
|
||||
And(/^the time to get the filtered results should not exceed (\d+)\.(\d+)s$/) do |seconds, milliseconds| |
||||
puts "----Filtered Benchmark----" |
||||
puts @filtered_benchmark |
||||
@filtered_benchmark.total.should < "#{seconds}.#{milliseconds}".to_f |
||||
end |
||||
|
||||
Then(/^the time to get the filtered results should be faster than the time to get the unfiltered results$/) do |
||||
@filtered_benchmark.total.should < @unfiltered_benchmark.total |
||||
end |
||||
|
||||
def work_package_names |
||||
decoded_json["planning_elements"].map{|wp| wp["name"]} |
||||
end |
||||
|
||||
def decoded_json |
||||
@decoded_json ||= ActiveSupport::JSON.decode last_json |
||||
end |
||||
|
||||
def last_json |
||||
page.source |
||||
end |
||||
|
||||
def get_filtered_json(params) |
||||
@filtered_benchmark = Benchmark.measure("Filtered Results") do |
||||
visit api_v2_project_planning_elements_path(project_id: params[:project_name], |
||||
format: params[:format], |
||||
f: params[:filters], |
||||
op: params[:operators], |
||||
v: params[:values]) |
||||
end |
||||
end |
@ -0,0 +1,90 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2013 the OpenProject Foundation (OPF) |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License version 3. |
||||
# |
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||
# Copyright (C) 2010-2013 the ChiliProject Team |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License |
||||
# as published by the Free Software Foundation; either version 2 |
||||
# of the License, or (at your option) any later version. |
||||
# |
||||
# This program is distributed in the hope that it will be useful, |
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
# GNU General Public License for more details. |
||||
# |
||||
# You should have received a copy of the GNU General Public License |
||||
# along with this program; if not, write to the Free Software |
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
# |
||||
# See doc/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
Feature: Timeline view with filter tests |
||||
As an openproject user |
||||
I want to view filtered timelines |
||||
|
||||
Background: |
||||
Given there is 1 user with: |
||||
| login | manager | |
||||
|
||||
And there is a role "manager" |
||||
And the role "manager" may have the following rights: |
||||
| view_timelines | |
||||
| edit_timelines | |
||||
| view_work_packages | |
||||
|
||||
And there are the following project types: |
||||
| Name | |
||||
| Pilot | |
||||
|
||||
And there is a project named "Space Pilot 3000" of type "Pilot" |
||||
And I am working in project "Space Pilot 3000" |
||||
And the project uses the following modules: |
||||
| timelines | |
||||
|
||||
And the user "manager" is a "manager" |
||||
And I am already logged in as "manager" |
||||
And there are the following types: |
||||
| Name | Is Milestone | In aggregation | |
||||
| Phase | false | true | |
||||
| Milestone | true | true | |
||||
|
||||
And the following types are enabled for projects of type "Pilot" |
||||
| Phase | |
||||
| Milestone | |
||||
And there is a timeline "Storyboard" for project "Space Pilot 3000" |
||||
|
||||
|
||||
@javascript |
||||
Scenario: The timeline w/o filters renders properly |
||||
Given there are the following work packages in project "Space Pilot 3000": |
||||
| Subject | Start date | Due date | type | parent | |
||||
| Mission to the moon | 3000-01-02 | 3000-01-03 | Phase | | |
||||
| Mom captures Nibblonians | 3000-04-01 | 3000-04-13 | Phase | | |
||||
|
||||
When I go to the page of the timeline of the project called "Space Pilot 3000" |
||||
And I wait for timeline to load table |
||||
Then I should see the work package "Mission to the moon" in the timeline |
||||
And I should see the work package "Mom captures Nibblonians" in the timeline |
||||
|
||||
@javascript |
||||
Scenario: The timeline w/o filters renders properly |
||||
Given there are the following work packages in project "Space Pilot 3000": |
||||
| Subject | Start date | Due date | type | parent | |
||||
| Hubert Farnsworth's Birthday | 2841-04-09 | 2841-04-09 | Milestone | | |
||||
| Unrelated | 3000-01-01 | 3000-01-05 | Phase | | |
||||
| Mission to the moon | 3000-01-02 | 3000-01-02 | Milestone | Unrelated | |
||||
And I am working in the timeline "Storyboard" of the project called "Space Pilot 3000" |
||||
When I go to the page of the timeline of the project called "Space Pilot 3000" |
||||
And I show only work packages which have the type "Milestone" |
||||
And I wait for timeline to load table |
||||
Then I should see the work package "Hubert Farnsworth's Birthday" in the timeline |
||||
And I should see the work package "Mission to the moon" in the timeline |
||||
And I should not see the work package "Unrelated" in the timeline |
@ -0,0 +1,131 @@ |
||||
#-- copyright |
||||
# OpenProject is a project management system. |
||||
# Copyright (C) 2012-2013 the OpenProject Foundation (OPF) |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License version 3. |
||||
# |
||||
# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: |
||||
# Copyright (C) 2006-2013 Jean-Philippe Lang |
||||
# Copyright (C) 2010-2013 the ChiliProject Team |
||||
# |
||||
# This program is free software; you can redistribute it and/or |
||||
# modify it under the terms of the GNU General Public License |
||||
# as published by the Free Software Foundation; either version 2 |
||||
# of the License, or (at your option) any later version. |
||||
# |
||||
# This program is distributed in the hope that it will be useful, |
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
# GNU General Public License for more details. |
||||
# |
||||
# You should have received a copy of the GNU General Public License |
||||
# along with this program; if not, write to the Free Software |
||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
||||
# |
||||
# See doc/COPYRIGHT.rdoc for more details. |
||||
#++ |
||||
|
||||
require File.expand_path('../../../../spec_helper', __FILE__) |
||||
|
||||
describe Api::V2::StatusesController do |
||||
|
||||
let(:valid_user) { FactoryGirl.create(:user) } |
||||
let(:status) {FactoryGirl.create(:issue_status)} |
||||
|
||||
before do |
||||
User.stub(:current).and_return valid_user |
||||
end |
||||
|
||||
describe 'authentication of index' do |
||||
def fetch |
||||
get 'index', :format => 'json' |
||||
end |
||||
it_should_behave_like "a controller action with require_login" |
||||
end |
||||
|
||||
describe 'authentication of show' do |
||||
def fetch |
||||
get 'show', :format => 'json', :id => status.id |
||||
end |
||||
it_should_behave_like "a controller action with require_login" |
||||
end |
||||
|
||||
describe 'looking up a singular status' do |
||||
let(:closed){FactoryGirl.create(:issue_status, name: "Closed")} |
||||
|
||||
it 'that does not exist should raise an error' do |
||||
get 'show', :id => '0', :format => 'json' |
||||
response.response_code.should == 404 |
||||
end |
||||
it 'that exists should return the proper status' do |
||||
get 'show', :id => closed.id, :format => 'json' |
||||
expect(assigns(:status)).to eql closed |
||||
end |
||||
|
||||
end |
||||
|
||||
describe 'looking up statuses' do |
||||
|
||||
let(:open) {FactoryGirl.create(:issue_status, name: "Open")} |
||||
let(:in_progress) {FactoryGirl.create(:issue_status, name: "In Progress")} |
||||
let(:closed){FactoryGirl.create(:issue_status, name: "Closed")} |
||||
let(:no_see_status){FactoryGirl.create(:issue_status, name: "You don't see me.")} |
||||
|
||||
let(:workflows) do |
||||
workflows = [FactoryGirl.create(:workflow, old_status: open, new_status: in_progress, role: role), |
||||
FactoryGirl.create(:workflow, old_status: in_progress, new_status: closed, role: role)] |
||||
end |
||||
|
||||
let(:no_see_workflows) do |
||||
workflows = [FactoryGirl.create(:workflow, old_status: closed, new_status: no_see_status, role: role)] |
||||
end |
||||
|
||||
let(:project) do |
||||
type = FactoryGirl.create(:type, name: "Standard", workflows: workflows) |
||||
project = FactoryGirl.create(:project, types: [type]) |
||||
end |
||||
let(:invisible_project) do |
||||
invisible_type = FactoryGirl.create(:type, name: "No See", workflows: no_see_workflows) |
||||
project = FactoryGirl.create(:project, types: [invisible_type], is_public: false) |
||||
end |
||||
|
||||
let(:role) { FactoryGirl.create(:role) } |
||||
let(:member) { FactoryGirl.create(:member, :project => project, |
||||
:user => valid_user, |
||||
:roles => [role]) } |
||||
|
||||
|
||||
before do |
||||
member |
||||
workflows |
||||
end |
||||
|
||||
describe 'with project-scope' do |
||||
it 'with unknown project raises ActiveRecord::RecordNotFound errors' do |
||||
get 'index', :project_id => '0', :format => 'json' |
||||
expect(response.response_code).to eql 404 |
||||
end |
||||
|
||||
it "should return the available statuses _only_ for the given project" do |
||||
get 'index', :project_id => project.id, :format => 'json' |
||||
expect(assigns(:statuses)).to include open, in_progress, closed |
||||
expect(assigns(:statuses)).not_to include no_see_status |
||||
end |
||||
|
||||
end |
||||
|
||||
describe 'without project-scope' do |
||||
it "should return only status for visible projects" do |
||||
# create the invisible type/workflow/status |
||||
invisible_project |
||||
get 'index', :format => 'json' |
||||
|
||||
expect(assigns(:statuses)).to include open, in_progress, closed |
||||
expect(assigns(:statuses)).not_to include no_see_status |
||||
end |
||||
end |
||||
end |
||||
|
||||
end |
||||
|
Loading…
Reference in new issue