marty 0.5.39 → 0.5.40
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +3 -0
- data/app/controllers/marty/diagnostic_controller.rb +2 -2
- data/lib/marty/version.rb +1 -1
- data/spec/features/auth_app_spec.rb +4 -4
- data/spec/features/data_import_spec.rb +13 -9
- data/spec/features/reporting_spec.rb +28 -20
- data/spec/features/scripting_spec.rb +66 -47
- data/spec/features/scripting_test_spec.rb +18 -12
- data/spec/features/user_view_spec.rb +34 -32
- data/spec/spec_helper.rb +3 -0
- data/spec/support/integration_helpers.rb +0 -590
- metadata +1 -1
@@ -92,18 +92,18 @@ DELOREAN
|
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
95
|
-
let(:tg) { gridpanel('tag_grid') }
|
96
|
-
let(:sg) { gridpanel('script_grid') }
|
97
|
-
|
98
95
|
it 'switches between tags & scripts, computes values and checks for errors' do
|
99
96
|
log_in_as('dev1')
|
100
97
|
go_to_scripting
|
101
98
|
|
99
|
+
tag_grid = netzke_find('tag_grid')
|
100
|
+
script_grid = netzke_find('script_grid')
|
101
|
+
|
102
102
|
by 'select M1 sample script' do
|
103
103
|
wait_for_ajax
|
104
|
-
zoom_out
|
105
|
-
select_row(2
|
106
|
-
select_row(1
|
104
|
+
zoom_out
|
105
|
+
tag_grid.select_row(2)
|
106
|
+
script_grid.select_row(1)
|
107
107
|
tab_press('Testing')
|
108
108
|
end
|
109
109
|
|
@@ -155,8 +155,8 @@ DELOREAN
|
|
155
155
|
tab_press('Selection')
|
156
156
|
wait_for_ajax
|
157
157
|
find(:gridpanel, 'script_grid', match: :first, wait: 10)
|
158
|
-
select_row(1
|
159
|
-
select_row(1
|
158
|
+
tag_grid.select_row(1)
|
159
|
+
script_grid.select_row(1)
|
160
160
|
tab_press('Testing')
|
161
161
|
end
|
162
162
|
|
@@ -187,7 +187,7 @@ DELOREAN
|
|
187
187
|
and_by 'select M2 sample grid' do
|
188
188
|
tab_press('Selection')
|
189
189
|
wait_for_ajax
|
190
|
-
select_row(2
|
190
|
+
script_grid.select_row(2)
|
191
191
|
tab_press('Testing')
|
192
192
|
end
|
193
193
|
|
@@ -209,9 +209,12 @@ DELOREAN
|
|
209
209
|
log_in_as('dev1')
|
210
210
|
go_to_scripting
|
211
211
|
|
212
|
+
tag_grid = netzke_find('tag_grid')
|
213
|
+
script_grid = netzke_find('script_grid')
|
214
|
+
|
212
215
|
by 'select M1 sample script' do
|
213
216
|
wait_for_ajax
|
214
|
-
select_row(1
|
217
|
+
script_grid.select_row(1)
|
215
218
|
tab_press('Testing')
|
216
219
|
end
|
217
220
|
|
@@ -271,10 +274,13 @@ DELOREAN
|
|
271
274
|
log_in_as('dev1')
|
272
275
|
go_to_scripting
|
273
276
|
|
277
|
+
tag_grid = netzke_find('tag_grid')
|
278
|
+
script_grid = netzke_find('script_grid')
|
279
|
+
|
274
280
|
by 'select M3 sample script' do
|
275
281
|
wait_for_ajax
|
276
|
-
zoom_out
|
277
|
-
select_row(3
|
282
|
+
zoom_out
|
283
|
+
script_grid.select_row(3)
|
278
284
|
tab_press('Testing')
|
279
285
|
end
|
280
286
|
|
@@ -35,15 +35,15 @@ feature 'under Sytem menu, User Management worflows', js: true do
|
|
35
35
|
check(name, false)
|
36
36
|
end
|
37
37
|
|
38
|
-
let(:uv) { gridpanel('user_view') }
|
39
|
-
|
40
38
|
it 'marty user can add/edit but not delete users' do
|
41
39
|
log_in_as('marty')
|
42
40
|
go_to_user_view
|
43
41
|
|
42
|
+
user_view = netzke_find('user_view')
|
43
|
+
|
44
44
|
by 'add new user' do
|
45
45
|
wait_for_ajax
|
46
|
-
zoom_out
|
46
|
+
zoom_out
|
47
47
|
press('New User')
|
48
48
|
within(:gridpanel, 'add_window', match: :first) do
|
49
49
|
press 'OK'
|
@@ -64,8 +64,8 @@ feature 'under Sytem menu, User Management worflows', js: true do
|
|
64
64
|
|
65
65
|
and_by 'edit the added user' do
|
66
66
|
wait_for_ajax
|
67
|
-
expect(row_count
|
68
|
-
select_row(2
|
67
|
+
expect(user_view.row_count).to eq 2
|
68
|
+
user_view.select_row(2)
|
69
69
|
press('Edit in form')
|
70
70
|
|
71
71
|
within(:gridpanel, 'edit_window', match: :first) do
|
@@ -80,27 +80,27 @@ feature 'under Sytem menu, User Management worflows', js: true do
|
|
80
80
|
|
81
81
|
and_by 'check row got edited' do
|
82
82
|
wait_for_ajax
|
83
|
-
validate_row_values(2,
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
83
|
+
user_view.validate_row_values(2,
|
84
|
+
:login => 'new_login',
|
85
|
+
:firstname => 'new_fname',
|
86
|
+
:lastname => 'new_lname',
|
87
|
+
:active => true,
|
88
|
+
:roles => 'User Manager,Viewer')
|
89
89
|
end
|
90
90
|
|
91
91
|
and_by 'delete user fails' do
|
92
|
-
select_row(2
|
92
|
+
user_view.select_row(2)
|
93
93
|
press("Delete")
|
94
94
|
press("Yes")
|
95
95
|
expect(find(:msg)).to have_content("Users cannot be deleted - set " +
|
96
96
|
"'Active' to false to disable the " +
|
97
97
|
"account")
|
98
|
-
select_row(1
|
98
|
+
user_view.select_row(1)
|
99
99
|
press("Delete")
|
100
100
|
press("Yes")
|
101
101
|
expect(find(:msg)).to have_content("You cannot delete your own account")
|
102
102
|
|
103
|
-
expect(row_count
|
103
|
+
expect(user_view.row_count).to eq 2
|
104
104
|
end
|
105
105
|
end
|
106
106
|
|
@@ -115,49 +115,51 @@ feature 'under Sytem menu, User Management worflows', js: true do
|
|
115
115
|
go_to_user_view
|
116
116
|
by 'check buttons' do
|
117
117
|
find(:btn, 'New User', match: :first)
|
118
|
-
zoom_out
|
119
|
-
expect(btn_disabled?('New User'
|
120
|
-
expect(btn_disabled?('Edit in form'
|
121
|
-
expect(btn_disabled?('Delete'
|
118
|
+
zoom_out
|
119
|
+
expect(btn_disabled?('New User')).to be_falsy
|
120
|
+
expect(btn_disabled?('Edit in form')).to be_falsy
|
121
|
+
expect(btn_disabled?('Delete')).to be_falsy
|
122
122
|
end
|
123
123
|
end
|
124
124
|
|
125
125
|
it 'admin has access' do
|
126
126
|
log_in_as('admin1')
|
127
127
|
go_to_user_view
|
128
|
-
|
128
|
+
by 'check buttons' do
|
129
129
|
find(:btn, 'New User', match: :first)
|
130
|
-
expect(btn_disabled?('New User'
|
131
|
-
expect(btn_disabled?('Edit in form'
|
132
|
-
expect(btn_disabled?('Delete'
|
130
|
+
expect(btn_disabled?('New User')).to be_falsy
|
131
|
+
expect(btn_disabled?('Edit in form')).to be_falsy
|
132
|
+
expect(btn_disabled?('Delete')).to be_falsy
|
133
133
|
end
|
134
134
|
end
|
135
135
|
|
136
136
|
it 'viewer denied access' do
|
137
137
|
log_in_as('viewer1')
|
138
138
|
go_to_user_view_backdoor
|
139
|
-
|
139
|
+
user_view = netzke_find('user_view')
|
140
|
+
by 'check buttons' do
|
140
141
|
find(:btn, 'New User', match: :first)
|
141
142
|
#selection needed to make delete button disappear
|
142
143
|
wait_for_ajax
|
143
|
-
select_row(1
|
144
|
-
expect(btn_disabled?('New User'
|
145
|
-
expect(btn_disabled?('Edit in form'
|
146
|
-
expect(btn_disabled?('Delete'
|
144
|
+
user_view.select_row(1)
|
145
|
+
expect(btn_disabled?('New User')).to be_truthy
|
146
|
+
expect(btn_disabled?('Edit in form')).to be_truthy
|
147
|
+
expect(btn_disabled?('Delete')).to be_truthy
|
147
148
|
end
|
148
149
|
end
|
149
150
|
|
150
151
|
it 'developer denied access' do
|
151
152
|
log_in_as('dev1')
|
152
153
|
go_to_user_view_backdoor
|
153
|
-
|
154
|
+
user_view = netzke_find('user_view')
|
155
|
+
by 'check buttons' do
|
154
156
|
find(:btn, 'New User', match: :first)
|
155
157
|
#selection needed to make delete button disappear
|
156
158
|
wait_for_ajax
|
157
|
-
select_row(1
|
158
|
-
expect(btn_disabled?('New User'
|
159
|
-
expect(btn_disabled?('Edit in form'
|
160
|
-
expect(btn_disabled?('Delete'
|
159
|
+
user_view.select_row(1)
|
160
|
+
expect(btn_disabled?('New User')).to be_truthy
|
161
|
+
expect(btn_disabled?('Edit in form')).to be_truthy
|
162
|
+
expect(btn_disabled?('Delete')).to be_truthy
|
161
163
|
end
|
162
164
|
end
|
163
165
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -3,6 +3,7 @@ ENV["RAILS_ENV"] ||= "test"
|
|
3
3
|
require 'dummy/config/application'
|
4
4
|
require 'rspec/rails'
|
5
5
|
require 'database_cleaner'
|
6
|
+
require 'marty_rspec'
|
6
7
|
|
7
8
|
Dummy::Application.initialize!
|
8
9
|
|
@@ -35,6 +36,8 @@ RSpec.configure do |config|
|
|
35
36
|
config.include CleanDbHelpers
|
36
37
|
config.include SpecSetup
|
37
38
|
config.include Marty::IntegrationHelpers
|
39
|
+
config.include MartyRSpec::Util
|
40
|
+
config.include MartyRSpec::NetzkeGrid
|
38
41
|
|
39
42
|
Capybara.default_max_wait_time = 3
|
40
43
|
|
@@ -1,33 +1,4 @@
|
|
1
1
|
module Marty::IntegrationHelpers
|
2
|
-
|
3
|
-
MAX_WAIT_TIME = 5.0
|
4
|
-
|
5
|
-
# without rspec-by gem, essentially works as documentation & wait
|
6
|
-
def by message, level=0
|
7
|
-
wait_for_ready(10)
|
8
|
-
pending(message) unless block_given?
|
9
|
-
begin
|
10
|
-
by_start(message)
|
11
|
-
yield
|
12
|
-
ensure
|
13
|
-
by_end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
alias and_by by
|
18
|
-
|
19
|
-
def by_start message
|
20
|
-
if RSpec.configuration.reporter.respond_to? :by_started
|
21
|
-
RSpec.configuration.reporter.by_started(message)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def by_end
|
26
|
-
if RSpec.configuration.reporter.respond_to? :by_ended
|
27
|
-
RSpec.configuration.reporter.by_ended()
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
2
|
# test setup helpers
|
32
3
|
def populate_test_users
|
33
4
|
(1..2).each { |i|
|
@@ -59,27 +30,6 @@ module Marty::IntegrationHelpers
|
|
59
30
|
user.save
|
60
31
|
end
|
61
32
|
|
62
|
-
# navigation helpers
|
63
|
-
def ensure_on(path)
|
64
|
-
visit(path) unless current_path == path
|
65
|
-
end
|
66
|
-
|
67
|
-
def log_in(username, password)
|
68
|
-
wait_for_ready(10)
|
69
|
-
|
70
|
-
if first("a[data-qtip='Current user']")
|
71
|
-
log_out
|
72
|
-
wait_for_ajax
|
73
|
-
end
|
74
|
-
|
75
|
-
find(:xpath, "//span", text: 'Sign in', match: :first, wait: 5).click
|
76
|
-
find(:xpath, "//span", text: 'Password', match: :first, wait: 5)
|
77
|
-
fill_in("login", :with => username)
|
78
|
-
fill_in("password", :with => password)
|
79
|
-
press("OK")
|
80
|
-
wait_for_ajax
|
81
|
-
end
|
82
|
-
|
83
33
|
def log_in_as(username)
|
84
34
|
Rails.configuration.marty.auth_source = 'local'
|
85
35
|
|
@@ -87,544 +37,4 @@ module Marty::IntegrationHelpers
|
|
87
37
|
log_in(username, Rails.configuration.marty.local_password)
|
88
38
|
ensure_on("/")
|
89
39
|
end
|
90
|
-
|
91
|
-
def log_out
|
92
|
-
press("Current user")
|
93
|
-
press("Sign out")
|
94
|
-
end
|
95
|
-
|
96
|
-
def press button_name, index_of = 0
|
97
|
-
wait_for_element do
|
98
|
-
begin
|
99
|
-
cmp = first("a[data-qtip='#{button_name}']")
|
100
|
-
cmp ||= first(:xpath, ".//a", text: "#{button_name}")
|
101
|
-
cmp ||= find(:btn, button_name, match: :first)
|
102
|
-
cmp.click
|
103
|
-
true
|
104
|
-
rescue
|
105
|
-
find_by_id(ext_button_id(button_name, index_of), visible: :all).click
|
106
|
-
true
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
def popup message = ''
|
112
|
-
by_start('popup: ' + message)
|
113
|
-
wait_for_ready
|
114
|
-
yield if block_given?
|
115
|
-
close_window
|
116
|
-
by_end
|
117
|
-
end
|
118
|
-
|
119
|
-
def close_window
|
120
|
-
find(:xpath, '//img[contains(@class, "x-tool-close")]', wait: 5).click
|
121
|
-
end
|
122
|
-
|
123
|
-
def wait_for_ready wait_time = nil
|
124
|
-
if wait_time
|
125
|
-
find(:status, 'Ready', wait: wait_time)
|
126
|
-
else
|
127
|
-
find(:status, 'Ready')
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
def wait_for_ajax
|
132
|
-
wait_for_ready(10)
|
133
|
-
wait_for_element { !ajax_loading? }
|
134
|
-
wait_for_ready
|
135
|
-
end
|
136
|
-
|
137
|
-
def ajax_loading?
|
138
|
-
page.execute_script <<-JS
|
139
|
-
return Netzke.ajaxIsLoading() || Ext.Ajax.isLoading();
|
140
|
-
JS
|
141
|
-
end
|
142
|
-
|
143
|
-
def zoom_out component
|
144
|
-
wait_for_element do
|
145
|
-
el_id = id_of(component)
|
146
|
-
el = find_by_id(el_id)
|
147
|
-
el.native.send_keys([:control, '0'])
|
148
|
-
el.native.send_keys([:control, '-'])
|
149
|
-
el.native.send_keys([:control, '-'])
|
150
|
-
el.native.send_keys([:control, '-'])
|
151
|
-
end
|
152
|
-
end
|
153
|
-
|
154
|
-
def wait_for_element(seconds_to_wait = 2.0, sleeptime = 0.1)
|
155
|
-
res = nil
|
156
|
-
start_time = current_time = Time.now
|
157
|
-
while !res && current_time - start_time < seconds_to_wait
|
158
|
-
begin
|
159
|
-
res = yield
|
160
|
-
rescue
|
161
|
-
ensure
|
162
|
-
sleep sleeptime
|
163
|
-
current_time = Time.now
|
164
|
-
end
|
165
|
-
end
|
166
|
-
res
|
167
|
-
end
|
168
|
-
|
169
|
-
def run_js js_str, seconds_to_wait = MAX_WAIT_TIME, sleeptime = 0.1
|
170
|
-
result = wait_for_element(seconds_to_wait, sleeptime) do
|
171
|
-
res = nil
|
172
|
-
page.document.synchronize { res = page.execute_script(js_str) }
|
173
|
-
res.nil? ? true : res
|
174
|
-
end
|
175
|
-
result
|
176
|
-
end
|
177
|
-
|
178
|
-
# Component helpers
|
179
|
-
def show_submenu text
|
180
|
-
run_js <<-JS
|
181
|
-
Ext.ComponentQuery.query('menuitem[text="#{text}"] menu')[0].show()
|
182
|
-
JS
|
183
|
-
end
|
184
|
-
|
185
|
-
def ext_button_id title, scope = nil, index_of = 0
|
186
|
-
c_str = ext_arg('button{isVisible(true)}', text: "\"#{title}\"")
|
187
|
-
run_js <<-JS
|
188
|
-
return #{ext_find(c_str, scope, index_of)}.id;
|
189
|
-
JS
|
190
|
-
end
|
191
|
-
|
192
|
-
def set_field_value value, field_type='textfield', name=''
|
193
|
-
args1 = name.empty? ? "" : "[fieldLabel='#{name}']"
|
194
|
-
args2 = name.empty? ? "" : "[name='#{name}']"
|
195
|
-
run_js <<-JS
|
196
|
-
var field = Ext.ComponentQuery.query("#{field_type}#{args1}")[0];
|
197
|
-
field = field || Ext.ComponentQuery.query("#{field_type}#{args2}")[0];
|
198
|
-
field.setValue("#{value}");
|
199
|
-
return true;
|
200
|
-
JS
|
201
|
-
end
|
202
|
-
|
203
|
-
def get_total_pages
|
204
|
-
# will get deprecated by Netzke 1.0
|
205
|
-
result = find(:xpath, ".//div[contains(@id, 'tbtext-')]",
|
206
|
-
text: /^of (\d+)$/, match: :first).text
|
207
|
-
result.split(' ')[1].to_i
|
208
|
-
end
|
209
|
-
|
210
|
-
def simple_escape! text
|
211
|
-
text.gsub!(/(\r\n|\n)/, "\\n")
|
212
|
-
text.gsub!(/\t/, "\\t")
|
213
|
-
end
|
214
|
-
|
215
|
-
def paste text, textarea
|
216
|
-
# bit hacky: textarea doesn't like receiving tabs and newlines via fill_in
|
217
|
-
simple_escape!(text)
|
218
|
-
|
219
|
-
find(:xpath, ".//textarea[@name='#{textarea}']")
|
220
|
-
run_js <<-JS
|
221
|
-
#{ext_var(ext_find(ext_arg('textarea', name: textarea)), 'area')}
|
222
|
-
area.setValue("#{text}");
|
223
|
-
JS
|
224
|
-
end
|
225
|
-
|
226
|
-
def btn_disabled? text, grid
|
227
|
-
res = wait_for_element do
|
228
|
-
find_by_id(ext_button_id(text))
|
229
|
-
end
|
230
|
-
!res[:class].match(/disabled/).nil?
|
231
|
-
end
|
232
|
-
|
233
|
-
# Netzke component lookups, arguments for helper methods below
|
234
|
-
# (i.e. component) require JS scripts instead of objects
|
235
|
-
def ext_arg(component, c_args = {})
|
236
|
-
res = component
|
237
|
-
c_args.each do |k, v|
|
238
|
-
res += "[#{k.to_s}=#{v.to_s}]"
|
239
|
-
end
|
240
|
-
res
|
241
|
-
end
|
242
|
-
|
243
|
-
def ext_find(ext_arg_str, scope = nil, index = 0)
|
244
|
-
scope_str = scope.nil? ? '' : ", #{scope}"
|
245
|
-
<<-JS
|
246
|
-
Ext.ComponentQuery.query('#{ext_arg_str}'#{scope_str})[#{index}]
|
247
|
-
JS
|
248
|
-
end
|
249
|
-
|
250
|
-
def ext_var(ext_find_str, var_name='ext_c')
|
251
|
-
<<-JS
|
252
|
-
var #{var_name} = #{ext_find_str};
|
253
|
-
JS
|
254
|
-
end
|
255
|
-
|
256
|
-
def ext_netzkecombo field
|
257
|
-
<<-JS
|
258
|
-
#{ext_find(ext_arg('netzkeremotecombo', name: field))}
|
259
|
-
JS
|
260
|
-
end
|
261
|
-
|
262
|
-
def ext_combo combo_label, c_name='combo'
|
263
|
-
<<-JS
|
264
|
-
#{ext_var(ext_find(ext_arg('combobox', fieldLabel: combo_label)), c_name)}
|
265
|
-
#{c_name} = #{c_name} ||
|
266
|
-
#{ext_find(ext_arg('combobox', name: combo_label))};
|
267
|
-
JS
|
268
|
-
end
|
269
|
-
|
270
|
-
def ext_celleditor(grid_name='grid')
|
271
|
-
<<-JS
|
272
|
-
#{grid_name}.getPlugin('celleditor')
|
273
|
-
JS
|
274
|
-
end
|
275
|
-
|
276
|
-
def ext_row(row, grid_name='grid')
|
277
|
-
<<-JS
|
278
|
-
#{grid_name}.getStore().getAt(#{row})
|
279
|
-
JS
|
280
|
-
end
|
281
|
-
|
282
|
-
def ext_col(col, grid_name='grid')
|
283
|
-
<<-JS
|
284
|
-
#{ext_find(ext_arg('gridcolumn', name: "\"#{col}\""), grid_name)}
|
285
|
-
JS
|
286
|
-
end
|
287
|
-
|
288
|
-
def ext_cell_val(row, col, grid, var_str = 'value')
|
289
|
-
# FOR NETZKE 1.0, use this line for columns
|
290
|
-
# r.get('association_values')['#{col}'] :
|
291
|
-
<<-JS
|
292
|
-
#{ext_var(grid, 'grid')}
|
293
|
-
#{ext_var(ext_col(col, 'grid'), 'col')}
|
294
|
-
#{ext_var(ext_row(row, 'grid'), 'row')}
|
295
|
-
var #{var_str} = col.assoc ?
|
296
|
-
row.get('meta').associationValues['#{col}'] :
|
297
|
-
row.get('#{col}');
|
298
|
-
JS
|
299
|
-
end
|
300
|
-
|
301
|
-
####
|
302
|
-
def gridpanel arg
|
303
|
-
# use these to generate component args for below
|
304
|
-
if /^\d+$/.match(arg)
|
305
|
-
ext_find('gridpanel', nil, arg)
|
306
|
-
else
|
307
|
-
ext_find(ext_arg('gridpanel', name: arg))
|
308
|
-
end
|
309
|
-
end
|
310
|
-
|
311
|
-
def treepanel arg
|
312
|
-
if /^\d+$/.match(arg)
|
313
|
-
ext_find('treepanel', nil, arg)
|
314
|
-
else
|
315
|
-
ext_find(ext_arg('treepanel', name: arg))
|
316
|
-
end
|
317
|
-
end
|
318
|
-
|
319
|
-
# Netzke helper methods
|
320
|
-
# Grid helpers
|
321
|
-
def id_of component
|
322
|
-
res = run_js <<-JS
|
323
|
-
var c = #{component};
|
324
|
-
return c.view.id;
|
325
|
-
JS
|
326
|
-
res
|
327
|
-
end
|
328
|
-
|
329
|
-
def row_count grid
|
330
|
-
res = run_js <<-JS
|
331
|
-
return #{grid}.getStore().getCount();
|
332
|
-
JS
|
333
|
-
res.to_i
|
334
|
-
end
|
335
|
-
|
336
|
-
def row_total grid
|
337
|
-
res = run_js <<-JS
|
338
|
-
return #{grid}.getStore().getTotalCount();
|
339
|
-
JS
|
340
|
-
res.to_i
|
341
|
-
end
|
342
|
-
|
343
|
-
def row_modified_count grid
|
344
|
-
res = run_js <<-JS
|
345
|
-
return #{grid}.getStore().getUpdatedRecords().length;
|
346
|
-
JS
|
347
|
-
res.to_i
|
348
|
-
end
|
349
|
-
|
350
|
-
def data_desc row, grid
|
351
|
-
res = run_js <<-JS
|
352
|
-
var r = #{grid}.getStore().getAt(#{row.to_i-1});
|
353
|
-
return r.data.desc
|
354
|
-
JS
|
355
|
-
res.gsub(/<.*?>/, '')
|
356
|
-
end
|
357
|
-
|
358
|
-
def click_col col, grid
|
359
|
-
run_js <<-JS
|
360
|
-
#{ext_find(ext_arg('gridcolumn', text: col), grid)}.click();
|
361
|
-
JS
|
362
|
-
end
|
363
|
-
|
364
|
-
def col_values(col, grid, cnt, init=0)
|
365
|
-
#does not validate the # of rows
|
366
|
-
run_js <<-JS
|
367
|
-
var result = [];
|
368
|
-
for (var i = #{init}; i < #{init.to_i + cnt.to_i}; i++) {
|
369
|
-
#{ext_cell_val('i', col, grid)}
|
370
|
-
if(value instanceof Date){
|
371
|
-
result.push(value.toISOString().substring(0,value.toISOString().indexOf('T')));
|
372
|
-
} else {
|
373
|
-
result.push(value);
|
374
|
-
};
|
375
|
-
};
|
376
|
-
return result;
|
377
|
-
JS
|
378
|
-
end
|
379
|
-
|
380
|
-
def validate_col_values(col, val, grid, cnt, init=0)
|
381
|
-
run_js <<-JS
|
382
|
-
for (var i = #{init}; i < #{init.to_i + cnt.to_i}; i++) {
|
383
|
-
#{ext_cell_val('i', col, grid)}
|
384
|
-
if (value != #{val}) { return false };
|
385
|
-
};
|
386
|
-
return true;
|
387
|
-
JS
|
388
|
-
end
|
389
|
-
|
390
|
-
def cell_value(row, col, grid)
|
391
|
-
run_js <<-JS
|
392
|
-
#{ext_cell_val(row.to_i - 1, col, grid)}
|
393
|
-
return value;
|
394
|
-
JS
|
395
|
-
end
|
396
|
-
|
397
|
-
def select_row(row, grid, click_after=true)
|
398
|
-
resid = run_js(<<-JS, 10.0)
|
399
|
-
#{ext_var(grid, 'grid')}
|
400
|
-
grid.getSelectionModel().select(#{row.to_i-1});
|
401
|
-
return grid.getView().getNode(#{row.to_i-1}).id;
|
402
|
-
JS
|
403
|
-
find_by_id(resid).click if click_after
|
404
|
-
wait_for_ajax
|
405
|
-
return resid
|
406
|
-
end
|
407
|
-
|
408
|
-
def set_row_vals row, grid, fields
|
409
|
-
js_set_fields = fields.each_pair.map do |k,v|
|
410
|
-
"r.set('#{k}', '#{v}');"
|
411
|
-
end.join
|
412
|
-
|
413
|
-
run_js <<-JS
|
414
|
-
#{ext_var(ext_row(row.to_i - 1, grid), 'r')}
|
415
|
-
#{js_set_fields}
|
416
|
-
JS
|
417
|
-
end
|
418
|
-
|
419
|
-
def validate_row_values row, grid, fields
|
420
|
-
js_get_fields = fields.each_key.map do |k|
|
421
|
-
<<-JS
|
422
|
-
var col = Ext.ComponentQuery.query('gridcolumn[name=\"#{k}\"]', grid)[0];
|
423
|
-
var value = col.assoc ? r.get('meta').associationValues['#{k}'] :
|
424
|
-
r.get('#{k}');
|
425
|
-
if (value instanceof Date) {
|
426
|
-
obj['#{k}'] = value.toISOString().substring(0,
|
427
|
-
value.toISOString().indexOf('T'));
|
428
|
-
} else {
|
429
|
-
obj['#{k}'] = value;
|
430
|
-
};
|
431
|
-
JS
|
432
|
-
end.join
|
433
|
-
|
434
|
-
res = run_js <<-JS
|
435
|
-
#{ext_var(grid, 'grid')}
|
436
|
-
#{ext_var(ext_row(row.to_i - 1, 'grid'), 'r')}
|
437
|
-
var obj = {};
|
438
|
-
#{js_get_fields}
|
439
|
-
return obj;
|
440
|
-
JS
|
441
|
-
wait_for_element { expect(res).to eq fields.stringify_keys }
|
442
|
-
end
|
443
|
-
|
444
|
-
def sorted_by? col, grid, direction = 'asc'
|
445
|
-
run_js <<-JS
|
446
|
-
#{ext_var(grid, 'grid')}
|
447
|
-
#{ext_var(ext_col(col, 'grid'), 'col')}
|
448
|
-
var colValues = [];
|
449
|
-
|
450
|
-
grid.getStore().each(function(r){
|
451
|
-
var val = col.assoc ? r.get('meta').associationValues['#{col}'] :
|
452
|
-
r.get('#{col}');
|
453
|
-
if (val) colValues.#{direction == 'asc' ? 'push' : 'unshift'}(val);
|
454
|
-
});
|
455
|
-
|
456
|
-
return colValues.toString() === Ext.Array.sort(colValues).toString();
|
457
|
-
JS
|
458
|
-
end
|
459
|
-
|
460
|
-
# Grid Combobox Helpers
|
461
|
-
def select_grid_combobox(selection, row, field, grid)
|
462
|
-
run_js <<-JS
|
463
|
-
#{start_edit_grid_combobox(row, field, grid)}
|
464
|
-
|
465
|
-
rec = combo.findRecordByDisplay('#{selection}');
|
466
|
-
if (rec == false) { return false; }
|
467
|
-
combo.setValue(rec);
|
468
|
-
combo.onTriggerClick();
|
469
|
-
editor.completeEdit();
|
470
|
-
return true
|
471
|
-
JS
|
472
|
-
end
|
473
|
-
|
474
|
-
def grid_combobox_values(row, field, grid)
|
475
|
-
run_js <<-JS
|
476
|
-
#{start_edit_grid_combobox(row, field, grid)}
|
477
|
-
JS
|
478
|
-
|
479
|
-
# hacky: delay for combobox to render, assumes that the combobox is not empty
|
480
|
-
run_js <<-JS
|
481
|
-
#{ext_var(grid, 'grid')}
|
482
|
-
#{ext_var(ext_netzkecombo(field), 'combo')}
|
483
|
-
var r = [];
|
484
|
-
#{ext_var(ext_celleditor, 'editor')}
|
485
|
-
var store = combo.getStore();
|
486
|
-
|
487
|
-
// force a retry if the store is still loading
|
488
|
-
if (store.loading == true) { throw "store not loaded yet"; }
|
489
|
-
|
490
|
-
for(var i = 0; i < store.getCount(); i++) {
|
491
|
-
r.push(store.getAt(i).get('text'));
|
492
|
-
};
|
493
|
-
|
494
|
-
editor.completeEdit();
|
495
|
-
return r;
|
496
|
-
JS
|
497
|
-
end
|
498
|
-
|
499
|
-
def get_grid_combobox_val(index, row, field, grid)
|
500
|
-
run_js <<-JS
|
501
|
-
#{start_edit_grid_combobox(row, field, grid)}
|
502
|
-
JS
|
503
|
-
|
504
|
-
run_js <<-JS
|
505
|
-
#{ext_var(grid, 'grid')}
|
506
|
-
#{ext_var(ext_netzkecombo(field), 'combo')}
|
507
|
-
#{ext_var(ext_celleditor, 'editor')}
|
508
|
-
var val = combo.getStore().getAt(#{index}).get('text');
|
509
|
-
editor.completeEdit();
|
510
|
-
return val;
|
511
|
-
JS
|
512
|
-
end
|
513
|
-
|
514
|
-
def start_edit_grid_combobox(row, field, grid)
|
515
|
-
<<-JS
|
516
|
-
#{ext_var(grid, 'grid')}
|
517
|
-
#{ext_var(ext_netzkecombo(field), 'combo')}
|
518
|
-
#{ext_var(ext_celleditor, 'editor')}
|
519
|
-
|
520
|
-
editor.startEditByPosition({ row:#{row.to_i-1},
|
521
|
-
column:grid.headerCt.items.findIndex('name', '#{field}') });
|
522
|
-
|
523
|
-
var now = new Date().getTime();
|
524
|
-
while(new Date().getTime() < now + 500) { }
|
525
|
-
|
526
|
-
combo.onTriggerClick();
|
527
|
-
JS
|
528
|
-
end
|
529
|
-
|
530
|
-
# Field edit/Key in Helpers
|
531
|
-
def type_in(type_s, el_id)
|
532
|
-
el = find_by_id("#{el_id}")
|
533
|
-
el.native.clear()
|
534
|
-
type_s.each_char do |key|
|
535
|
-
el.native.send_keys(key)
|
536
|
-
end
|
537
|
-
el.send_keys(:enter)
|
538
|
-
end
|
539
|
-
|
540
|
-
def press_key_in(key, el_id)
|
541
|
-
kd = key.downcase
|
542
|
-
use_key = ['enter', 'return'].include?(kd) ? kd.to_sym : key
|
543
|
-
el = find_by_id("#{el_id}")
|
544
|
-
el.native.send_keys(use_key)
|
545
|
-
end
|
546
|
-
|
547
|
-
def id_of_edit_field(row, field, grid)
|
548
|
-
res = run_js <<-JS
|
549
|
-
#{ext_var(grid, 'grid')}
|
550
|
-
#{ext_var(ext_celleditor, 'editor')}
|
551
|
-
|
552
|
-
editor.startEditByPosition({ row:#{row.to_i-1},
|
553
|
-
column:grid.headerCt.items.findIndex('name', '#{field}') });
|
554
|
-
return editor.activeEditor.field.inputId;
|
555
|
-
JS
|
556
|
-
res
|
557
|
-
end
|
558
|
-
|
559
|
-
def end_edit(row, field, grid)
|
560
|
-
run_js <<-JS
|
561
|
-
#{ext_var(grid, 'grid')}
|
562
|
-
#{ext_var(ext_celleditor, 'editor')}
|
563
|
-
editor.completeEdit();
|
564
|
-
return true;
|
565
|
-
JS
|
566
|
-
end
|
567
|
-
|
568
|
-
# Combobox Helpers
|
569
|
-
def select_combobox(values, combo_label)
|
570
|
-
run_js <<-JS
|
571
|
-
var values = #{values.split(/,\s*/)};
|
572
|
-
#{ext_combo(combo_label)}
|
573
|
-
|
574
|
-
var arr = new Array();
|
575
|
-
for(var i=0; i < values.length; i++) {
|
576
|
-
arr[i] = combo.findRecordByDisplay(values[i]);
|
577
|
-
}
|
578
|
-
combo.select(arr);
|
579
|
-
if (combo.isExpanded) { combo.onTriggerClick(); }
|
580
|
-
JS
|
581
|
-
end
|
582
|
-
|
583
|
-
def combobox_values(combo_label)
|
584
|
-
run_js <<-JS
|
585
|
-
#{ext_combo(combo_label)}
|
586
|
-
var values = [];
|
587
|
-
combo.getStore().each(
|
588
|
-
function(r) { values.push(r.data.text || r.data.field1); });
|
589
|
-
return values;
|
590
|
-
JS
|
591
|
-
end
|
592
|
-
|
593
|
-
def click_combobox combo_label
|
594
|
-
run_js <<-JS
|
595
|
-
#{ext_combo(combo_label)}
|
596
|
-
combo.onTriggerClick();
|
597
|
-
JS
|
598
|
-
wait_for_element { !ajax_loading? }
|
599
|
-
end
|
600
|
-
|
601
|
-
# Capybara finders
|
602
|
-
def custom_selectors
|
603
|
-
Capybara.add_selector(:gridpanel) do
|
604
|
-
xpath { |name| ".//div[contains(@id, '#{name}')] | " +
|
605
|
-
".//div[contains(@id, '#{name.camelize(:lower)}')]" }
|
606
|
-
end
|
607
|
-
Capybara.add_selector(:msg) do
|
608
|
-
xpath { "//div[@id='msg-div']" }
|
609
|
-
end
|
610
|
-
Capybara.add_selector(:body) do
|
611
|
-
xpath { ".//div[@data-ref='body']" }
|
612
|
-
end
|
613
|
-
Capybara.add_selector(:input) do
|
614
|
-
xpath { |name| "//input[@name='#{name}']" }
|
615
|
-
end
|
616
|
-
Capybara.add_selector(:status) do
|
617
|
-
xpath { |name| "//div[contains(@id, 'statusbar')]//div[text()='#{name}']" }
|
618
|
-
end
|
619
|
-
Capybara.add_selector(:btn) do
|
620
|
-
xpath { |name| ".//span[text()='#{name}']" }
|
621
|
-
end
|
622
|
-
Capybara.add_selector(:refresh) do
|
623
|
-
xpath { "//img[contains(@class, 'x-tool-refresh')]" }
|
624
|
-
end
|
625
|
-
Capybara.add_selector(:gridcolumn) do
|
626
|
-
xpath { |name| ".//span[contains(@class, 'x-column-header')]" +
|
627
|
-
"//span[text()='#{name}']" }
|
628
|
-
end
|
629
|
-
end
|
630
40
|
end
|