Skip to content

New Case Contacts Table: row actions menu#6834

Open
cliftonmcintosh wants to merge 22 commits intorubyforgood:mainfrom
cliftonmcintosh:feature/6500-case-contacts-new-design-row-actions-menu
Open

New Case Contacts Table: row actions menu#6834
cliftonmcintosh wants to merge 22 commits intorubyforgood:mainfrom
cliftonmcintosh:feature/6500-case-contacts-new-design-row-actions-menu

Conversation

@cliftonmcintosh
Copy link
Copy Markdown
Collaborator

@cliftonmcintosh cliftonmcintosh commented Apr 9, 2026

What github issue is this PR for, if any?

Resolves #6500

What changed, and why?

Implements the ellipsis (⋮) action menu for each row in the new case contacts table at /case_contacts/new_design. The menu contains three items: Edit, Delete, and Set Reminder (or Resolve Reminder if a pending followup already exists).

app/datatables/case_contact_datatable.rb

  • Added current_user parameter to the initializer so the datatable can compute per-row permissions
  • Added per-row fields to the JSON response: can_edit, can_destroy, edit_path, and followup_id
    • can_edit and can_destroy are derived from CaseContactPolicy so the UI reflects actual Pundit permissions
    • followup_id is the id of any open (requested) followup, used to toggle between Set Reminder and Resolve Reminder
  • Updated includes to add :followups and :creator to avoid N+1 queries

app/controllers/case_contacts/case_contacts_new_design_controller.rb

  • Passed current_user to CaseContactDatatable.new

app/controllers/case_contacts_controller.rb

  • Added respond_to to destroy so jQuery AJAX receives 204 No Content instead of an HTML redirect that would be silently followed

app/controllers/case_contacts/followups_controller.rb

  • Added respond_to to resolve for the same reason

app/javascript/src/dashboard.js

  • Imported SweetAlert2
  • Replaced the placeholder ellipsis icon in the last column with a fully-functional Bootstrap dropdown menu
    • Edit links to edit_path with data-turbo="false"; rendered as a disabled <span> when can_edit is false
    • Delete triggers a SweetAlert2 confirmation dialog before sending a DELETE request via AJAX; rendered as a disabled <button> when can_destroy is false
    • Set Reminder opens a SweetAlert2 dialog for an optional note, then POSTs to the followups endpoint; shown when no open followup exists
    • Resolve Reminder sends a PATCH to the followup resolve endpoint; shown when an open followup exists
    • All three actions reload the DataTable in place on success so the row reflects the new state
  • All AJAX requests include the CSRF token from the page's <meta> tag
  • The dropdown toggle button includes aria-label, aria-haspopup, and aria-expanded attributes; the icon is marked aria-hidden="true"

How is this tested? (please write rspec and jest tests!) 💖💪

Note: if you see a flake in your test build in github actions, please post in slack #casa "Flaky test: " :) 💪
Note: We love capybara tests! If you are writing both haml/js and ruby, please try to test your work with tests at every level including system tests like https://github.com/rubyforgood/casa/tree/main/spec/system

Datatable spec — updated spec/datatables/case_contact_datatable_spec.rb:

  • can_edit is "true" for admin, "false" for a different volunteer's contact
  • can_destroy reflects policy (admin can destroy active contacts; volunteers cannot)
  • edit_path is the correct Rails edit path for the contact
  • followup_id is empty when no requested followup exists
  • followup_id contains the followup id when a requested followup exists

Request specs — updated spec/requests/case_contacts/case_contacts_new_design_spec.rb:

  • Datatable response includes can_edit, can_destroy, edit_path, and followup_id for each row
  • Admin sees can_edit: "true" and can_destroy: "true"
  • Volunteer sees can_edit: "true" for their own contact and can_destroy: "false" for active contacts
  • Volunteer sees can_destroy: "true" for their own draft contacts

Jest — updated app/javascript/__tests__/dashboard.test.js:

Ellipsis column rendering:

  • Toggle button has the correct aria-label containing the contact date
  • Icon is aria-hidden="true"
  • Edit link is rendered when can_edit is "true"; rendered as a disabled <span> when "false"
  • Delete button is rendered when can_destroy is "true"; rendered as a disabled <button> with aria-disabled="true" when "false"
  • Set Reminder is shown when followup_id is empty
  • Resolve Reminder is shown (with data-followup-id) when followup_id is present

