Skip to content

feat(integrations-page): add the MyYoast connection card and OAuth client controls#23395

Open
diedexx wants to merge 28 commits into
trunkfrom
DE/rt1168-oauth-client-controls
Open

feat(integrations-page): add the MyYoast connection card and OAuth client controls#23395
diedexx wants to merge 28 commits into
trunkfrom
DE/rt1168-oauth-client-controls

Conversation

@diedexx

@diedexx diedexx commented Jun 23, 2026

Copy link
Copy Markdown
Member
image

Context

Authenticating Yoast AI requests with MyYoast OAuth tokens (the parent feature, PR #23265) needs a way for site admins to actually connect their site to MyYoast: register the site as an OAuth client, complete the authorization-code grant, see the connection state, and disconnect. This PR adds that user-facing surface on the Integrations page, plus the client-side controls and REST/orchestration layer behind it.

This branch is stacked on top of 1207-authenticate-yoast-ai-requests-with-myyoast-oauth-tokens and targets it (not trunk), so the diff is limited to the connection-card work.

Summary

This PR can be summarized in the following changelog entry:

  • Adds a MyYoast connection card on the Integrations page to connect, verify, and disconnect a site using MyYoast OAuth.

Relevant technical choices:

  • The OAuth callback is handled on admin-post.php via the admin_post_* hook (logged-in only, no _nopriv), with CSRF protection via hash_equals on the state parameter and open-redirect prevention via wp_validate_redirect at both the management route and the callback. admin-post is used as a neutral spot in the wp-admin that is accessible to all that can access wp-admin. This helps when implementing a per-user login down the line (see yoast/reserved-tasks#1166)
  • All management REST routes enforce wpseo_manage_options through a shared permission_callback.
  • The connect flow registers the site and immediately continues into the authorization-code grant, so users don't linger on an unverified state.
  • Mount-time status refreshes are throttled to once per hour per issuer via a transient to avoid hammering MyYoast and hitting rate limits quickly. They are done to spot desync issues between the site and MyYoast.
  • Transient OAuth-flow outcomes surface as bottom-left toasts (matching the plugin's notification convention); persistent connection-state messages (connection lost, verification needed, not provisioned) are shown as inline card alerts.

Test instructions

Test instructions for the acceptance test before the PR gets merged

This PR can be acceptance tested by following these steps:
Setup

  • Make sure you have the newest test helper installed with:
    • Enable DB logging
    • Enable Switch to AI staging API
    • In Domain Dropdown select staging-5 as your MyYoast testing domain.
    • In MyYoast OAuth overrides enter your PAT from an admin user (sourced from staging MyYoast), save, and click 'Fetch credentials'. Make sure it now says Stored credentials: yes.

Regression

  1. Make sure YOAST_SEO_MYYOAST_CONNECTION is NOT defined in wp-config.php (or is false).
  2. go to Yoast SEO → Integrations.
  3. Check that there's no MyYoast card. and the console is clean of new errors.

Connect

  1. Enable the feature flag: Add define( 'YOAST_SEO_MYYOAST_CONNECTION', true ); to wp-config.php.
  2. Go to Yoast SEO → Integrations. Confirm a "MyYoast" card appears with the "Unlock more from Yoast with MyYoast" heading, the explanatory copy, a "Learn more" link, and a "Connect your site" button.
  3. Click Connect your site. You should be registered and redirected to MyYoast to sign in. After signing in and being returned to the Integrations page, a success toast (bottom-left, auto-dismissing) should confirm the site is connected, and the card should show "Site connected" with the connected origin listed.
  4. Reload the page. The card should still show the connected state without flashing a "Verification needed" notice.
  5. Change the site's URL (e.g. via WordPress Address in Settings → General on a test site) so it no longer matches the connected domain, then return to the card. It should show the inline "Connection lost" alert with a Reconnect button; clicking it should restore the connection.
  6. Click Disconnect, confirm in the modal, and verify a success toast appears and the card returns to the "Connect your site" state.
  7. Error scenarios: trigger a failed connection (e.g. server can't reach MyYoast) and confirm an error toast appears that does not auto-dismiss. Trigger repeated connection attempts to hit the rate limit and confirm the rate-limited message shows a wait time in minutes/hours.
  8. On a build where the MyYoast connection is not provisioned (can only be the case for staging), confirm the card shows the inline "not configured on this build" warning and no connect button.

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.

QA can test this PR by following these steps:

Impact check

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

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 Yoast/reserved-tasks#1168

diedexx and others added 17 commits June 17, 2026 15:41
…ions

Reintroduces Rate_Limited_Exception and Registration_Not_Found_Exception
(both extending Registration_Failed_Exception) and maps the relevant HTTP
statuses onto them in the registration client: a 429 from DCR, read, or
RFC 7592 update becomes a Rate_Limited_Exception carrying the parsed
Retry-After, and a 401/404 on read/update becomes a
Registration_Not_Found_Exception after clearing the local registration.

This gives the REST layer the retry-after countdown and a distinct
"registration gone" path that the user-facing connection card relies on,
which the generic Registration_Failed_Exception alone could not provide.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds a dedicated OAuth callback endpoint on admin-post.php and registers
it as the site's redirect URI through the client's redirect-URI provider
filters, replacing the base client's placeholder admin-page default. The
endpoint is reachable from any page the flow may have started on; the
per-flow return URL sends the user back to where they began.

On the returning request it exchanges the authorization code — which the
authorization-code handler now also marks the redirect URI validated for
— and stashes a one-shot per-user outcome the connection card surfaces.
Adds Authorization_Code_Handler::discard_flow_state() to clear a pending
flow when the provider returns an error (e.g. the user denied consent).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ent API

Updates the REST management route and status presenter for the reworked
client: registration takes no caller-supplied redirect URIs (the client
resolves them itself), so register and the URL-change recovery both call
ensure_registered(), and authorize no longer accepts or validates a
redirect_uri — the client picks the registered one.

The status presenter now reports real per-URI verification state via the
registration's is_uri_validated(), and derives redirect_uris_match from
the redirect-URI provider instead of a standalone builder.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds the MyYoast connection card to the Recommended integrations section:
a standalone wp.data store seeded from the localized status, the card UI
(connect, per-state notices for connection-lost and verification-needed,
disconnect via a confirm modal), and the entry/recommended-integrations
wiring. Connecting continues straight into the authorization-code flow.

The verify/authorize action no longer sends a redirect URI — the client
resolves the registered one — and heroicons are imported per-icon to
satisfy the current lint rule.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The remote registration liveness check was named "verify", which collided
with the cryptographic Jwt_Signer::verify and, more confusingly, with the
site-verification product feature in the integrations UI (isVerified,
verificationNeeded, handleVerify). Renaming to refresh_registration_status /
refresh-status disambiguates the two and better reflects that the call
reconciles local state with the server, self-healing by forgetting the
registration on 401/404 rather than performing a pure check.

Renames the application facade method, the REST route (POST
/myyoast/refresh-status) and its callback, the WP-CLI subcommand
(wp yoast auth refresh-status), the JS store endpoint/action, and the
corresponding unit tests. The crypto verify and all site-verification
identifiers are left untouched.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…he App layer

Move the authorization-code callback use-case out of the UI integration and
into a new App-layer OAuth_Callback_Handler plus a Callback_Outcome value
object. The handler does the transport-agnostic work — discard pending flow
state on a provider error, exchange the code, persist the outcome for one-shot
surfacing, and report it in neutral OAuth terms — so any consumer (admin-post
endpoint, REST route, WP-CLI) can drive it and translate the outcome onto its
own surface.

OAuth_Callback_Integration now only extracts the request parameters and
delegates; Integrations_Page_Script_Data consumes the stored outcome through
the handler and maps it to the front-end message keys. This keeps the onion
dependency rule intact: the orchestration lives in App, the WordPress-specific
adapters stay in User_Interface.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…he OAuth return URL

Two additions to the MyYoast management route:

Refresh throttle — a successful upstream status refresh now sets a short-lived,
issuer-scoped marker that suppresses further upstream reads for an hour, so the
integrations page reloading does not hit MyYoast's aggressive RFC 7592 rate
limit. Only the fact that we checked is stored, never the response body, so the
endpoint's no-store contract holds. Connect, re-sync, and disconnect clear the
marker so a deliberate state change is reflected on the next read. A failed or
rate-limited attempt does not set the marker, leaving the next retry free.

Caller-supplied return URL — POST /myyoast/authorize accepts an optional
return_url, since the flow can be started from admin pages other than the
integrations page. It is validated against the site's own host and dropped when
off-site or invalid (the callback re-validates before redirecting, so this is
the first of two open-redirect gates). When absent, null flows through and the
callback surfaces a standalone outcome instead of redirecting.

Also narrows the over-broad Throwable catches to the exception types each
endpoint can actually raise, and renames respond_with_status to
respond_with_connection_status for clarity.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…re folder

Restructure the MyYoast connection from loose files plus a flat
`myyoast-store.js` into a self-contained feature folder, matching the
`ai-generator` and `introductions` layout where a feature directory is
named for the store it owns.

- Split the store into a `store/` directory: a `myyoast-connection`
  slice module and an `index.js` that builds and registers it.
- Register through `createReduxStore` + `register` rather than the
  deprecated `registerStore`.
- Centralize the store name in `constants.js` so the store and its
  consumers share one address without a circular import.
- Add unit tests for the slice, generator actions, controls-driven
  branches, selectors, and the status transform.
- Surface backend message codes through a `messageFor` switch so only
  the matched string is translated at call time.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The authorize action accepted a return URL, but the card never passed one,
so after the OAuth round-trip the backend fell back to its default instead
of returning the user to the integrations page.

Pass the current page as the return URL from both the connect and verify
flows. The backend validates it and ignores it when off-site or invalid.

Take the return URL as a named option (`{ returnUrl }`) so the call site is
self-documenting and the action can grow more options without a signature
change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…necting

Connecting registers the site as an OAuth client and then redirects to
MyYoast to complete the authorization-code grant. Registration leaves the
site registered-but-unverified, and `window.location.assign` navigates
asynchronously, so the card kept rendering — and briefly showed the
"Verification needed" notice — while the MyYoast page loaded.

Track the connect flow with a local `isConnecting` flag that suppresses the
notice, and keep it set through the redirect tail. It is cleared only when
we stay on the page (registration failed, or authorize returned no URL) so
the notice and error still surface there. Scoped to the connect auto-flow,
so a deliberate verify click still shows its context.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The OAuth callback emits one success notice for both first-time setup and a
standalone re-verify, so "This site is now verified" read as jargon right
after connecting. Describe the end state instead: the connection is active.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the trailing underscore from the prefix constant and the redundant
rtrim() that stripped it, so the throttle key is built in one step. The
resulting transient key is unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reword the card heading and description to lead with the offline/firewall
benefit, and replace the terse connection-lost message with an actionable
one explaining that the site's URL changed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…y_after_seconds

The parameter was only documented in PHPDoc; add the native type
declaration to match the rest of the class and enable static analysis.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ith no fallback

AI_Request_Sender::send rethrew the primary strategy's exception silently
when no fallback was configured, unlike the fallback paths which log. Add a
matching warning before the rethrow so the failure is traceable.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…nection

Drop the top border and padding on the registered-state section so the
site-connection details no longer sit under a horizontal rule.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…oasts

Move the transient connect/verify/reconnect/disconnect and OAuth callback
outcomes from an inline card Alert to a bottom-left toast, matching the
notification pattern used elsewhere in the plugin. Each outcome carries a
fresh id so the toast remounts and re-animates. Success toasts auto-dismiss
after five seconds; errors persist until dismissed. The connection-state
alerts (connection lost, verification needed, not provisioned) stay inline.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@diedexx diedexx added component: interface Visual interface problems or enhancements changelog: enhancement Needs to be included in the 'Enhancements' category in the changelog labels Jun 23, 2026
@coveralls

coveralls commented Jun 23, 2026

Copy link
Copy Markdown

Coverage Report for CI Build 0

Warning

No base build found for commit 29a3539 on 1207-authenticate-yoast-ai-requests-with-myyoast-oauth-tokens.
Coverage changes can't be calculated without a base build.
If a base build is processing, this comment will update automatically when it completes.

Coverage: 44.544%

Details

  • Patch coverage: 222 uncovered changes across 17 files (459 of 681 lines covered, 67.4%).

Uncovered Changes

Top 10 Files by Coverage Impact Changed Covered %
packages/js/src/integrations-page/myyoast-connection/myyoast-integration.js 122 0 0.0%
src/myyoast-client/user-interface/management-route.php 203 182 89.66%
src/myyoast-client/application/oauth-callback-handler.php 44 24 54.55%
packages/js/src/integrations-page/myyoast-connection/store/myyoast-connection.js 77 62 80.52%
src/myyoast-client/infrastructure/registration/client-registration.php 19 9 47.37%
packages/js/src/integrations-page/myyoast-connection/store/index.js 7 0 0.0%
src/myyoast-client/application/callback-outcome.php 39 34 87.18%
src/myyoast-client/user-interface/status-presenter.php 59 54 91.53%
packages/js/src/integrations-page/myyoast-connection/myyoast-disconnect-modal.js 4 0 0.0%
packages/js/src/integrations-page/recommended-integrations.js 3 0 0.0%
Total (22 files) 681 459 67.4%

Coverage Regressions

Requires a base build to compare against. How to fix this →


Coverage Stats

Coverage Status
Relevant Lines: 60941
Covered Lines: 28481
Line Coverage: 46.74%
Relevant Branches: 11725
Covered Branches: 3887
Branch Coverage: 33.15%
Branches in Coverage %: Yes
Coverage Strength: 5.61 hits per line

💛 - Coveralls

…the card

The verification-needed tooltip used a centered top position on an icon
pinned to the card's right edge, so it overflowed the card's overflow-hidden
boundary and clipped its text. Anchor it to the right (top-left) and narrow
it so it stacks taller and stays within the card.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

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.

Pull request overview

Adds the MyYoast connection surface and supporting backend/REST/OAuth callback plumbing needed for site admins to connect, verify, and disconnect a site from MyYoast via OAuth, exposed on the Integrations page and backed by a small orchestration layer (status presenter, management route, callback integration + outcome persistence).

Changes:

  • Adds MyYoast connection status/script-data providers and wires them into the Integrations page localized payload, plus a new React “MyYoast” card and data store.
  • Introduces REST management endpoints for registration/refresh/authorize/deregister, and an admin-post.php OAuth callback handler that records one-shot outcomes for UI toasts.
  • Extends MyYoast client registration handling with typed exceptions for “registration gone” and “rate limited” (including Retry-After parsing), plus additional tests.

Reviewed changes

Copilot reviewed 36 out of 37 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tests/Unit/MyYoast_Client/User_Interface/Status_Presenter_Test.php Unit coverage for the status payload shaping (provisioned/registered/redirect URI state).
tests/Unit/MyYoast_Client/User_Interface/OAuth_Callback_Integration_Test.php Tests for the admin-post callback integration wiring and return-url behavior.
tests/Unit/MyYoast_Client/User_Interface/Management_Route_Test.php Tests for the MyYoast management REST endpoints and exception mapping.
tests/Unit/MyYoast_Client/User_Interface/Integrations_Page_Script_Data_Test.php Tests for Integrations page script-data shaping (status/profile URL/callback outcome).
tests/Unit/MyYoast_Client/Infrastructure/WordPress/Redirect_URI_Provider_Test.php Updates redirect URI expectations to the admin-post callback endpoint.
tests/Unit/MyYoast_Client/Infrastructure/Registration/Client_Registration_Test.php Adds coverage for 401/404 “gone” and 429 rate-limiting behaviors.
tests/Unit/MyYoast_Client/Application/Registration_Not_Found_Exception_Test.php Unit coverage for the new typed “registration gone” exception.
tests/Unit/MyYoast_Client/Application/Rate_Limited_Exception_Test.php Unit coverage for the new rate-limit exception and Retry-After parsing.
tests/Unit/MyYoast_Client/Application/OAuth_Callback_Handler_Test.php Tests the callback handler orchestration and outcome persistence/consumption.
tests/Unit/MyYoast_Client/Application/Callback_Outcome_Test.php Unit tests for the callback outcome value object and array round-trip.
tests/Unit/Integrations/Admin/Integrations_Page_Integration_Test.php Updates integrations-page localization payload tests to include myyoast_connection.
tests/Unit/AI/Authentication/Application/AI_Request_Sender/AI_Request_Sender_Test.php Adds test coverage for new warning logging when no fallback is configured.
src/myyoast-client/user-interface/status-presenter.php New presenter building the minimal status payload for the connection card/UI.
src/myyoast-client/user-interface/oauth-callback-integration.php New admin-post OAuth callback integration that drives the callback handler and redirects back.
src/myyoast-client/user-interface/management-route.php New REST management endpoints for status/refresh/register/update/authorize/deregister.
src/myyoast-client/user-interface/integrations-page-script-data.php New script-data provider for Integrations page boot payload (status, profile URL, callback toast outcome).
src/myyoast-client/user-interface/auth-command.php Renames/adjusts WP-CLI subcommand to “refresh-status” and updates messaging.
src/myyoast-client/infrastructure/wordpress/redirect-uri-provider.php Switches canonical redirect URI to the admin-post callback endpoint.
src/myyoast-client/infrastructure/registration/client-registration.php Adds typed exceptions for 401/404 and 429 handling + Retry-After extraction.
src/myyoast-client/application/oauth-callback-handler.php New callback orchestration that exchanges code and persists a one-shot outcome per user.
src/myyoast-client/application/myyoast-client.php Renames verify method to refresh_registration_status() and updates doc.
src/myyoast-client/application/exceptions/registration-not-found-exception.php New typed exception for “registration no longer exists”.
src/myyoast-client/application/exceptions/rate-limited-exception.php New typed exception for rate limiting with retry-after support.
src/myyoast-client/application/callback-outcome.php New value object describing callback outcomes in OAuth terms.
src/myyoast-client/application/authorization-code-handler.php Refactors flow-state deletion into a reusable discard_flow_state() method.
src/integrations/admin/integrations-page.php Injects/exports MyYoast connection script-data into the Integrations page payload.
src/integrations/admin/helpscout-beacon.php Switches integrations page reference to Integrations_Page::PAGE.
src/ai/authentication/application/ai-request-sender.php Adds warning log when primary strategy fails and no fallback exists.
packages/js/tests/integrations-page/myyoast-connection/store/myyoast-connection.test.js Jest coverage for MyYoast connection store reducers/selectors/actions.
packages/js/src/integrations-page/recommended-integrations.js Prepends the MyYoast card when the localized payload is present (feature flag on).
packages/js/src/integrations-page/myyoast-connection/store/myyoast-connection.js Implements the MyYoast connection slice + generator actions + REST controls.
packages/js/src/integrations-page/myyoast-connection/store/index.js Registers the standalone WP data store seeded from wpseoIntegrationsData.
packages/js/src/integrations-page/myyoast-connection/myyoast-integration.js Adds the MyYoast connection card UI, action flows, and toast surfacing.
packages/js/src/integrations-page/myyoast-connection/myyoast-disconnect-modal.js Adds the disconnect confirmation modal UI.
packages/js/src/integrations-page/myyoast-connection/constants.js Adds store-name constant to avoid circular imports.
packages/js/src/integrations-page.js Registers the MyYoast store on page load before rendering.
packages/js/images/myyoast-logo.svg Adds the MyYoast logo asset for the card header.

Comment thread src/myyoast-client/user-interface/oauth-callback-integration.php Outdated
Comment thread tests/Unit/MyYoast_Client/User_Interface/Management_Route_Test.php Outdated
Comment thread packages/js/src/integrations-page/myyoast-connection/myyoast-integration.js Outdated
Comment thread src/myyoast-client/user-interface/management-route.php
diedexx and others added 6 commits June 24, 2026 10:27
…es it

The authorize endpoint returned invalid_user with HTTP 401, but the JS store
reads error_code only from successful (2xx) bodies; api-fetch rejects non-2xx,
so the dedicated invalid_user message was masked as a generic unexpected_error.
Return it as HTTP 200 with the error_code in the body, like every other failure
on this endpoint.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ference

The redirect-URI provider and OAuth callback integration docblocks still
described the canonical redirect URI as an admin page reached via provider
filters, but it is now the admin-post.php callback endpoint resolved directly
from get_callback_url(). Also fixes a @Covers annotation that referenced the
renamed respond_with_connection_status method.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… UTM-tag outbound links

The integrations page never registered the yoast-seo/settings store, so the
selectLink machinery the other cards rely on is unavailable here. Surface the
short-link query params through the MyYoast script data and store instead, so
the card can append the same attribution params the other cards carry.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…other cards

Switch the bespoke anchor to the shared Link component, the RTL-aware
ArrowSmRightIcon, and the same markup the SimpleIntegration cards use, and add
the missing screen-reader 'opens in a new tab' text. Point the link at the real
integrations-myyoast URL and append the localized UTM params so it carries the
same attribution as the other cards.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…f showing a fake error

A double-click on "Connect your site" before the button re-rendered as disabled
let the second click hit runAction's in-flight guard, which returns the
action_in_flight sentinel. handleConnect routed that through resolveErrorMessage,
where messageFor has no matching case and falls back to the generic "Something
went wrong" string, surfacing a spurious error toast for an action that was
deliberately dropped. Extract the sentinel to a named constant and detect it in
handleConnect so the dropped action is ignored silently.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ectors

The profileUrl was computed in PHP (admin_url('profile.php')), localized, stored,
and exposed via a selector, but no component ever read it; likewise
selectMyyoastConnectionProfileUrl, selectHasMyyoastConnection, and
selectMyyoastConnectionActionError were referenced only by their own tests. Remove
the field, its localization, the PHP computation, and the three unused selectors
along with their assertions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
diedexx and others added 4 commits June 24, 2026 15:48
…ction

The error_message_key() docblock referenced buildMessages() in
myyoast-integration.js, but the front-end maps message keys to copy in
messageFor(). Correct the reference so a maintainer adding an error code can find
the matching JS handler.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… unconnected MyYoast card

The design specs a 2px yoast-purple/200 (#e0b3cc) border on the MyYoast
connection card, which the initial build missed. Add an optional className prop
to the shared integrations Card (appended so a consumer can override the default
border) and pass yst-border-2 yst-border-primary-200 from the MyYoast card only
while the site is not yet connected; once registered the outline is dropped so
the card blends in with the others. The other integration cards are unchanged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tokens' of github.com:Yoast/wordpress-seo into DE/rt1168-oauth-client-controls
…tokens' of github.com:Yoast/wordpress-seo into DE/rt1168-oauth-client-controls
Base automatically changed from 1207-authenticate-yoast-ai-requests-with-myyoast-oauth-tokens to trunk June 26, 2026 08:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog: enhancement Needs to be included in the 'Enhancements' category in the changelog component: interface Visual interface problems or enhancements

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants