Skip to content

fix: prevent duplicate error notifications on flow publish#3929

Open
srushti-55 wants to merge 7 commits into
glific:masterfrom
srushti-55:master
Open

fix: prevent duplicate error notifications on flow publish#3929
srushti-55 wants to merge 7 commits into
glific:masterfrom
srushti-55:master

Conversation

@srushti-55
Copy link
Copy Markdown

@srushti-55 srushti-55 commented May 7, 2026

When clicking "Publish & go back", publishLoading was never set, leaving both publish buttons active. A second click would fire a second mutation, and both onError callbacks would call setNotification, showing the same error toast twice.

Guard handlePublishFlow with publishLoading and centralise setPublishLoading(true) there so no duplicate mutations can fire regardless of which publish button is clicked.

Fixes #3499

Summary

Test Plan

Summary by CodeRabbit

  • Bug Fixes

    • Prevented duplicate flow publish actions from being initiated while a publish is already in progress, avoiding concurrent publish conflicts and accidental double-submissions.
  • Tests

    • Added a test that verifies the UI blocks additional publish attempts while the first publish is loading and displays the appropriate error dialog when a second attempt is made.

Review Change Stack

When clicking "Publish & go back", publishLoading was never set,
leaving both publish buttons active. A second click would fire a
second mutation, and both onError callbacks would call setNotification,
showing the same error toast twice.

Guard handlePublishFlow with publishLoading and centralise
setPublishLoading(true) there so no duplicate mutations can fire
regardless of which publish button is clicked.

Fixes glific#3499
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 7, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0e22fdad-950d-4525-8e9b-9ce16be288d9

📥 Commits

Reviewing files that changed from the base of the PR and between f6db5ac and 2575c9d.

📒 Files selected for processing (1)
  • src/components/floweditor/FlowEditor.test.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/floweditor/FlowEditor.test.tsx

Walkthrough

The change adds an early-return guard in FlowEditor.handlePublishFlow: if publishLoading is true the handler returns immediately, and it now sets publishLoading = true before invoking publishFlow. A new test simulates a publish in progress, verifies the confirmation OK button is disabled during loading, attempts a second publish, and asserts the error/validation dialog appears.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

I’m a rabbit in the code, I tap and wait, 🐇
One click starts the journey, then I hesitate,
No second thump to start the race,
One publish blossoms in its place,
I munch a carrot as the spinner hums.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: preventing duplicate error notifications when publishing a flow by adding a publishLoading guard and centralizing state management.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 8, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 81.24%. Comparing base (be7cc88) to head (2575c9d).

❌ Your project check has failed because the head coverage (81.24%) is below the target coverage (82.38%). You can increase the head coverage or adjust the target coverage.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #3929      +/-   ##
==========================================
+ Coverage   81.19%   81.24%   +0.04%     
==========================================
  Files         319      319              
  Lines       13871    13872       +1     
  Branches     3248     3249       +1     
==========================================
+ Hits        11263    11270       +7     
+ Misses       1615     1610       -5     
+ Partials      993      992       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/components/floweditor/FlowEditor.test.tsx (1)

186-210: ⚡ Quick win

The test doesn't actually verify that only one mutation is fired.

The stated intent is "should not fire a second publish mutation while one is already in progress," but the final assertion only checks that the error dialog text appears — which is produced by the first mutation's onError callback and would appear regardless of whether the guard fires or not.

If the guard in handlePublishFlow were removed, the second click on middle-button would dispatch a second publishFlow mutation. activeFlowMocks contains only one publishFlow mock, so the second mutation would receive an Apollo "no more mocked responses" error. Its onError callback would still call setNotification, and screen.getByText(...) would still find the dialog — meaning this test would still pass without the guard.

To meaningfully assert the guard's invariant, spy on the mutation directly:

