Skip to content

Commit 8f80e41

Browse files
Race Condition Check: spec/system/case_contacts/ updates
Resolves rubyforgood#6701 When github's free CI servers are under heavy load, a race condition between the page loading and checking the database causes tests to flake. This is caused by a system test inputting data into a form then immediately checking the database without waiting for the form to finish submitting. For every database check in the system files, this ensures it's preceded by a capybara matcher with automatic waiting, such as checking for assertions after the page loads before checking for DB values, or replaced the database check with a check for something to appear on the page. I also took the opportunity to refactor some small things to save up test setup time: - build factories instead of creating as much as possible - require `:js` only when necessary - remove unused variables and factories - keep necessary factories close to where they are used to avoid creating extra factories when not needed - update Date string to Date objects (these were flaky locally), similar to rubyforgood#6764
1 parent ac44c7c commit 8f80e41

File tree

8 files changed

+255
-257
lines changed

8 files changed

+255
-257
lines changed
Lines changed: 45 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
require "rails_helper"
22

3-
RSpec.describe "CaseContact AdditionalExpenses Form", :flipper, :js, type: :system do
3+
RSpec.describe "CaseContact AdditionalExpenses Form", :flipper, type: :system do
44
subject do
55
visit new_case_contact_path(casa_case)
66
fill_in_contact_details(contact_types: [contact_type.name])
@@ -28,7 +28,7 @@
2828
expect(page).to have_no_button("Add Another Expense", visible: :all)
2929
end
3030

31-
it "is not shown until Reimbursement is checked and Add Another Expense clicked" do
31+
it "is not shown until Reimbursement is checked and Add Another Expense clicked", :js do
3232
sign_in volunteer
3333
visit new_case_contact_path casa_case
3434
fill_in_contact_details
@@ -42,64 +42,64 @@
4242
expect(page).to have_field(class: "expense-amount-input")
4343
end
4444

45-
it "does not submit values if reimbursement is cancelled (unchecked)" do
45+
it "does not submit values if reimbursement is cancelled (unchecked)", :js do
4646
subject
4747

4848
click_on "Add Another Expense"
4949
fill_expense_fields 5.34, "Lunch"
5050
uncheck "Request travel or other reimbursement"
5151

52-
expect { click_on "Submit" }
53-
.to change(CaseContact.active, :count).by(1)
52+
click_on "Submit"
53+
expect(page).to have_text("Case contact successfully created")
5454

55+
expect(CaseContact.active.count).to eq(1)
5556
case_contact = CaseContact.active.last
5657
expect(case_contact.additional_expenses).to be_empty
5758
expect(case_contact.miles_driven).to be_zero
5859
expect(case_contact.want_driving_reimbursement).to be false
5960
end
6061

61-
it "can remove an expense" do
62+
it "can remove an expense", :js do
6263
subject
6364
fill_in_contact_details
6465
check "Request travel or other reimbursement"
6566
fill_in "case_contact_miles_driven", with: 50
6667
fill_in "case_contact_volunteer_address", with: "123 Params St"
6768

68-
expect {
69-
click_on "Add Another Expense"
70-
fill_expense_fields 1.50, "1st meal"
71-
click_on "Add Another Expense"
72-
fill_expense_fields 2.50, "2nd meal"
73-
click_on "Add Another Expense"
74-
fill_expense_fields 2.00, "3rd meal"
69+
click_on "Add Another Expense"
70+
fill_expense_fields 1.50, "1st meal"
71+
click_on "Add Another Expense"
72+
fill_expense_fields 2.50, "2nd meal"
73+
click_on "Add Another Expense"
74+
fill_expense_fields 2.00, "3rd meal"
7575

76-
within "#contact-form-expenses" do
77-
click_on "Delete", match: :first
78-
end
76+
within "#contact-form-expenses" do
77+
click_on "Delete", match: :first
78+
end
7979

80-
expect(page).to have_field(class: "expense-amount-input", count: 2)
80+
expect(page).to have_field(class: "expense-amount-input", count: 2)
8181

82-
click_on "Submit"
83-
expect(page).to have_text("Case contact successfully created")
84-
}
85-
.to change(CaseContact.active, :count).by(1)
86-
.and change(AdditionalExpense, :count).by(2)
82+
click_on "Submit"
83+
expect(page).to have_text("Case contact successfully created")
8784

