Add 'apps/arv-web/' from commit 'f9732ad8460d013c2f28363655d0d1b91894dca5'
[arvados.git] / apps / workbench / test / controllers / projects_controller_test.rb
1 require 'test_helper'
2
3 class ProjectsControllerTest < ActionController::TestCase
4   test "invited user is asked to sign user agreements on front page" do
5     get :index, {}, session_for(:inactive)
6     assert_response :redirect
7     assert_match(/^#{Regexp.escape(user_agreements_url)}\b/,
8                  @response.redirect_url,
9                  "Inactive user was not redirected to user_agreements page")
10   end
11
12   test "uninvited user is asked to wait for activation" do
13     get :index, {}, session_for(:inactive_uninvited)
14     assert_response :redirect
15     assert_match(/^#{Regexp.escape(inactive_users_url)}\b/,
16                  @response.redirect_url,
17                  "Uninvited user was not redirected to inactive user page")
18   end
19
20   [[:active, true],
21    [:project_viewer, false]].each do |which_user, should_show|
22     test "create subproject button #{'not ' unless should_show} shown to #{which_user}" do
23       readonly_project_uuid = api_fixture('groups')['aproject']['uuid']
24       get :show, {
25         id: readonly_project_uuid
26       }, session_for(which_user)
27       buttons = css_select('[data-method=post]').select do |el|
28         el.attributes['href'].match /project.*owner_uuid.*#{readonly_project_uuid}/
29       end
30       if should_show
31         assert_not_empty(buttons, "did not offer to create a subproject")
32       else
33         assert_empty(buttons.collect(&:to_s),
34                      "offered to create a subproject in a non-writable project")
35       end
36     end
37   end
38
39   test "sharing a project with a user and group" do
40     uuid_list = [api_fixture("groups")["future_project_viewing_group"]["uuid"],
41                  api_fixture("users")["future_project_user"]["uuid"]]
42     post(:share_with, {
43            id: api_fixture("groups")["asubproject"]["uuid"],
44            uuids: uuid_list,
45            format: "json"},
46          session_for(:active))
47     assert_response :success
48     assert_equal(uuid_list, json_response["success"])
49   end
50
51   test "user with project read permission can't add permissions" do
52     share_uuid = api_fixture("users")["spectator"]["uuid"]
53     post(:share_with, {
54            id: api_fixture("groups")["aproject"]["uuid"],
55            uuids: [share_uuid],
56            format: "json"},
57          session_for(:project_viewer))
58     assert_response 422
59     assert(json_response["errors"].andand.
60              any? { |msg| msg.start_with?("#{share_uuid}: ") },
61            "JSON response missing properly formatted sharing error")
62   end
63
64   def user_can_manage(user_sym, group_key)
65     get(:show, {id: api_fixture("groups")[group_key]["uuid"]},
66         session_for(user_sym))
67     is_manager = assigns(:user_is_manager)
68     assert_not_nil(is_manager, "user_is_manager flag not set")
69     if not is_manager
70       assert_empty(assigns(:share_links),
71                    "non-manager has share links set")
72     end
73     is_manager
74   end
75
76   test "admin can_manage aproject" do
77     assert user_can_manage(:admin, "aproject")
78   end
79
80   test "owner can_manage aproject" do
81     assert user_can_manage(:active, "aproject")
82   end
83
84   test "owner can_manage asubproject" do
85     assert user_can_manage(:active, "asubproject")
86   end
87
88   test "viewer can't manage aproject" do
89     refute user_can_manage(:project_viewer, "aproject")
90   end
91
92   test "viewer can't manage asubproject" do
93     refute user_can_manage(:project_viewer, "asubproject")
94   end
95
96   test "subproject_admin can_manage asubproject" do
97     assert user_can_manage(:subproject_admin, "asubproject")
98   end
99
100   test "detect ownership loop in project breadcrumbs" do
101     # This test has an arbitrary time limit -- otherwise we'd just sit
102     # here forever instead of reporting that the loop was not
103     # detected. The test passes quickly, but fails slowly.
104     Timeout::timeout 10 do
105       get(:show,
106           { id: api_fixture("groups")["project_owns_itself"]["uuid"] },
107           session_for(:admin))
108     end
109     assert_response :success
110   end
111
112   test "project admin can remove items from the project" do
113     coll_key = "collection_to_remove_from_subproject"
114     coll_uuid = api_fixture("collections")[coll_key]["uuid"]
115     delete(:remove_item,
116            { id: api_fixture("groups")["asubproject"]["uuid"],
117              item_uuid: coll_uuid,
118              format: "js" },
119            session_for(:subproject_admin))
120     assert_response :success
121     assert_match(/\b#{coll_uuid}\b/, @response.body,
122                  "removed object not named in response")
123   end
124
125   test 'projects#show tab infinite scroll partial obeys limit' do
126     get_contents_rows(limit: 1, filters: [['uuid','is_a',['arvados#job']]])
127     assert_response :success
128     assert_equal(1, json_response['content'].scan('<tr').count,
129                  "Did not get exactly one row")
130   end
131
132   ['', ' asc', ' desc'].each do |direction|
133     test "projects#show tab partial orders correctly by #{direction}" do
134       _test_tab_content_order direction
135     end
136   end
137
138   def _test_tab_content_order direction
139     get_contents_rows(limit: 100,
140                       order: "created_at#{direction}",
141                       filters: [['uuid','is_a',['arvados#job',
142                                                 'arvados#pipelineInstance']]])
143     assert_response :success
144     not_grouped_by_kind = nil
145     last_timestamp = nil
146     last_kind = nil
147     found_kind = {}
148     json_response['content'].scan /<tr[^>]+>/ do |tr_tag|
149       found_timestamps = 0
150       tr_tag.scan(/\ data-object-created-at=\"(.*?)\"/).each do |t,|
151         if last_timestamp
152           correct_operator = / desc$/ =~ direction ? :>= : :<=
153           assert_operator(last_timestamp, correct_operator, t,
154                           "Rows are not sorted by created_at#{direction}")
155         end
156         last_timestamp = t
157         found_timestamps += 1
158       end
159       assert_equal(1, found_timestamps,
160                    "Content row did not have exactly one timestamp")
161
162       # Confirm that the test for timestamp ordering couldn't have
163       # passed merely because the test fixtures have convenient
164       # timestamps (e.g., there is only one pipeline and one job in
165       # the project being tested, or there are no pipelines at all in
166       # the project being tested):
167       tr_tag.scan /\ data-kind=\"(.*?)\"/ do |kind|
168         if last_kind and last_kind != kind and found_kind[kind]
169           # We saw this kind before, then a different kind, then
170           # this kind again. That means objects are not grouped by
171           # kind.
172           not_grouped_by_kind = true
173         end
174         found_kind[kind] ||= 0
175         found_kind[kind] += 1
176         last_kind = kind
177       end
178     end
179     assert_equal(true, not_grouped_by_kind,
180                  "Could not confirm that results are not grouped by kind")
181   end
182
183   def get_contents_rows params
184     params = {
185       id: api_fixture('users')['active']['uuid'],
186       partial: :contents_rows,
187       format: :json,
188     }.merge(params)
189     encoded_params = Hash[params.map { |k,v|
190                             [k, (v.is_a?(Array) || v.is_a?(Hash)) ? v.to_json : v]
191                           }]
192     get :show, encoded_params, session_for(:active)
193   end
194 end