Click handlers:

  • Delete: shows a SweetAlert2 confirmation; sends DELETE with CSRF header when confirmed; does not send request when cancelled; reloads DataTable on success
  • Set Reminder: fires SweetAlert2; POSTs with empty params when confirmed without a note; POSTs with { note } when confirmed with a note; does not POST when cancelled; reloads DataTable on success
  • Resolve Reminder: sends PATCH to /followups/:id/resolve with CSRF header; reloads DataTable on success

System specs — updated spec/system/case_contacts/case_contacts_new_design_spec.rb:

Action menu visibility:

  • Ellipsis button opens the dropdown
  • Edit, Delete, Set Reminder, and Resolve Reminder items are present
  • Set Reminder is shown when no followup exists; Resolve Reminder is shown when one does
  • Clicking outside closes the dropdown

Edit action:

  • Navigates to the edit form

Delete action:

  • Confirms then removes the row from the table
  • Cancels and leaves the row in place

Set Reminder action:

  • Confirms then shows Resolve Reminder in the menu (table reloads)
  • Cancels without creating a followup

Resolve Reminder action:

  • Resolves the followup and shows Set Reminder in the menu afterwards
  • Marks the followup record as resolved in the database

Permission states:

  • Delete is rendered as disabled for a volunteer's active contact
  • Delete is rendered as enabled for a volunteer's draft contact

Screen recordings

Edit case contact
edit.contact.mov
Delete case contact
delete.case.contact.mov
Delete disabled for volunteer

A volunteer can only delete a draft case contact. This screen recording shows the Delete disabled for non-drafts and the Delete working for drafts.

volunteer.can.only.delete.drafts.mov
Set reminder
set.reminder.mov
Resolve reminder
resolve.reminder.mov

AI Disclosure

This PR was implemented with the assistance of Claude Code (Anthropic, claude-sonnet-4-6). The AI was used to:

  • Analyze the codebase and existing patterns (Pundit policies, SweetAlert2 usage, CSRF handling) to inform the implementation approach
  • Draft and iterate on code changes across the datatable, controllers, JavaScript, and test files
  • Write and run RSpec request/datatable specs and Jest tests, including debugging test failures caused by DataTables DOM re-rendering behavior
  • Investigate and resolve a CSRF/redirect issue with jQuery following HTML redirects from Rails actions that didn't yet have JSON responses

All generated code was reviewed and committed by the author.

Action menu clipped near bottom of table

When a row is near the bottom of the table, the dropdown action menu may be partially obscured by the table footer or page content below it.

The root cause seems to be overflow-x: hidden on the <body> element, which clips position: absolute elements (including Bootstrap dropdowns) that extend beyond the body's paint area. I'm worried that fixing this globally risks unintended layout side effects elsewhere, so it is left as is.

Menu is hidden by table footer
menu.hidden.by.footer.mov

@github-actions github-actions bot added javascript for use by Github Labeler to mark pull requests that update Javascript code ruby Pull requests that update Ruby code Tests! 🎉💖👏 labels Apr 9, 2026
@cliftonmcintosh cliftonmcintosh force-pushed the feature/6500-case-contacts-new-design-row-actions-menu branch from 36e1e71 to 7a11bdd Compare April 9, 2026 17:36
@cliftonmcintosh cliftonmcintosh self-assigned this Apr 9, 2026
cliftonmcintosh and others added 12 commits April 9, 2026 15:40
Co-Authored-By: claude-sonnet-4-6 <noreply@anthropic.com>
Each row in the new case contacts datatable now has a Bootstrap dropdown
menu with Edit, Delete, and Set/Resolve Reminder actions. Items are shown
or hidden based on per-row Pundit permissions already returned by the
datatable JSON. Delete and Resolve Reminder use AJAX so the table reloads
in place. Set Reminder opens a SweetAlert2 dialog for an optional note.
Backend controllers now respond to JSON for destroy and followup resolve
so jQuery does not follow the HTML redirect.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The delete action in the new case contacts table now shows a
confirmation dialog before sending the DELETE request. Cancelling the
dialog aborts the request. Tests updated to reflect async flow.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Edit and Delete are now rendered as disabled dropdown items when the
current user lacks permission, rather than being omitted from the menu.
Disabled items retain aria-disabled="true" for screen reader accessibility.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@cliftonmcintosh cliftonmcintosh force-pushed the feature/6500-case-contacts-new-design-row-actions-menu branch from b50076e to e59e9ee Compare April 9, 2026 20:41
@cliftonmcintosh cliftonmcintosh changed the title Case contacts new design row actions menu New Case Contacts Table: row actions menu Apr 9, 2026
@cliftonmcintosh cliftonmcintosh force-pushed the feature/6500-case-contacts-new-design-row-actions-menu branch 3 times, most recently from 1600b95 to 92abe1e Compare April 9, 2026 21:59
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@cliftonmcintosh cliftonmcintosh force-pushed the feature/6500-case-contacts-new-design-row-actions-menu branch from 92abe1e to c4370f3 Compare April 9, 2026 22:38
@cliftonmcintosh cliftonmcintosh marked this pull request as ready for review April 9, 2026 23:03
@compwron compwron requested a review from Copilot April 14, 2026 01:13
compwron
compwron previously approved these changes Apr 14, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Implements a per-row ellipsis (⋮) actions dropdown for the new case contacts DataTable at /case_contacts/new_design, wiring the UI to Pundit permissions and followup state.