8885
case_contact = CaseContact.active.last
8986
expect(case_contact.additional_expenses.size).to eq(2)
87+
expect(CaseContact.count).to eq(1)
88+
expect(AdditionalExpense.count).to eq(2)
9089
end
9190

92-
it "requires a description for each additional expense" do
91+
it "requires a description for each additional expense", :js do
9392
subject
9493

9594
click_on "Add Another Expense"
9695
fill_expense_fields 5.34, nil
9796

98-
expect { click_on "Submit" }
99-
.to not_change(CaseContact.active, :count)
100-
.and not_change(AdditionalExpense, :count)
97+
click_on "Submit"
10198

10299
expect(page).to have_text("Other Expense Details can't be blank")
100+
101+
expect(CaseContact.active.count).to eq(0)
102+
expect(AdditionalExpense.count).to eq(1)
103103
end
104104

105105
context "when editing existing case contact expenses" do
@@ -125,38 +125,39 @@
125125
expect(page).to have_button "Add Another Expense"
126126
end
127127

128-
it "allows removing expenses" do
128+
it "allows removing expenses", :js do
129129
subject
130130

131131
expect(page).to have_css(".expense-amount-input", count: 2)
132132
expect(page).to have_css(".expense-describe-input", count: 2)
133133

134-
expect {
135-
within "#contact-form-expenses" do
136-
click_on "Delete", match: :first
137-
end
134+
within "#contact-form-expenses" do
135+
click_on "Delete", match: :first
136+
end
137+
138+
expect(page).to have_css(".expense-amount-input", count: 1)
139+
expect(page).to have_css(".expense-describe-input", count: 1)
138140

139-
expect(page).to have_css(".expense-amount-input", count: 1)
140-
expect(page).to have_css(".expense-describe-input", count: 1)
141+
click_on "Submit"
141142

142-
click_on "Submit"
143-
}
144-
.to not_change(CaseContact.active, :count)
145-
.and change(AdditionalExpense, :count).by(-1)
143+
expect(page).to have_text(/Case contact .* was successfully updated./)
146144

145+
expect(CaseContact.active.count).to eq(1)
146+
expect(AdditionalExpense.count).to eq(1)
147147
expect(case_contact.reload.additional_expenses.size).to eq(1)
148148
end
149149

150-
it "can add an expense" do
150+
it "can add an expense", :js do
151151
subject
152152

153-
expect {
154-
click_on "Add Another Expense"
155-
fill_expense_fields 11.50, "Gas"
156-
click_on "Submit"
157-
}
158-
.to change(AdditionalExpense, :count).by(1)
153+
click_on "Add Another Expense"
154+
fill_expense_fields 11.50, "Gas"
155+
click_on "Submit"
156+
157+
expect(page).to have_text(/Case contact .* was successfully updated./)
158+
159159
expect(case_contact.reload.additional_expenses.size).to eq(3)
160+
expect(AdditionalExpense.count).to eq(3)
160161
end
161162
end
162163
end

spec/system/case_contacts/contact_topic_answers_spec.rb

Lines changed: 48 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
require "rails_helper"
22

3-
RSpec.describe "CaseContact form ContactTopicAnswers and notes", :js, type: :system do
3+
RSpec.describe "CaseContact form ContactTopicAnswers and notes", type: :system do
44
subject do
55
sign_in user
66
visit new_case_contact_path(casa_case)
@@ -12,8 +12,7 @@
1212
let(:user) { volunteer }
1313

1414
let!(:contact_type) { create :contact_type, casa_org: }
15-
let(:topic_count) { 2 }
16-
let!(:contact_topics) { create_list :contact_topic, topic_count, casa_org: }
15+
let!(:contact_topics) { create_list :contact_topic, 2, casa_org: }
1716
let(:contact_topic_questions) { contact_topics.map(&:question) }
1817
let(:select_options) { contact_topic_questions + ["Select a discussion topic"] }
1918

@@ -36,7 +35,7 @@ def notes_section
3635
expect(notes_section).to have_select(class: topic_select_class, with_options: contact_topic_questions)
3736
end
3837

39-
it "adds contact answers for the topics" do
38+
it "adds contact answers for the topics", :js do
4039
subject
4140
fill_in_contact_details(contact_types: [contact_type.name])
4241

@@ -65,22 +64,19 @@ def notes_section
6564
subject
6665
fill_in_contact_details(contact_types: [contact_type.name])
6766

