From bfb75fd051cb3471a38d6544fdf10afd856ea9f5 Mon Sep 17 00:00:00 2001 From: Utkarsh Patel Date: Wed, 3 Jun 2026 14:52:33 +0530 Subject: [PATCH 1/9] test(e2e): add fixture video for Cloudinary delivery spec --- tests/e2e/fixtures/test-video.mp4 | Bin 0 -> 2325 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/e2e/fixtures/test-video.mp4 diff --git a/tests/e2e/fixtures/test-video.mp4 b/tests/e2e/fixtures/test-video.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..2f32332b7777dd98a43d7b8c242ac4e4ea06b1ca GIT binary patch literal 2325 zcmd5-UuYaf7@tdOt)(sflWGfj7;PRDlFRO1a;?#YTthU4h*h*j5Vmu>bGbFUx0~Hb za#s*qY^$$67-@y%NouvI53PNYMo>XT^sxmIq#%}pRuK#p@BDqccg@{V@YUgFzW=}Z zzWHYM7-PJoYM~nkK4U$MD5fD6Y~2q>bjCK6{2*9hjCuY-*#T`Ey}vMqnPK!>9~}bJ zUGn(4=e@WdV7{p$F$?3%YBt%kx6QGMMtgUSu6^#cZ)O}Zx0AR5>8Kc7zw~02Xp&3` zcSAGh-Uocg6|iyN>8{;?+F&n!od=LOvf;(?DsoW2TC6lsyHOCXLMQ zY53=jtgdHuP2-+htQz@|)R?S$8V%4qye2XZ+uHbv?VSO=c)d{gJF^{KVzl(~-w&QW zmSG#qw{Cp%$m&09YZSaa6mbYjdC=@Ds;GI$`w|D}_QWb_0NBK5FI_;4KGa2xq0x%J zX0Q9gkMw9#LN_;QOD2)*2^Q%8+TM>^?Ih#%TATH;Ds0D_HX?LBe}V46+}1W90*_AI z)%}KjuN0R`7)tod$|45%w?$Fdrq1y$%^Y`R(F^QZ zQynkqwt&dM6FO=DDRvKBt15P59NinQmIIigXTk)R`uWL!pg zWLtO3C3|F>c2wd%zDJVEf?yiCtj6c47*osU!G;8!P*FAWk3$hF8JZ*94bdcA2=owG zVh;VMZn6`&!3FuoDfUF8e&d6+zH5hHP}5<0ecse)hY*x4l1h?eG7ne*deZ$Jn4) z`tz|br{8+&`^+F?J6FFwqn*3()suJb9DNQTTMOp~yosyz3wU(FDioUw%Ll8c@gaWg zBuSZNp$=YU?2{9zWWSO~WZP9ZS3dM!p?r3F(_$k9_zdbTh2=AoI|hf_Al^+Ont9M5UVM~*OR+DAZ~VKajOI3b`v6K)X$${>_^&XOJQYOC&bE7dloCh>kvB& z?~F7dW*YV7?W~vn34!o@7s6b75-V{BLbZu-v{64W&bA&(5tdpACm?UmtX%HM;Yx~d F@?W@2`pN(R literal 0 HcmV?d00001 From 574a99c0fb8a5cb71f4c1822a93e21f4750cf121 Mon Sep 17 00:00:00 2001 From: Utkarsh Patel Date: Wed, 3 Jun 2026 14:53:01 +0530 Subject: [PATCH 2/9] test(e2e): scaffold Cloudinary video delivery spec --- tests/e2e/cloudinary-video-delivery.spec.js | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 tests/e2e/cloudinary-video-delivery.spec.js diff --git a/tests/e2e/cloudinary-video-delivery.spec.js b/tests/e2e/cloudinary-video-delivery.spec.js new file mode 100644 index 00000000..2ba09feb --- /dev/null +++ b/tests/e2e/cloudinary-video-delivery.spec.js @@ -0,0 +1,23 @@ +/** + * External dependencies + */ +const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); + +/** + * Internal dependencies + */ +const { ensureCloudinaryConnected } = require( './utils/connection' ); + +let cloudName; + +test.describe( 'Cloudinary video delivery', () => { + test.beforeAll( () => { + ( { cloudName } = ensureCloudinaryConnected() ); + } ); + + test( 'serves video from a core/video block via Cloudinary', async () => { + // Sentinel assertion: will be replaced in Task 4. + expect( cloudName, 'cloudName should be parsed from env' ).toBeTruthy(); + expect( false, 'placeholder — to be implemented' ).toBe( true ); + } ); +} ); From ba95d9c9b67ee90717c19e6f3b023e61d9d5df9c Mon Sep 17 00:00:00 2001 From: Utkarsh Patel Date: Wed, 3 Jun 2026 14:53:51 +0530 Subject: [PATCH 3/9] test(e2e): set up REST-driven video lifecycle for delivery spec --- tests/e2e/cloudinary-video-delivery.spec.js | 86 ++++++++++++++++++++- 1 file changed, 84 insertions(+), 2 deletions(-) diff --git a/tests/e2e/cloudinary-video-delivery.spec.js b/tests/e2e/cloudinary-video-delivery.spec.js index 2ba09feb..714f00bd 100644 --- a/tests/e2e/cloudinary-video-delivery.spec.js +++ b/tests/e2e/cloudinary-video-delivery.spec.js @@ -1,23 +1,105 @@ /** * External dependencies */ +const fs = require( 'fs' ); +const path = require( 'path' ); const { test, expect } = require( '@wordpress/e2e-test-utils-playwright' ); /** * Internal dependencies */ const { ensureCloudinaryConnected } = require( './utils/connection' ); +const { wpCli } = require( './utils/wizard' ); + +const FIXTURE_PATH = path.join( __dirname, 'fixtures', 'test-video.mp4' ); let cloudName; +/** + * Per-test scratch space populated by beforeEach. + * + * @type {{ postId: number, attachmentId: number, postLink: string }|null} + */ +let created = null; + test.describe( 'Cloudinary video delivery', () => { test.beforeAll( () => { ( { cloudName } = ensureCloudinaryConnected() ); } ); + test.beforeEach( async ( { requestUtils } ) => { + // Upload the fixture video via REST. + const file = fs.readFileSync( FIXTURE_PATH ); + const media = await requestUtils.rest( { + method: 'POST', + path: '/wp/v2/media', + headers: { + 'Content-Type': 'video/mp4', + 'Content-Disposition': 'attachment; filename="test-video.mp4"', + }, + data: file, + } ); + + const attachmentId = media.id; + const sourceUrl = media.source_url; + + // Create a published post containing a single core/video block + // that references the just-uploaded attachment. + const content = + `\n` + + `
\n` + + ``; + + const post = await requestUtils.rest( { + method: 'POST', + path: '/wp/v2/posts', + data: { + status: 'publish', + title: `Cloudinary video e2e ${ Date.now() }`, + content, + }, + } ); + + created = { + postId: post.id, + attachmentId, + postLink: post.link, + }; + + // The plugin's URL rewriting depends on the asset being synced + // to Cloudinary. Drive the sync synchronously here so the + // front-end visit sees rewritten URLs. + wpCli( [ 'cloudinary', 'sync' ] ); + } ); + + test.afterEach( async () => { + if ( ! created ) { + return; + } + const { postId, attachmentId } = created; + created = null; + + // Best-effort cleanup via WP-CLI. Matches the image spec; we + // do not use the REST API because this wp-env runs without + // pretty permalinks, which makes `?force=true` fragile. + try { + wpCli( [ 'post', 'delete', String( postId ), '--force' ] ); + } catch ( e ) { + // eslint-disable-next-line no-console + console.warn( 'Post cleanup failed:', e.message ); + } + try { + wpCli( [ 'post', 'delete', String( attachmentId ), '--force' ] ); + } catch ( e ) { + // eslint-disable-next-line no-console + console.warn( 'Media cleanup failed:', e.message ); + } + } ); + test( 'serves video from a core/video block via Cloudinary', async () => { - // Sentinel assertion: will be replaced in Task 4. - expect( cloudName, 'cloudName should be parsed from env' ).toBeTruthy(); + // Placeholder — assertions added in Task 4. + expect( created, 'post + attachment should be created' ).not.toBeNull(); + expect( created.postLink ).toMatch( /^https?:\/\// ); expect( false, 'placeholder — to be implemented' ).toBe( true ); } ); } ); From 7d24ba68dd37a3d1e99ee6f570a156589233eed5 Mon Sep 17 00:00:00 2001 From: Utkarsh Patel Date: Wed, 3 Jun 2026 14:55:59 +0530 Subject: [PATCH 4/9] test(e2e): assert core/video block is served via Cloudinary --- tests/e2e/cloudinary-video-delivery.spec.js | 59 +++++++++++++++++++-- 1 file changed, 55 insertions(+), 4 deletions(-) diff --git a/tests/e2e/cloudinary-video-delivery.spec.js b/tests/e2e/cloudinary-video-delivery.spec.js index 714f00bd..c9564a80 100644 --- a/tests/e2e/cloudinary-video-delivery.spec.js +++ b/tests/e2e/cloudinary-video-delivery.spec.js @@ -22,6 +22,28 @@ let cloudName; */ let created = null; +/** + * Assert that a given URL is served by Cloudinary under the expected + * cloud name. We intentionally do not assert specific transformations — + * those are an implementation detail of the plugin and may change. + * + * @param {string} rawUrl The URL to validate. + * @param {string} expectedCloud The cloud name parsed from CLOUDINARY_E2E_URL. + */ +function expectCloudinaryUrl( rawUrl, expectedCloud ) { + let parsed; + try { + parsed = new URL( rawUrl ); + } catch ( e ) { + throw new Error( `URL is not parseable: ${ rawUrl }` ); + } + expect( parsed.host, `host of ${ rawUrl }` ).toBe( 'res.cloudinary.com' ); + expect( + parsed.pathname.startsWith( `/${ expectedCloud }/` ), + `pathname of ${ rawUrl } should start with /${ expectedCloud }/` + ).toBe( true ); +} + test.describe( 'Cloudinary video delivery', () => { test.beforeAll( () => { ( { cloudName } = ensureCloudinaryConnected() ); @@ -96,10 +118,39 @@ test.describe( 'Cloudinary video delivery', () => { } } ); - test( 'serves video from a core/video block via Cloudinary', async () => { - // Placeholder — assertions added in Task 4. + test( 'serves video from a core/video block via Cloudinary', async ( { + page, + } ) => { expect( created, 'post + attachment should be created' ).not.toBeNull(); - expect( created.postLink ).toMatch( /^https?:\/\// ); - expect( false, 'placeholder — to be implemented' ).toBe( true ); + + await page.goto( created.postLink ); + + // Locate the core/video block on the rendered page. + const video = page.locator( 'figure.wp-block-video video' ).first(); + await expect( + video, + 'core/video block should render a