質問編集履歴

1

書式の改善

2020/03/08 04:06

投稿

meganezaru-kei
meganezaru-kei

スコア6

test CHANGED
@@ -1 +1 @@
1
- capybaraでselectタグの中にoption格納することができない
1
+ capybara】JavaScript生成されたselectタグを選択することができない
test CHANGED
@@ -4,207 +4,377 @@
4
4
 
5
5
  capybaraで記事の新規投稿をする場合の統合テストを書いています。
6
6
 
7
+ 新規投稿画面で、以下のように「犬種」を選択すると、その子カテゴリーのselectタグが出てくるようにJavaScript (jQuery) を書いています。
8
+
9
+ ![![イメージ説明](4606282692957788466294c3b6d2fd21.gif)]
10
+
11
+ この新しく生成されたselectタグを、capybara上で選択されるようにしたいのですが、以下のようなエラーが発生します。
12
+
13
+
14
+
15
+ ### 発生している問題・エラーメッセージ
16
+
17
+
18
+
19
+ ```
20
+
21
+ Failures:
22
+
23
+
24
+
25
+ 1) post create post
26
+
27
+ Failure/Error: select 'ゴールデンレトリバー', from: 'child_category'
28
+
29
+
30
+
31
+ Capybara::ElementNotFound:
32
+
33
+ Unable to find select box "child_category" that is not disabled and Unable to find input box with datalist completion "child_category" that is not disabled
34
+
35
+ ```
36
+
37
+
38
+
39
+ ### 該当のソースコード
40
+
41
+ spec/features/post_spec.rb
42
+
43
+ ```ruby
44
+
45
+ require 'rails_helper'
46
+
47
+
48
+
49
+ feature 'post', type: :feature do
50
+
51
+ let(:user) { create(:user) }
52
+
53
+ background do
54
+
55
+ parent_category = Category.create(name: '大型犬', ancestry: nil)
56
+
57
+ child_category = Category.create(name: 'ゴールデンレトリバー', ancestry: 9)
58
+
59
+ end
60
+
61
+
62
+
63
+ scenario 'create post', js: true do
64
+
65
+ visit root_path
66
+
67
+ expect(page).to have_no_content('新規投稿')
68
+
69
+
70
+
71
+ visit login_path
72
+
73
+ fill_in 'user_email', with: user.email
74
+
75
+ fill_in 'user_password', with: user.password
76
+
77
+ find('input[value="ログイン"]').click
78
+
79
+ expect(current_path).to eq root_path
80
+
81
+ expect(page).to have_content('新規投稿')
82
+
83
+
84
+
7
- 新規投稿画面に、
85
+ expect {
86
+
8
-
87
+ click_link('new-post-btn')
88
+
9
-
89
+ expect(current_path).to eq new_post_path
90
+
91
+ attach_file 'post_images_1', "#{Rails.root}/spec/support/assets/test-image.png", make_visible: true
92
+
93
+ fill_in 'post_title', with: 'フィーチャスペックのテスト'
94
+
95
+ fill_in 'post_body', with: 'フィーチャスペックのテスト'
96
+
97
+ select '大型犬', from: 'parent_category'
98
+
99
+ select 'ゴールデンレトリバー', from: 'child_category' ###ここでエラー発生###
100
+
101
+ find('input[value="保存"]').click
102
+
103
+ }.to change(Post, :count).by(1)
104
+
105
+ end
106
+
107
+ end
108
+
109
+ ```
110
+
111
+ rails_helper.rb
112
+
113
+ ```ruby
114
+
115
+ require 'spec_helper'
116
+
117
+ ENV['RAILS_ENV'] ||= 'test'
118
+
119
+ require File.expand_path('../config/environment', __dir__)
120
+
121
+ if Rails.env.production?
122
+
123
+ abort('The Rails environment is running in production mode!')
124
+
125
+ end
126
+
127
+ require 'rspec/rails'
128
+
129
+
130
+
131
+ require 'capybara/rspec'
132
+
133
+ require 'capybara/poltergeist'
134
+
135
+
136
+
137
+ begin
138
+
139
+ ActiveRecord::Migration.maintain_test_schema!
140
+
141
+ rescue ActiveRecord::PendingMigrationError => e
142
+
143
+ puts e.to_s.strip
144
+
145
+ exit 1
146
+
147
+ end
148
+
149
+ RSpec.configure do |config|
150
+
151
+ Dir[Rails.root.join('spec/support/**/*.rb')].sort.each { |f| require f }
152
+
153
+ config.include Devise::Test::ControllerHelpers, type: :controller
154
+
155
+ config.include ControllerMacros, type: :controller
156
+
157
+ config.include FactoryBot::Syntax::Methods
158
+
159
+ Capybara.javascript_driver = :poltergeist
160
+
161
+ Capybara.register_driver :poltergeist do |app|
162
+
163
+ Capybara::Poltergeist::Driver.new(app, {js_errors: false})
164
+
165
+ end
166
+
167
+
168
+
169
+ Headless.new.start
170
+
171
+
172
+
173
+ require 'database_cleaner'
174
+
175
+ config.before(:suite) do
176
+
177
+ DatabaseCleaner.strategy = :truncation
178
+
179
+ DatabaseCleaner.clean_with(:truncation)
180
+
181
+ end
182
+
183
+
184
+
185
+ config.before(:each) do
186
+
187
+ DatabaseCleaner.start
188
+
189
+ end
190
+
191
+
192
+
193
+ config.after(:each) do
194
+
195
+ DatabaseCleaner.clean
196
+
197
+ end
198
+
199
+
200
+
201
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
202
+
203
+ config.use_transactional_fixtures = false
204
+
205
+ config.infer_spec_type_from_file_location!
206
+
207
+ config.filter_rails_from_backtrace!
208
+
209
+ end
210
+
211
+
212
+
213
+ FactoryBot::SyntaxRunner.class_eval do
214
+
215
+ include ActionDispatch::TestProcess
216
+
217
+ end
218
+
219
+ ```
220
+
221
+ posts_controller.rb
222
+
223
+ ```ruby
224
+
225
+ def new
226
+
227
+ @post = Post.new
228
+
229
+ @images_count = @post.images.length.to_i
230
+
231
+
232
+
233
+ @category_parent_array = ['---', '大型犬', '中型犬', '小型犬']
234
+
235
+ end
236
+
237
+ ```
238
+
239
+ new.html.haml
240
+
241
+ ```haml
242
+
243
+ .form-group#category
244
+
245
+ = f.label :parent_category, '犬種:'
246
+
247
+ = f.select :parent_category, @category_parent_array, {}, { id: 'parent_category', class: 'form-control' }
248
+
249
+ ```
250
+
251
+ javascriptで生成されるselectタグ
10
252
 