68-
expect do
69-
using_wait_time 6 do # autosave debounce may be longer than capybara's wait time
70-
answer_topic contact_topics.first.question, "First discussion topic answer."
71-
within notes_section do
72-
expect(page).to have_text "Saved" # autosave success alert
73-
expect(page).to have_no_text "Saved" # wait for clearing of alert
74-
end
75-
answer_topic contact_topics.first.question, "Changing the first topic answer."
76-
within notes_section { expect(page).to have_text "Saved" }
77-
end
67+
answer_topic contact_topics.first.question, "First discussion topic answer."
68+
within notes_section do
69+
expect(page).to have_text "Saved" # autosave success alert
70+
expect(page).to have_no_text "Saved" # wait for clearing of alert
71+
end
72+
answer_topic contact_topics.first.question, "Changing the first topic answer."
73+
within notes_section { expect(page).to have_text "Saved" }
7874

79-
click_on "Submit"
80-
expect(page).to have_content("Case contact successfully created.")
81-
end.to change(CaseContact.active, :count).by(1)
82-
.and change(ContactTopicAnswer, :count).by(0) # answer already exists on page load
75+
click_on "Submit"
76+
expect(page).to have_content("Case contact successfully created.")
8377

78+
expect(CaseContact.active.count).to eq(1)
79+
expect(ContactTopicAnswer.count).to eq(1)
8480
case_contact = CaseContact.active.last
8581
created_answer = ContactTopicAnswer.last
8682
expect(created_answer.contact_topic).to eq(contact_topics.first)
@@ -89,7 +85,7 @@ def notes_section
8985
expect(case_contact.contact_topic_answers).to include created_answer
9086
end
9187

92-
it "prevents adding more answers than topics" do
88+
it "prevents adding more answers than topics", :js do
9389
subject
9490

9591
(contact_topics.size - 1).times do
@@ -99,7 +95,7 @@ def notes_section
9995
expect(notes_section).to have_button("Add Another Discussion Topic", disabled: true)
10096
end
10197

102-
it "disables contact topics that are already selected" do
98+
it "disables contact topics that are already selected", :js do
10399
subject
104100

105101
topic_one_question = contact_topics.first.question
@@ -115,42 +111,40 @@ def notes_section
115111
context "when casa org has no contact topics" do
116112
let(:contact_topics) { [] }
117113

118-
it "displays a field for contact.notes" do
114+
it "displays a field for contact.notes", :js do
119115
subject
120116
expect(page).to have_no_button "Add Another Discussion Topic"
121117
expect(notes_section).to have_field "Additional Notes"
122118

123119
fill_in_contact_details
124120
fill_in "Additional Notes", with: "This is a note."
125121

126-
expect do
127-
click_on "Submit"
128-
expect(page).to have_content("Case contact successfully created.")
129-
end.to change(CaseContact.active, :count).by(1)
122+
click_on "Submit"
123+
expect(page).to have_content("Case contact successfully created.")
130124

131125
contact = CaseContact.active.last
126+
expect(CaseContact.active.count).to eq(1)
132127
expect(contact.contact_topic_answers).to be_empty
133128
expect(contact.notes).to eq "This is a note."
134129
end
135130

136-
it "saves 'Additional Notes' answer as contact.notes" do
131+
it "saves 'Additional Notes' answer as contact.notes", :js do
137132
subject
138133
fill_in_contact_details(contact_types: [contact_type.name])
139134

140135
fill_in "Additional Notes", with: "This is a fake a topic answer."
141136

142-
expect do
143-
click_on "Submit"
144-
expect(page).to have_text("Case contact successfully created")
145-
end.to change(CaseContact.active, :count).by(1)
137+
click_on "Submit"
138+
expect(page).to have_text("Case contact successfully created")
146139

147140
contact = CaseContact.active.last
141+
expect(CaseContact.active.count).to eq(1)
148142
expect(contact.contact_topic_answers).to be_empty
149143
expect(contact.notes).to eq "This is a fake a topic answer."
150144
end
151145
end
152146

153-
context "when editing existing an case contact" do
147+
context "when editing an existing case contact" do
154148
subject do
155149
sign_in user
156150
visit edit_case_contact_path(case_contact)
@@ -181,46 +175,46 @@ def notes_section
181175
)
182176
end
183177

184-
it "can remove an existing answer" do
178+
it "can remove an existing answer", :js do
185179
subject
186180
fill_in_contact_details
187181

