Skip to content

3070 bulk editor during ai generation user can edit manually#23452

Merged
FAMarfuaty merged 9 commits into
release/28.1from
3070-bulk-editor-during-ai-generation-user-can-edit-manually
Jul 15, 2026
Merged

3070 bulk editor during ai generation user can edit manually#23452
FAMarfuaty merged 9 commits into
release/28.1from
3070-bulk-editor-during-ai-generation-user-can-edit-manually

Conversation

@pls78

@pls78 pls78 commented Jul 14, 2026

Copy link
Copy Markdown
Member

Context

Note: to be tested together with https://github.com/Yoast/wordpress-seo-premium/pull/5021

Summary

This PR can be summarized in the following changelog entry:

  • Disables the "Edit" button for posts that have a pending AI Generate call.

Relevant technical choices:

  • N/A

Test instructions

Test instructions for the acceptance test before the PR gets merged

This PR can be acceptance tested by following these steps:

Prerequisites

  • Have Premium installed and active with a valid subscription
    • Make sure your site either has a public URL or you're using OAuth as your authentication mechanism
  • Have some posts with a focus keyphrase set

Test the fix

  • Go to Yoast -> Tools -> Bulk editor
  • Select some posts that have a focus keyphrase and bulk-generate e.g. their SEO titles
    • Verify the Edit button stays deactivated while the AI generation is running

Relevant test scenarios

  • Changes should be tested with the browser console open
  • Changes should be tested on different posts/pages/taxonomies/custom post types/custom taxonomies
  • Changes should be tested on different editors (Default Block/Gutenberg/Classic/Elementor/other)
  • Changes should be tested on different browsers
  • Changes should be tested on multisite

Test instructions for QA when the code is in the RC

  • QA should use the same steps as above.

Impact check

This PR affects the following parts of the plugin, which may require extra testing:

  • N/A

Other environments

  • This PR also affects Shopify. I have added a changelog entry starting with [shopify-seo], added test instructions for Shopify and attached the Shopify label to this PR.
  • This PR also affects Yoast SEO for Google Docs. I have added a changelog entry starting with [yoast-doc-extension], added test instructions for Yoast SEO for Google Docs and attached the Google Docs Add-on label to this PR.

Documentation

  • I have written documentation for this change. For example, comments in the Relevant technical choices, comments in the code, documentation on Confluence / shared Google Drive / Yoast developer portal, or other.

Quality assurance

  • I have tested this code to the best of my abilities.
  • During testing, I had activated all plugins that Yoast SEO provides integrations for.
  • [] I have added unit tests to verify the code works as intended.
  • If any part of the code is behind a feature flag, my test instructions also cover cases where the feature flag is switched off.
  • I have written this PR in accordance with my team's definition of done.
  • I have checked that the base branch is correctly set.
  • I have run grunt build:images and committed the results, if my PR introduces or edits images or SVGs.

Innovation

  • No innovation project is applicable for this PR.
  • This PR falls under an innovation project. I have attached the innovation label.
  • I have added my hours to the WBSO document.

Fixes https://github.com/Yoast/plugins-automated-testing/issues/3070

@pls78 pls78 added this to the 28.1 milestone Jul 14, 2026
@pls78 pls78 added the changelog: non-user-facing Needs to be included in the 'Non-userfacing' category in the changelog label Jul 14, 2026
@github-actions

Copy link
Copy Markdown

A merge conflict has been detected for the proposed code changes in this PR. Please resolve the conflict by either rebasing the PR or merging in changes from the base branch.

@coveralls

coveralls commented Jul 14, 2026

Copy link
Copy Markdown

Coverage Report for CI Build 15

Coverage increased (+0.006%) to 55.185%

Details

  • Coverage increased (+0.006%) from the base build.
  • Patch coverage: 11 of 11 lines across 5 files are fully covered (100%).
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 72125
Covered Lines: 39682
Line Coverage: 55.02%
Relevant Branches: 18766
Covered Branches: 10476
Branch Coverage: 55.82%
Branches in Coverage %: Yes
Coverage Strength: 41727.04 hits per line

💛 - Coveralls

@pls78
pls78 marked this pull request as ready for review July 14, 2026 11:55
describe( "BulkEditorTable", () => {
beforeAll( () => {
// The rows read the external-generation flag from the store, so it must be registered.
registerStore();

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.

The new hasExternalGeneration path isn't covered by a test. registerStore() in beforeAll keeps the existing tests green now that the row reads the store, but nothing asserts the actual new behaviour — that Edit disables table-wide when the flag is set. There's a dedicated test for the sibling flag (disables every row's Edit button while Premium AI suggestions are pending review), and this deserves the mirror:

it( "disables every row's Edit button while an external AI generation is in flight", () => {
    dispatch( STORE_NAME ).setHasExternalGeneration( true );
    render( <BulkEditorTable items={ items } fieldSet={ searchFieldSet } /> );
    expect( screen.getByRole( "button", { name: "Edit What Is SEO" } ) ).toBeDisabled();
    expect( screen.getByRole( "button", { name: "Edit On-Page SEO Checklist" } ) ).toBeDisabled();
    dispatch( STORE_NAME ).setHasExternalGeneration( false ); // reset — the store is a shared singleton across this file
} );

Note the reset: because the store is registered once in beforeAll, a true left set here leaks into every later test in the file. Worth also adding a small reducer test under store/external-generation.test.js to match external-pending-changes.test.js.

const fillsMetaDescription = useSlotFills( `${ TABLE_CELL_FIELD_SLOT }/metaDescription/${item.id}` );
const fillsSocialTitle = useSlotFills( `${ TABLE_CELL_FIELD_SLOT }/socialTitle/${item.id}` );
const fillsSocialDescription = useSlotFills( `${ TABLE_CELL_FIELD_SLOT }/socialDescription/${item.id}` );
const hasExternalGeneration = useSelect( ( select ) => select( STORE_NAME ).selectHasExternalGeneration(), [] );

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.

Consistency nit (non-blocking): the sibling flag hasExternalPendingChanges is selected once in bulk-editor-content.js and drilled down as a prop (bulk-editor-tabletable-bodytable-row), whereas hasExternalGeneration is read here with useSelect inside every row. Two conceptually identical global flags now follow two different patterns, and this variant adds a per-row store subscription (N per page) instead of one at the top. Unless there's a reason to diverge, I'd source it the same way as hasExternalPendingChanges and pass it through as a prop — it keeps the row presentational and the two flags symmetrical.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Damn, I thought about avoiding prop drilling and didn't think about the multiplication of the store subscription...

@FAMarfuaty FAMarfuaty added the innovation Innovative issue. Relating to performance, memory or data-flow. label Jul 14, 2026
@FAMarfuaty

Copy link
Copy Markdown
Contributor

CR & Acceptance: ✅

@FAMarfuaty
FAMarfuaty merged commit 15dd1c8 into release/28.1 Jul 15, 2026
23 checks passed
@FAMarfuaty
FAMarfuaty deleted the 3070-bulk-editor-during-ai-generation-user-can-edit-manually branch July 15, 2026 09:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog: non-user-facing Needs to be included in the 'Non-userfacing' category in the changelog innovation Innovative issue. Relating to performance, memory or data-flow.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants