tests/Support/AssertsToolErrors (used by TestCase): assertToolError($result, code)
checks the WP_Error code lit_<code> and the code of the client JSON and returns the
payload; clientError() decodes the payload; errorFields() returns the fields and
asserts they exist. Replaces the private clientError() decoders of
DiviWriteAbilitiesTest/DiviReplaceTextAbilityTest, 216 single-line
assertSame('lit_…', …->get_error_code()) assertions, 24 get_error_data()['fields']
digs and two json_decode(message) reads. ErrorsTest keeps json_decode: it tests
the format itself. Tests 1404 -> 1409 (AssertsToolErrorsTest); no test has fewer
assertions.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- tests/Support/FakeChangeLog extends ChangeLog: records record()/recordPartial()
calls, increasing ids, optional failure; new FakeChangeLog(id) / partialsOnly() /
any(id) / forbidden() mirror what the replaced mocks allowed. assertRecorded() /
assertPartials() check count and the named arguments. Calls a fake does not allow
throw and are also verified in TestCase::tearDown (one assertion per test that
uses a fake), so swallowed change-log calls still fail like a never() expectation.
- All ChangeLog mocks of ability/integration tests replaced (the admin tests that
stub query/purge/clear keep their mocks); expectException tests that checked the
partial log now catch and assert.
- SchemaFixture::managed(?divi) replaces the 21 isManaged-only ContentSchema mocks;
DiviFixtures::schema() uses it.
Tests 1397 -> 1404 (FakeChangeLogTest); no test has fewer assertions.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- WriteFailed::rolledBack()/partial() replace the 11-parameter constructor (now
private); the hint/state of either error are plain $hint/$state.
- Rollback::attempt(...steps) runs every undo step and collects failure messages;
used by ContentCreate::discard, ContentUpdate::rollBack, MediaUpdate::rollBack and
DiviSaver::restore.
- Errors::clientMessage/codeOf/fieldsOf replace DiviReplaceTextAbility::reason,
the JSON digging in MediaUpdateAbility::failure and ContentCreateAbility::fields.
- Errors docblock documents the exception/WP_Error split.
- ContentCreateAbility::discard takes the client reason as a parameter (both callers
still pass REASON_EXTRAS; changing the Divi text needs a ruling).
Error payloads unchanged.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
MediaImporter streams URL imports via wp_safe_remote_get with limit_response_size,
checks Content-Length, intersects the MIME whitelist with get_allowed_mime_types and
validates real content; base64 is size-checked before decoding. Server-side failures
are write_failed; a failed alt text deletes the new attachment again (or partial_write).
MediaUploads is the shared permission/result helper of both upload abilities.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7