188182
expect(notes_section).to have_select(class: topic_select_class, count: 2)
189183

190-
expect {
191-
accept_confirm do
192-
notes_section.find_button(text: "Delete", match: :first).click
193-
end
184+
accept_confirm do
185+
notes_section.find_button(text: "Delete", match: :first).click
186+
end
194187

195-
expect(notes_section).to have_select(class: topic_select_class, count: 1, visible: :all)
188+
expect(notes_section).to have_select(class: topic_select_class, count: 1, visible: :all)
196189

197-
click_on "Submit"
198-
expect(page).to have_content(/Case contact .* was successfully updated./)
199-
}
200-
.to change(ContactTopicAnswer, :count).by(-1)
190+
click_on "Submit"
191+
expect(page).to have_content(/Case contact .* was successfully updated./)
201192

202193
case_contact.reload
194+
expect(ContactTopicAnswer.count).to eq(1)
203195
expect(case_contact.contact_topic_answers.size).to eq(1)
204196
end
205197
end
206198

207-
it "autosaves form with answer inputs" do
208-
expect { subject }.to change(CaseContact, :count).by(1)
209-
case_contact = CaseContact.last
210-
expect(case_contact.casa_case).to eq casa_case
199+
it "autosaves form with answer inputs", :js do
200+
subject
201+
211202
fill_in_contact_details(
212203
contact_made: false, medium: "In Person", occurred_on: 1.day.ago.to_date, hours: 1, minutes: 5
213204
)
214205

215-
expect {
216-
click_on "Add Another Discussion Topic"
217-
answer_topic contact_topics.first.question, "Topic One answer."
218-
within autosave_alert_div do
219-
find(autosave_alert_css, text: autosave_alert_text, wait: 3)
220-
end
221-
}
222-
.to change(ContactTopicAnswer, :count).by(1)
223-
case_contact.reload
206+
click_on "Add Another Discussion Topic"
207+
answer_topic contact_topics.first.question, "Topic One answer."
208+
within autosave_alert_div do
209+
find(autosave_alert_css, text: autosave_alert_text, wait: 3)
210+
end
211+
212+
expect(page).to have_content("Editing Existing Case Contact")
213+
214+
expect(CaseContact.count).to eq(1)
215+
case_contact = CaseContact.last
216+
expect(case_contact.casa_case).to eq casa_case
217+
expect(ContactTopicAnswer.count).to eq(1)
224218
expect(case_contact.contact_topic_answers.size).to eq(1)
225219
expect(case_contact.contact_topic_answers.last.value).to eq "Topic One answer."
226220

spec/system/case_contacts/drafts_spec.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
require "rails_helper"
22

3-
RSpec.describe "case_contacts/drafts", :js, type: :system do
4-
let(:organization) { create(:casa_org) }
5-
let(:admin) { create(:casa_admin, casa_org: organization) }
3+
RSpec.describe "case_contacts/drafts", type: :system do
4+
let(:organization) { build(:casa_org) }
5+
let(:admin) { build(:casa_admin, casa_org: organization) }
66

77
context "with case contacts" do
8-
let!(:casa_case) { create(:casa_case, casa_org: organization) }
9-
let!(:other_org_case) { create(:case_contact, notes: "NOTE_A") }
10-
let!(:past_contact) { create(:case_contact, casa_case: casa_case, occurred_at: 3.weeks.ago, notes: "NOTE_B") }
8+
let!(:casa_case) { build(:casa_case, casa_org: organization) }
9+
let!(:other_org_case) { build(:case_contact, notes: "NOTE_A") }
10+
let!(:past_contact) { build(:case_contact, casa_case: casa_case, occurred_at: 3.weeks.ago, notes: "NOTE_B") }
1111
let!(:past_contact_draft) { create(:case_contact, :started_status, casa_case: casa_case, occurred_at: 3.weeks.ago, notes: "NOTE_C") }
12-
let!(:recent_contact) { create(:case_contact, casa_case: casa_case, occurred_at: 3.days.ago, notes: "NOTE_D") }
12+
let!(:recent_contact) { build(:case_contact, casa_case: casa_case, occurred_at: 3.days.ago, notes: "NOTE_D") }
1313
let!(:recent_contact_draft) { create(:case_contact, :started_status, casa_case: casa_case, occurred_at: 3.days.ago, notes: "NOTE_E") }
1414

1515
it "shows only same orgs drafts" do

0 commit comments

Comments
 (0)