Changes:

  • Extend the case contacts datatable JSON payload with per-row permissions, edit path, and requested-followup metadata.
  • Add row actions UI (Edit/Delete/Set or Resolve Reminder) and AJAX handlers in the new-design table.
  • Adjust controllers to respond with JSON-friendly 204 No Content for AJAX destroy/resolve, and expand test coverage (system/request/datatable/Jest).

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
spec/system/case_contacts/case_contacts_new_design_spec.rb Adds system coverage for action menu behavior, followup toggling, and permission states.
spec/requests/case_contacts/case_contacts_new_design_spec.rb Verifies datatable JSON includes permission/action metadata per row.
spec/datatables/case_contact_datatable_spec.rb Covers new datatable fields (can_edit, can_destroy, edit_path, followup_id).
app/javascript/src/dashboard.js Replaces placeholder ellipsis with Bootstrap dropdown and adds AJAX handlers for row actions.
app/javascript/src/case_contact.js Exports fireSwalFollowupAlert for reuse by the dashboard action menu.
app/javascript/tests/dashboard.test.js Adds Jest coverage for menu rendering and action click handlers (Swal + AJAX).
app/datatables/case_contact_datatable.rb Adds current_user to compute per-row Pundit permissions and followup metadata.
app/controllers/case_contacts_controller.rb Returns 204 No Content for JSON destroy requests to support AJAX.
app/controllers/case_contacts/followups_controller.rb Returns 204 No Content for JSON resolve requests to support AJAX.
app/controllers/case_contacts/case_contacts_new_design_controller.rb Passes current_user into the datatable initializer.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +22 to +24
policy = CaseContactPolicy.new(current_user, case_contact)
requested_followup = case_contact.followups.find(&:requested?)

Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

case_contact.followups.find(&:requested?) forces loading the full followups association for each case contact and then scans it in Ruby. With .includes(:followups) this can pull a lot of rows into memory even though only the requested followup (if any) is needed. Consider fetching only requested followups (e.g., via a scoped query keyed by the page of case_contact IDs) and then looking up the ID per row, to reduce memory and object allocations.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

has_followup was re-scanning the already-loaded followups collection with any?(&:requested?) when requested_followup was already computed on the line above. Simplified to requested_followup.present?.

Regarding the suggestion to scope the followups query to only load requested followups: the current includes(:followups) does load all followups per record, but in practice each case contact is unlikely to accumulate enough followups for this to be significant. I left this as-is for now but it's a reasonable future improvement if it becomes a concern.

Comment on lines +222 to +226
type: 'DELETE',
dataType: 'json',
headers: { 'X-CSRF-Token': csrfToken() },
success: () => table.ajax.reload()
})
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The AJAX call declares dataType: 'json', but the controller responds with head :no_content (204) for JSON. With jQuery this can surface as a JSON parse error and skip success. Consider removing dataType (or setting it to 'text') or returning a JSON body. Also, table.ajax.reload() defaults to resetting pagination; if the intent is to reload “in place”, pass resetPaging = false so the user stays on the same page.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressee

const { value: text, isConfirmed } = await fireSwalFollowupAlert()
if (!isConfirmed) return
const params = text ? { note: text } : {}
$.post(`/case_contacts/${id}/followups`, params, () => table.ajax.reload())
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This POST does not include the CSRF token, while the other row actions explicitly set X-CSRF-Token. If @rails/ujs isn’t wiring jQuery’s $.post, this request can fail with an invalid authenticity token. Prefer using $.ajax (type POST) and set the same CSRF header, and keep pagination by reloading the DataTable without resetting paging.

