Merge branch '3531-sort-jobs-with-pipelines' closes #3531
[arvados.git] / apps / workbench / test / functional / projects_controller_test.rb
1 require 'test_helper'
2
3 class ProjectsControllerTest < ActionController::TestCase
4   test "inactive user is asked to sign user agreements on front page" do
5     get :index, {}, session_for(:inactive)
6     assert_response :success
7     assert_not_empty assigns(:required_user_agreements),
8     "Inactive user did not have required_user_agreements"
9     assert_template 'user_agreements/index',
10     "Inactive user was not presented with a user agreement at the front page"
11   end
12
13   [[:active, true],
14    [:project_viewer, false]].each do |which_user, should_show|
15     test "create subproject button #{'not ' unless should_show} shown to #{which_user}" do
16       readonly_project_uuid = api_fixture('groups')['aproject']['uuid']
17       get :show, {
18         id: readonly_project_uuid
19       }, session_for(which_user)
20       buttons = css_select('[data-method=post]').select do |el|
21         el.attributes['href'].match /project.*owner_uuid.*#{readonly_project_uuid}/
22       end
23       if should_show
24         assert_not_empty(buttons, "did not offer to create a subproject")
25       else
26         assert_empty(buttons.collect(&:to_s),
27                      "offered to create a subproject in a non-writable project")
28       end
29     end
30   end
31
32   test "sharing a project with a user and group" do
33     uuid_list = [api_fixture("groups")["future_project_viewing_group"]["uuid"],
34                  api_fixture("users")["future_project_user"]["uuid"]]
35     post(:share_with, {
36            id: api_fixture("groups")["asubproject"]["uuid"],
37            uuids: uuid_list,
38            format: "json"},
39          session_for(:active))
40     assert_response :success
41     assert_equal(uuid_list, json_response["success"])
42   end
43
44   test "user with project read permission can't add permissions" do
45     share_uuid = api_fixture("users")["spectator"]["uuid"]
46     post(:share_with, {
47            id: api_fixture("groups")["aproject"]["uuid"],
48            uuids: [share_uuid],
49            format: "json"},
50          session_for(:project_viewer))
51     assert_response 422
52     assert(json_response["errors"].andand.
53              any? { |msg| msg.start_with?("#{share_uuid}: ") },
54            "JSON response missing properly formatted sharing error")
55   end
56
57   def user_can_manage(user_sym, group_key)
58     get(:show, {id: api_fixture("groups")[group_key]["uuid"]},
59         session_for(user_sym))
60     is_manager = assigns(:user_is_manager)
61     assert_not_nil(is_manager, "user_is_manager flag not set")
62     if not is_manager
63       assert_empty(assigns(:share_links),
64                    "non-manager has share links set")
65     end
66     is_manager
67   end
68
69   test "admin can_manage aproject" do
70     assert user_can_manage(:admin, "aproject")
71   end
72
73   test "owner can_manage aproject" do
74     assert user_can_manage(:active, "aproject")
75   end
76
77   test "owner can_manage asubproject" do
78     assert user_can_manage(:active, "asubproject")
79   end
80
81   test "viewer can't manage aproject" do
82     refute user_can_manage(:project_viewer, "aproject")
83   end
84
85   test "viewer can't manage asubproject" do
86     refute user_can_manage(:project_viewer, "asubproject")
87   end
88
89   test 'projects#show tab infinite scroll partial obeys limit' do
90     get_contents_rows(limit: 1, filters: [['uuid','is_a',['arvados#job']]])
91     assert_response :success
92     assert_equal(1, json_response['content'].scan('<tr').count,
93                  "Did not get exactly one row")
94   end
95
96   ['', ' asc', ' desc'].each do |direction|
97     test "projects#show tab partial orders correctly by #{direction}" do
98       _test_tab_content_order direction
99     end
100   end
101
102   def _test_tab_content_order direction
103     get_contents_rows(limit: 100,
104                       order: "created_at#{direction}",
105                       filters: [['uuid','is_a',['arvados#job',
106                                                 'arvados#pipelineInstance']]])
107     assert_response :success
108     not_grouped_by_kind = nil
109     last_timestamp = nil
110     last_kind = nil
111     found_kind = {}
112     json_response['content'].scan /<tr[^>]+>/ do |tr_tag|
113       found_timestamps = 0
114       tr_tag.scan(/\ data-object-created-at=\"(.*?)\"/).each do |t,|
115         if last_timestamp
116           correct_operator = / desc$/ =~ direction ? :>= : :<=
117           assert_operator(last_timestamp, correct_operator, t,
118                           "Rows are not sorted by created_at#{direction}")
119         end
120         last_timestamp = t
121         found_timestamps += 1
122       end
123       assert_equal(1, found_timestamps,
124                    "Content row did not have exactly one timestamp")
125
126       # Confirm that the test for timestamp ordering couldn't have
127       # passed merely because the test fixtures have convenient
128       # timestamps (e.g., there is only one pipeline and one job in
129       # the project being tested, or there are no pipelines at all in
130       # the project being tested):
131       tr_tag.scan /\ data-kind=\"(.*?)\"/ do |kind|
132         if last_kind and last_kind != kind and found_kind[kind]
133           # We saw this kind before, then a different kind, then
134           # this kind again. That means objects are not grouped by
135           # kind.
136           not_grouped_by_kind = true
137         end
138         found_kind[kind] ||= 0
139         found_kind[kind] += 1
140         last_kind = kind
141       end
142     end
143     assert_equal(true, not_grouped_by_kind,
144                  "Could not confirm that results are not grouped by kind")
145   end
146
147   def get_contents_rows params
148     params = {
149       id: api_fixture('users')['active']['uuid'],
150       partial: :contents_rows,
151       format: :json,
152     }.merge(params)
153     encoded_params = Hash[params.map { |k,v|
154                             [k, (v.is_a?(Array) || v.is_a?(Hash)) ? v.to_json : v]
155                           }]
156     get :show, encoded_params, session_for(:active)
157   end
158 end