Administration: Handle AJAX failures for plugin and theme actions - #12654
Administration: Handle AJAX failures for plugin and theme actions#12654ArkaPrabhaChowdhury wants to merge 3 commits into
Conversation
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
There was a problem hiding this comment.
Pull request overview
This PR improves resilience of wp-admin plugin/theme update interactions by restoring UI controls and providing clearer messaging when AJAX requests fail or return invalid responses (e.g., maintenance mode / network issues).
Changes:
- Restore plugin/theme deletion UI controls after failed/invalid AJAX responses.
- Improve auto-update toggle failure messaging and restore toggle labels after failures.
- Add QUnit coverage for deletion failures and auto-update failure/invalid-response scenarios.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| tests/qunit/wp-admin/js/updates.js | Adds QUnit tests covering deletion and auto-update failure recovery behaviors. |
| src/js/_enqueues/wp/updates.js | Updates deletion and auto-update handlers to restore UI state and improve failure messaging. |
Comments suppressed due to low confidence (2)
src/js/_enqueues/wp/updates.js:1512
- The delete link is restored with
.text()even thoughoriginaltextwas captured via.html(). Using.html()avoids stripping markup and avoids accidentally clearing the label whenoriginaltextis missing.
$deleteLink = $plugin.find( '.row-actions a.delete' );
$deleteLink.text( $deleteLink.data( 'originaltext' ) );
tests/qunit/wp-admin/js/updates.js:208
- This test stubs
wp.ajax.sendbut never restores it, which can leak into other test files and change global Ajax behavior. Restore the stub at the end of the test.
sinon.stub( wp.ajax, 'send' ).returns( jQuery.Deferred().promise() );
wp.updates.deleteTheme( { slug: 'twentyeleven' } );
wp.ajax.send.firstCall.args[ 0 ].error( 'Briefly unavailable for scheduled maintenance.' );
assert.strictEqual( $button.text(), 'Delete', 'The delete button text is restored.' );
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| sinon.stub( wp.ajax, 'send' ).returns( jQuery.Deferred().promise() ); | ||
|
|
||
| wp.updates.deletePlugin( { slug: 'jetpack', plugin: 'jetpack/jetpack.php' } ); | ||
| wp.ajax.send.firstCall.args[ 0 ].error( 'Briefly unavailable for scheduled maintenance.' ); | ||
|
|
||
| assert.strictEqual( $pluginRow.find( 'a.delete' ).text(), 'Delete', 'The delete link text is restored.' ); | ||
| } ); |
| afterEach: function() { | ||
| window.pagenow = this.oldPagenow; | ||
| } | ||
| } ); |
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (3)
src/js/_enqueues/wp/updates.js:1512
deletePlugin()stores the original delete-link markup via$link.html()/data( 'originaltext' ), but the error handler restores it using.text(), which will strip any markup and can change the link label if it contains HTML (e.g., screen-reader text). Restore with.html()for consistency and to avoid altering the original content.
$deleteLink = $plugin.find( '.row-actions a.delete' );
$deleteLink.text( $deleteLink.data( 'originaltext' ) );
tests/qunit/wp-admin/js/updates.js:139
- This test stubs
wp.ajax.sendbut never restores it, which can leak into later tests and change behavior (other QUnit tests in this suite typically restore stubs inafterEach, e.g.tests/qunit/wp-admin/js/customize-header.js:10-12). Please restore the stub at the end of the test.
sinon.stub( wp.ajax, 'send' ).returns( jQuery.Deferred().promise() );
wp.updates.deletePlugin( { slug: 'jetpack', plugin: 'jetpack/jetpack.php' } );
wp.ajax.send.firstCall.args[ 0 ].error( 'Briefly unavailable for scheduled maintenance.' );
tests/qunit/wp-admin/js/updates.js:232
beforeEachstubsjQuery.post, butafterEachdoes not restore it. This can pollute subsequent tests (similar modules in this test suite restore their stubs/spies inafterEach).
afterEach: function() {
window.pagenow = this.oldPagenow;
}
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.
Comments suppressed due to low confidence (2)
tests/qunit/wp-admin/js/updates.js:235
jQuery.postis stubbed inbeforeEachbut never restored inafterEach, which can leak into other QUnit files and break unrelated tests. Restore the stub inafterEach.
QUnit.module( 'wp.updates.autoUpdates', {
beforeEach: function() {
this.oldPagenow = window.pagenow;
window.pagenow = 'plugins';
this.request = jQuery.Deferred();
sinon.stub( jQuery, 'post' ).returns( this.request.promise() );
this.$column = $(
'<div class="column-auto-updates">' +
'<div class="notice notice-error hidden"><p></p></div>' +
'<button class="toggle-auto-update" data-wp-action="enable">' +
'<span class="dashicons-update hidden"></span>' +
'<span class="label">Enable auto-updates</span>' +
'</button>' +
'</div>'
).appendTo( '#qunit-fixture' );
},
afterEach: function() {
window.pagenow = this.oldPagenow;
}
} );
tests/qunit/wp-admin/js/updates.js:142
- This test stubs
wp.ajax.sendbut never restores it, which can leak into subsequent tests/files and cause false failures (or hide real ones). Restore the stub at the end of the test (or in a module afterEach).
sinon.stub( wp.ajax, 'send' ).returns( jQuery.Deferred().promise() );
wp.updates.deletePlugin( { slug: 'jetpack', plugin: 'jetpack/jetpack.php' } );
wp.ajax.send.firstCall.args[ 0 ].error( 'Briefly unavailable for scheduled maintenance.' );
assert.strictEqual( $pluginRow.find( 'a.delete' ).text(), 'Delete', 'The delete link text is restored.' );
} );
What changed
Why
Plugin and theme actions can receive an invalid response while maintenance mode is active or when the server is unavailable. The existing handlers could leave controls displaying a permanent loading state or expose
undefinedas the error message.Testing
grunt jshint:core --file=wp/updates.jsgrunt jshint:testsnpm run typecheck:jsTrac ticket: https://core.trac.wordpress.org/ticket/55368
Use of AI Tools
AI assistance: Yes
Tool(s): OpenAI Codex
Model(s): GPT-5
Used for: Reviewing the Trac ticket and relevant code, helping with the initial implementation and regression-test approach, and assisting with validation and PR-description drafting. The final implementation, tests, validation results, and description were reviewed and accepted by me.
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.