Suggested change
$.post(`/case_contacts/${id}/followups`, params, () => table.ajax.reload())
$.ajax({
url: `/case_contacts/${id}/followups`,
type: 'POST',
data: params,
dataType: 'json',
headers: { 'X-CSRF-Token': csrfToken() },
success: () => table.ajax.reload(null, false)
})

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

@cliftonmcintosh cliftonmcintosh Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed dataType: 'json' from the Delete and Resolve Reminder $.ajax calls. I also replaced $.post with $.ajax for Set Reminder to make all three actions consistent. To compensate for losing the Accept: application/json header that dataType was providing implicitly, I added it explicitly to all three calls so Rails correctly routes to the format.json branch. I also added respond_to to followups#create, which was missing and would have caused a redirect to be followed instead of a 204 being returned.

Also changed all three table.ajax.reload() calls to table.ajax.reload(null, false) to keep the user on their current page after an action.

Comment on lines +241 to +245
type: 'PATCH',
dataType: 'json',
headers: { 'X-CSRF-Token': csrfToken() },
success: () => table.ajax.reload()
})
Copy link

Copilot AI Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same concern as delete: dataType: 'json' combined with a 204 No Content JSON response can trigger jQuery parse errors. Consider removing/adjusting dataType or returning a JSON payload. Also consider reloading without resetting paging to keep the user’s place in the table.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment at #6834 (comment)

@compwron
Copy link
Copy Markdown
Collaborator

I may have introduced a lint issue while trying to resolve a merge conflict - feel free to overwrite that but keep the performance improvement please

@cliftonmcintosh
Copy link
Copy Markdown
Collaborator Author

I may have introduced a lint issue while trying to resolve a merge conflict - feel free to overwrite that but keep the performance improvement please

👍🏽

I also accidentally used github's sync fork on this branch instead of main. I'll assess what changed.

I'll also take a look at the copilot review to see if things need adjusting.

cliftonmcintosh and others added 6 commits April 13, 2026 20:37
The missing comma after `has_followup` caused a Ruby syntax error,
preventing the file from loading entirely. Also simplified `has_followup`
to reuse the already-computed `requested_followup` value instead of
scanning the collection a second time.

Added a regression test asserting all action metadata keys are present
in a single row.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
jQuery parses the response body when dataType is 'json', causing a parse
error on the 204 No Content response and skipping the success callback.
Removing dataType lets jQuery accept the empty response and reload the table.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
$.post does not set the X-CSRF-Token header, which can cause Rails to
reject the request with an invalid authenticity token error. Replaced
$.post with $.ajax to match the pattern used by Delete and Resolve Reminder.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…actions

table.ajax.reload() resets to page 1 by default. Passing (null, false)
keeps the user on the current page after Delete, Set Reminder, and
Resolve Reminder actions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…wups#create

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ntactDatatable

Per-row policy checks call same_org? which loads casa_org through casa_case
for every record. Added preload for :casa_org and :creator_casa_org since
includes cannot resolve has_one :through when left_joins is already in the chain.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@cliftonmcintosh
Copy link
Copy Markdown
Collaborator Author

I may have introduced a lint issue while trying to resolve a merge conflict - feel free to overwrite that but keep the performance improvement please

There was a missing comma in CaseContactDatatable#data which may have been introduced during merge conflict resolution (missing comma after has_followup). Fixed, and added a regression test that asserts all action metadata keys are present in a single row so this class of merge error fails immediately.

@cliftonmcintosh
Copy link
Copy Markdown
Collaborator Author

@compwron This is ready for review when you have time. Thanks!

.joins("INNER JOIN users creators ON creators.id = case_contacts.creator_id")
.left_joins(:casa_case)
.includes(:casa_case, :contact_types, :contact_topics, :followups, :creator, contact_topic_answers: :contact_topic)
.preload(:casa_org, :creator_casa_org)
Copy link
Copy Markdown
Collaborator Author

@cliftonmcintosh cliftonmcintosh Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To handle an N+1 warning

