Skip to content

test(e2e): Add SVG upload and delivery spec - #1317

Merged
gabrielcld2 merged 2 commits into
developfrom
test/svg-upload-delivery-e2e
Oct 13, 2026
Merged

gabrielcld2 merged 2 commits into
developfrom
test/svg-upload-delivery-e2e

Conversation

@utkarshcloudinary

@utkarshcloudinary utkarshcloudinary commented Oct 13, 2026 •

Copy link
Copy Markdown
Collaborator

Adds a Playwright spec for SVG Support. It checks that a valid SVG uploads, syncs and is delivered from Cloudinary as an SVG, and that an SVG with unsafe content has that content stripped.

Approach

  • tests/e2e/cloudinary-svg-delivery.spec.js (@serial, needs CLOUDINARY_E2E_URL):
    • beforeAll sets svg_support=on, image_format=auto and image_quality=auto through the settings API. afterAll restores the previous values. SVG Support is off by default, and WordPress rejects SVG uploads without it. The format and quality are pinned because the analytics specs change them and do not change them back (see the note below).
    • Each test uploads an SVG over REST with a unique filename, publishes a post with an image block, and runs wp cloudinary sync.
    • Valid SVG: the upload is accepted as image/svg+xml, and the attachment has a public ID and a sync log. The REST source_url is a res.cloudinary.com/<cloud_name>/…/*.svg URL. The front-end <img> URL returns image/svg+xml, and the body is the original SVG.
    • Unsafe SVG: the fixture has an inline <script> and an onload handler. It still uploads and syncs. The front-end URL (f_svg,…/fl_sanitize) returns image/svg+xml with no <script> and no on*= attributes.
  • Fixtures: tests/e2e/fixtures/svg-valid.svg, tests/e2e/fixtures/svg-unsafe.svg.
  • When I removed the sanitize flag in SVG::add_features(), the unsafe-SVG test failed with "the <script> element should be stripped".

Notes

  • REST upload and read requests use _fields. Without this, missing_image_sizes reads width/height from the metadata, which an SVG does not have before sync. With WP_DEBUG on, the PHP warning breaks the JSON response.
  • The sync check uses has_public_id() + been_synced(), not is_synced(). After wp cloudinary sync, is_synced() returns false for every asset type, JPEG included, because the relation signature changes on the next request. This is a separate issue and is not specific to SVG.
  • The REST source_url for an SVG uses f_auto,q_auto, so Cloudinary serves PNG/WebP at that URL. Only the front-end URL serves SVG. For this reason, the spec checks the delivered content type on the front-end URL only. If the attachment URL must also return SVG, that is a plugin bug.
  • Plugin bug found by CI: when image_format is a fixed format such as webp, the first front-end render after sync delivers an SVG as f_webp,q_80 without fl_sanitize. Media::get_cloudinary_id() replaces the .svg extension with the global format, so SVG::add_features() sees format=webp and does nothing. The second render is correct. The spec pins image_format=auto to test the default path. This bug needs its own fix.

QA notes

  • cp .env.example .env and set CLOUDINARY_E2E_URL to a test account.
  • npm run env:start, or npx wp-env start --config .wp-env.ci.json for the plain HTTP setup that CI uses.
  • npm run test:e2e:serial -- cloudinary-svg-delivery, or with the CI config: WP_BASE_URL=http://localhost:8889 ./.wp-env/scripts/run-e2e.sh cloudinary-svg-delivery --workers=1.
  • Expect 2 passing tests. svg_support on the tests site has the same value after the run as before.

Cover the SVG Support feature end to end against a real Cloudinary
account:

- A valid SVG uploads, syncs, gets a Cloudinary attachment URL, and
  the front end serves it as image/svg+xml with its content intact.
- An SVG with an inline <script> and an onload handler still syncs,
  but the delivered asset has both stripped (fl_sanitize).

The spec turns svg_support on for its run and restores the previous
value afterwards. It is tagged @serial because it needs real
credentials for `wp cloudinary sync`.
The analytics specs flip image_format to webp and image_quality to 80
and leave them changed. With a fixed global format, the first render
after sync delivers an SVG as f_webp without fl_sanitize, because
Media::get_cloudinary_id() replaces the extension with the global
format. CI ran the analytics specs first, so both SVG tests got
image/webp.

Pin both settings to auto for the spec and restore the previous
values afterwards.
@utkarshcloudinary
utkarshcloudinary marked this pull request as ready for review October 13, 2026 10:19
@gabrielcld2
gabrielcld2 merged commit aea85e0 into develop Oct 13, 2026
7 checks passed
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.

3 participants