11
253
  ```html
12
254
 
13
- <select id="parent_category" class="form-control" name="post[parent_category]">
255
+ <select id="child_category" class="form-control mt-2" name="post[child_category]">
14
256
 
15
257
  <option value="---">---</option>
16
258
 
17
- <option value="大型犬">大型犬</option>
259
+ <option value="ゴールデンレトリバー" data-category="10">ゴールデンレトリバー</option>
18
-
260
+
19
- <option value="中型犬">中型犬</option>
261
+ <option value="ラブラドールレトリバー" data-category="11">ラブラドルレトリバー</option>
20
-
262
+
21
- <option value="小型犬">小型犬</option>
263
+ ##(中略)
22
264
 
23
265
  </select>
24
266
 
25
267
  ```
26
268
 
27
- というselectタグがあるので、
28
-
29
-
30
-
31
- `select '大型犬', from: 'parent_category'`
32
-
33
-
34
-
35
- 使って、「大型犬」というoptionが選択されている状態にしたいのですが、以下のエラーが発生してしまいます。
36
-
37
-
38
-
39
- ### 発生している問題・エラーメッセージ
40
-
41
-
42
-
43
- ```
44
-
45
- Failures:
46
-
47
-
48
-
49
- 1) post create post
50
-
51
- Failure/Error: select '大型犬', from: 'parent_category'
52
-
53
-
54
-
55
- Capybara::ElementNotFound:
56
-
57
- Unable to find option "大型犬" within #<Capybara::Node::Element tag="select" path="/html/body/div/form/div[3]/div[2]/div[1]/select">
58
-
59
- ```
60
-
61
-
62
-
63
- ### 該当のソースコード
64
-
65
- spec/features/post_spec.rb
66
-
67
- ```ruby
68
-
69
- require 'rails_helper'
70
-
71
-
72
-
73
- feature 'post', type: :feature do
74
-
75
- let(:user) { create(:user) }
76
-
77
- let(:category) { create(:category) }
78
-
79
-
80
-
81
- scenario 'create post' do
82
-
83
- visit root_path
84
-
85
- expect(page).to have_no_content('新規投稿')
86
-
87
-
88
-
89
- visit login_path
90
-
91
- fill_in 'user_email', with: user.email
92
-
93
- fill_in 'user_password', with: user.password
94
-
95
- find('input[value="ログイン"]').click
96
-
97
- expect(current_path).to eq root_path
98
-
99
- expect(page).to have_content('新規投稿')
100
-
101
-
102
-
103
- expect {
104
-
105
- click_link('new-post-btn')
106
-
107
- expect(current_path).to eq new_post_path
108
-
109
- attach_file 'post_images_1', "#{Rails.root}/spec/support/assets/test-image.png"
110
-
111
- fill_in 'post_title', with: 'フィーチャスペックのテスト'
112
-
113
- fill_in 'post_body', with: 'フィーチャスペックのテスト'
114
-
115
- select '大型犬', from: 'parent_category' #ここでエラー発生
116
-
117
- find('input[value="保存"]').click
118
-
119
- }.to change(Post, :count).by(1)
120
-
121
- end
122
-
123
- end
124
-
125
- ```
126
-
127
- posts_controller.rb
128
-
129
- ```ruby
130
-
131
- def new
132
-
133
- @post = Post.new
134
-
135
- @images_count = @post.images.length.to_i
136
-
137
-
138
-
139
- @category_parent_array = ['---']
140
-
141
- Category.where(ancestry: nil).each do |parent|
142
-
143
- @category_parent_array << parent.name
144
-
145
- end
146
-
147
- end
148
-
149
- ```
150
-
151
- new.html.haml
152
-
153
- ```haml
154
-
155
- .form-group#category
156
-
157
- = f.label :parent_category, '犬種:'
158
-
159
- = f.select :parent_category, @category_parent_array, {}, { id: 'parent_category', class: 'form-control' }
160
-
161
- ```
162
-
163
-
164
-
165
- コントローラで@category_parent_arrayの中に['---', '大型犬', '中型犬', '小型犬']を格納し、
166
-
167
- これをビューファイルでselectタグの選択肢となるように設定しています。
168
-
169
- ブラウザ上は問題なく選択肢が出てくるのですが、capybaraでは初期値の「---」しか設定されていないようで、テストが通りません。
170
-
171
-
172
-
173
- 試しに`select '大型犬', from: 'parent_category'`をコメントアウトして再度テストを実行してみると、
174
-
175
-
176
-
177
- ```
178
-
179
- Failures:
180
-
181
-
182
-
183
- 1) post create post
184
-
185
- Failure/Error: = f.select :parent_category, @category_parent_array, {}, { id: 'parent_category', class: 'form-control' }
186
-
187
-
188
-
189
- ActionView::Template::Error:
190
-
191
- undefined method `map' for nil:NilClass
192
-
193
- ```
194
-
195
-
196
-
197
- というエラーが発生し、capybaraでのテスト実行中にmapメソッドが使えていないことが原因なのかなと考えています。
198
-
199
-
200
-
201
- 状況としては以下の記事に似ているようなのですが、ベストアンサーもなく解決策が見つかりません。
202
-
203
- https://stackoverflow.com/questions/57974438/undefined-method-map-while-running-capybara-test
204
-
205
-
206
-
207
- 原因や解決方法がわかる方がいらっしゃいましたら、ご助言いただけますと幸いです。????‍♂️
269
+ post-categoies.js
270
+
271
+ ```js
272
+
273
+ $(document).on('turbolinks:load', function(){
274
+
275
+ $(function(){
276
+
277
+ // カテゴリーセレクトボックスのオプション作成
278
+
279
+ function appendOption(category){
280
+
281
+ var html = `<option value="${category.name}" data-category="${category.id}">${category.name}</option>`;
282
+
283
+ return html;
284
+
285
+ }
286
+
287
+ // 子カテゴリーの表示作成
288
+
289
+ function appendChidrenBox(insertHTML){
290
+
291
+ var childSelectHtml = '';
292
+
293
+ childSelectHtml = `
294
+
295
+ <select id="child_category" class="form-control mt-2" name="post[child_category]">
296
+
297
+ <option value="---">---</option>
298
+
299
+ ${insertHTML}
300
+
301
+ </select>`;
302
+
303
+ $('#category').append(childSelectHtml);
304
+
305
+ }
306
+
307
+ // 親カテゴリー選択後のイベント
308
+
309
+ $('#parent_category').on('change', function(){
310
+
311
+ var parentCategory = document.getElementById('parent_category').value; //選択された親カテゴリーの名前を取得
312
+
313
+ if (parentCategory != "---"){ //親カテゴリーが初期値でないことを確認
314
+
315
+ $.ajax({
316
+
317
+ url: '/posts/set_category_children',
318
+
319
+ type: 'GET',
320
+
321
+ data: { parent_name: parentCategory },
322
+
323
+ dataType: 'json'
324
+
325
+ })
326
+
327
+ .done(function(children){
328
+
329
+ $('#child_category').remove(); //親が変更された時、子以下を削除するする
330
+
331
+ var insertHTML = '';
332
+
333
+ children.forEach(function(child){
334
+
335
+ insertHTML += appendOption(child);
336
+
337
+ });
338
+
339
+ appendChidrenBox(insertHTML);
340
+
341
+ })
342
+
343
+ .fail(function(){
344
+
345
+ alert('カテゴリー取得に失敗しました');
346
+
347
+ })
348
+
349
+ }else{
350
+
351
+ $('#child_category').remove(); //親カテゴリーが初期値になった時、子以下を削除するする
352
+
353
+ }
354
+
355
+ });
356
+
357
+ });
358
+
359
+ });
360
+
361
+ ```
362
+
363
+
364
+
365
+ ### 試したこと
366
+
367
+ 以下の記事を参考にして、poltergeistをセットアップしているのですが、うまくいかず・・・
368
+
369
+
370
+
371
+ [使えるRSpec入門・その4「どんなブラウザ操作も自由自在!逆引きCapybara大辞典」](https://qiita.com/jnchito/items/607f956263c38a5fec24#javascript%E3%82%92%E4%BD%BF%E3%82%8F%E3%81%AA%E3%81%84%E3%81%A8%E6%93%8D%E4%BD%9C%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84%E5%87%A6%E7%90%86%E3%82%92%E3%83%86%E3%82%B9%E3%83%88%E3%81%99%E3%82%8B)
372
+
373
+
374
+
375
+ また他にもcapybara-webkitを導入してみたりなどもしましたが、これもまたうまく動作しないという状態です。。
376
+
377
+ 原因や解決方法がわかりそうな方がいらっしゃいましたら、ご助言いただけますと幸いです。????‍♂️
208
378
 
209
379
 
210
380