🔧 Proposed fix: spy on the mutation call-count
 import * as Apollo from '@apollo/client';
 test('should not fire a second publish mutation while one is already in progress', async () => {
+  const useMutationSpy = vi.spyOn(Apollo, 'useMutation');
   const { getByTestId } = render(defaultWrapper);
 
   await waitFor(() => expect(getByTestId('button')).toBeInTheDocument());
 
   fireEvent.click(getByTestId('button'));
 
   await waitFor(() => expect(getByTestId('ok-button')).toBeInTheDocument());
 
+  // Capture the publish mutation's execute function after first render
+  const publishMutationFn = vi.fn();
+  // ... OR alternatively, track via MockedProvider by asserting no
+  // "No more mocked responses" console.error fires:
+  const consoleErrorSpy = vi.spyOn(console, 'error');
+
   // First publish — sets publishLoading=true
   fireEvent.click(getByTestId('ok-button'));
 
   await waitFor(() => expect(getByTestId('ok-button')).toBeDisabled());
 
   // Second attempt via middle button while loading — guard should block it
   fireEvent.click(getByTestId('middle-button'));
 
   await waitFor(() => {
     expect(
       screen.getByText('Errors were detected in the flow. Would you like to continue modifying?')
     ).toBeInTheDocument();
   });
+
+  // Guard invariant: no "No more mocked responses" error means only one mutation fired
+  expect(consoleErrorSpy).not.toHaveBeenCalledWith(
+    expect.stringContaining('No more mocked responses')
+  );
+  consoleErrorSpy.mockRestore();
 });

A simpler alternative is asserting that console.error was not called with Apollo's "No more mocked responses for PublishFlow..." message. Since activeFlowMocks provides exactly one publishFlow mock, any second mutation dispatch will cause that error — making it a reliable canary for duplicate mutations.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/components/floweditor/FlowEditor.test.tsx` around lines 186 - 210, The
test currently only checks for the error dialog but not whether a second publish
mutation was dispatched; update the test to assert the mutation was called only
once by spying on the GraphQL mutation or on console.error: e.g., create a spy
for the PublishFlow mutation call (or jest.spyOn(console, 'error')) before
triggering clicks, trigger the first publish via ok-button and the second click
on middle-button, then assert the PublishFlow mutation spy was called exactly
once (or that console.error was not called with Apollo's "No more mocked
responses for `PublishFlow`..." message). Reference handlePublishFlow,
publishFlow, activeFlowMocks, ok-button and middle-button when locating the code
to change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/components/floweditor/FlowEditor.test.tsx`:
- Around line 186-210: The test currently only checks for the error dialog but
not whether a second publish mutation was dispatched; update the test to assert
the mutation was called only once by spying on the GraphQL mutation or on
console.error: e.g., create a spy for the PublishFlow mutation call (or
jest.spyOn(console, 'error')) before triggering clicks, trigger the first
publish via ok-button and the second click on middle-button, then assert the
PublishFlow mutation spy was called exactly once (or that console.error was not
called with Apollo's "No more mocked responses for `PublishFlow`..." message).
Reference handlePublishFlow, publishFlow, activeFlowMocks, ok-button and
middle-button when locating the code to change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 62217987-5f27-4757-8f4d-9a0cb27450cc

📥 Commits

Reviewing files that changed from the base of the PR and between ec85add and 2456596.

📒 Files selected for processing (1)
  • src/components/floweditor/FlowEditor.test.tsx

@priyanshu6238
Copy link
Copy Markdown
Collaborator

priyanshu6238 commented May 8, 2026

E2E ci test case will fail. you can ignore it

Copy link
Copy Markdown
Collaborator

@priyanshu6238 priyanshu6238 left a comment

Choose a reason for hiding this comment

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

test case is failing can you fix it?

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/floweditor/FlowEditor.test.tsx`:
- Around line 195-218: The test creates a console error spy (consoleErrorSpy)
but calls consoleErrorSpy.mockRestore() at the end unguarded, so if waitFor() or
assertions throw the spy is leaked; wrap the test body (the fireEvent clicks,
waitFor(...) and expect(...) checks) in a try/finally and call
consoleErrorSpy.mockRestore() from the finally block to guarantee cleanup of
consoleErrorSpy regardless of test failures.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 4736a1f6-1aac-48a5-9250-ae9b844c9d8a

📥 Commits

Reviewing files that changed from the base of the PR and between 2456596 and f6db5ac.

📒 Files selected for processing (1)
  • src/components/floweditor/FlowEditor.test.tsx

Comment thread src/components/floweditor/FlowEditor.test.tsx Outdated
@srushti-55
Copy link
Copy Markdown
Author

Hi, could you please approve the CI workflows to run?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flow publish - Same error showing two times

2 participants