21:01:42 web.1  | N+1 queries detected:
21:01:42 web.1  |   SELECT "casa_orgs".* FROM "casa_orgs" INNER JOIN "casa_cases" ON "casa_orgs"."id" = "casa_cases"."casa_org_id" WHERE "casa_cases"."id" = $1 LIMIT $2
21:01:42 web.1  |   SELECT "casa_orgs".* FROM "casa_orgs" INNER JOIN "casa_cases" ON "casa_orgs"."id" = "casa_cases"."casa_org_id" WHERE "casa_cases"."id" = $1 LIMIT $2
21:01:42 web.1  |   SELECT "casa_orgs".* FROM "casa_orgs" INNER JOIN "casa_cases" ON "casa_orgs"."id" = "casa_cases"."casa_org_id" WHERE "casa_cases"."id" = $1 LIMIT $2
21:01:42 web.1  |   SELECT "casa_orgs".* FROM "casa_orgs" INNER JOIN "casa_cases" ON "casa_orgs"."id" = "casa_cases"."casa_org_id" WHERE "casa_cases"."id" = $1 LIMIT $2
21:01:42 web.1  |   SELECT "casa_orgs".* FROM "casa_orgs" INNER JOIN "casa_cases" ON "casa_orgs"."id" = "casa_cases"."casa_org_id" WHERE "casa_cases"."id" = $1 LIMIT $2
21:01:42 web.1  |   SELECT "casa_orgs".* FROM "casa_orgs" INNER JOIN "casa_cases" ON "casa_orgs"."id" = "casa_cases"."casa_org_id" WHERE "casa_cases"."id" = $1 LIMIT $2
21:01:42 web.1  | Call stack:
21:01:42 web.1  |   app/policies/case_contact_policy.rb:57:in 'CaseContactPolicy#same_org?'
21:01:42 web.1  |   app/policies/application_policy.rb:72:in 'ApplicationPolicy#is_supervisor_same_org?'
21:01:42 web.1  |   app/policies/application_policy.rb:89:in 'ApplicationPolicy#admin_or_supervisor_same_org?'
21:01:42 web.1  |   app/policies/case_contact_policy.rb:45:in 'CaseContactPolicy#creator_or_supervisor_or_admin?'
21:01:42 web.1  |   app/policies/case_contact_policy.rb:11:in 'CaseContactPolicy#update?'
21:01:42 web.1  |   app/datatables/case_contact_datatable.rb:49:in 'block in CaseContactDatatable#data'
21:01:42 web.1  |   app/datatables/case_contact_datatable.rb:21:in 'Enumerable#map'
21:01:42 web.1  |   app/datatables/case_contact_datatable.rb:21:in 'CaseContactDatatable#data'
21:01:42 web.1  |   app/datatables/application_datatable.rb:15:in 'ApplicationDatatable#as_json'
21:01:42 web.1  |   app/controllers/case_contacts/case_contacts_new_design_controller.rb:15:in 'CaseContacts::CaseContactsNewDesignController#datatable'

let!(:draft_contact) { create(:case_contact, casa_case: casa_case_for_volunteer, creator: volunteer, status: "started", occurred_at: 10.days.ago) }

before do
Capybara.reset_sessions!
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am curious to know why was this line needed?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without it, the test regularly failed in CI because the admin, who is signed in in the before block at the top of this file, stayed logged in. This made the test for the enable vs disable delete for volunteers invalid. The tests for "shows Delete as disabled for an active contact" for a volunteer would fail because the admin was logged in and admins can delete any case contact. The screenshots captured by CI showed that the admin was still logged in.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's an example screenshot from a test run earlier. We should have the volunteer (User 3) logged in and accessing the menu for their own case contact. But up in the top right we can see that User 2 is logged in.

An aside: note that the menu is partially hidden by the bottom of the data table. I mention this and why I didn't try to fix it in the PR description.

failures_r_spec_example_groups_case_contacts_new_design_permission_states_shows_delete_as_disabled_for_an_active_contact_790

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there is a better way to make sure the volunteer is logged in, please let me know.

Also note that this failed regularly in CI but only intermittently when running the test locally. Not sure why.

Copy link
Copy Markdown
Contributor

@stefannibrasil stefannibrasil Apr 14, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, got it. That's one of the reasons I don't particularly like reusing objects with let and prefer to create the test setup for each test using only what they need (for reference: https://thoughtbot.com/blog/lets-not). I think adding this line is a bit of a code smell but I am not a maintainer of the repo.

Alternatives, if I may, feel free to ignore (haven't tried):

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@stefannibrasil

Thanks for the thoughts. I've made an update that doesn't rely on Capybara.reset_sessions!. It's a slightly different approach.

b4758d1

…min sign-in

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

javascript for use by Github Labeler to mark pull requests that update Javascript code ruby Pull requests that update Ruby code Tests! 🎉💖👏

Projects

None yet

Development

Successfully merging this pull request may close these issues.

New Case Contact Table: implement right-hand side menu for each row

4 participants