Repository navigation
test(e2e): Add breakpoints and lazy load spec - #1342
utkarshcloudinary wants to merge 4 commits into
Conversation
gabrielcld2
left a comment
There was a problem hiding this comment.
@utkarshcloudinary this is looking good, just a few minor issues
| .map( ( candidate ) => candidate.trim().split( /\s+/ )[ 0 ] ) | ||
| .filter( Boolean ); | ||
| const candidates = []; | ||
| const pattern = /\s*(\S+?)(?:\s+(\d+(?:\.\d+)?[wx]))?\s*(?:,(?=\s)|,?$)/gy; |
There was a problem hiding this comment.
issue: This regex only ends a candidate at , followed by whitespace, or at the end of the string. When exec fails, the loop breaks and quietly returns what it has so far:
| Input | Result |
|---|---|
a.jpg 1x,b.jpg 2x (valid HTML) |
[] |
a.jpg 300w ,b.jpg 600w |
[] |
a.jpg 1.5x, b.jpg 100h |
only a.jpg |
cloudinary-gallery-delivery.spec.js loops over [src, ...srcsetUrls(srcset)], so an empty result makes its srcset checks pass without checking anything.
Suggestion: follow the HTML parsing rule. A URL is a run of non-whitespace characters, and trailing commas on it end the candidate. Otherwise the descriptor runs up to the next comma:
function parseSrcset( srcset ) {
const candidates = [];
const input = srcset || '';
const urlPattern = /[\s,]*(\S+)/y;
const descriptorPattern = /\s*([^,]*?)\s*(?:,|$)/y;
while ( true ) {
const urlMatch = urlPattern.exec( input );
if ( ! urlMatch ) {
break;
}
let url = urlMatch[ 1 ];
let descriptor = '';
if ( /,$/.test( url ) ) {
url = url.replace( /,+$/, '' );
} else {
descriptorPattern.lastIndex = urlPattern.lastIndex;
descriptor = descriptorPattern.exec( input )[ 1 ];
urlPattern.lastIndex = descriptorPattern.lastIndex;
}
candidates.push( { url, descriptor } );
}
return candidates;
}It handles the cases above and the Cloudinary comma URLs (w_800,h_600,c_scale). If you keep the current regex, throw on leftover input instead of break, so a bad parse fails loudly.
There was a problem hiding this comment.
Good catch, fixed in 63da419. I used your parser: it follows the HTML parsing rule, so a.jpg 1x,b.jpg 2x, a.jpg 300w ,b.jpg 600w and a.jpg 1.5x, b.jpg 100h now give both candidates, and the Cloudinary URLs with commas stay whole.
| * @param {Record<string, string|number>} values Setting slug to value. | ||
| * @return {Record<string, string|number>} Setting slug to the value before the write. | ||
| */ | ||
| function saveSettings( values ) { |
There was a problem hiding this comment.
suggestion (if-minor): This is the same code as saveSettings() in cloudinary-svg-delivery.spec.js. Could it move, with readSettings(), into a shared helper (for example tests/e2e/utils/settings.js)?
Both copies also put JSON inside a single-quoted PHP string (json_decode( '${ JSON.stringify(values) }' )), which breaks if a value contains '. The values here are safe, but a shared helper should escape ' and \\ before inserting the JSON (or base64-encode it).
There was a problem hiding this comment.
| // The first candidate is the original `src`; the rest | ||
| // carry the breakpoint width as a transformation. | ||
| if ( i > 0 ) { | ||
| expect( url, `transformation of ${ url }` ).toContain( |
There was a problem hiding this comment.
issue (non-blocking, if-minor): toContain( 'w_1100' ) would also match w_11000, or a w_ in a different transformation segment. Match the parameter exactly:
expect( url ).toMatch( new RegExp( `[/,]w_${ EXPECTED_WIDTHS[ i ] }[,/]` ) );There was a problem hiding this comment.
Fixed in c90d1d6 with your regex, so it matches the exact w_ parameter.
|
|
||
| // Core may still emit its own srcset from the registered | ||
| // image sizes. None of the breakpoint-only widths may appear. | ||
| const widths = srcsetWidths( attrs.srcset ); |
There was a problem hiding this comment.
suggestion: If there is no srcset at all, srcsetWidths() returns [] and every not.toContain below passes. That is a valid outcome, but could we also check something positive? For example, that attrs.sizes, if present, isn't the plugin's (max-width: 1200px) 100vw, 1200px, or that every width found is one of core's (1200, 1024, 768, 300).
There was a problem hiding this comment.
Added in c90d1d6. The test now checks that WordPress still writes a srcset, and that every width in it is a registered size of the image. It reads the sizes from the attachment metadata instead of a fixed list. The check passes on CI.
|
|
||
| // The inline loader config carries the blur placeholder | ||
| // transformation. | ||
| const config = /var CLDLB = (\{.*?\});/.exec( html ); |
There was a problem hiding this comment.
Nit: .*? up to the first }; works today because wp_json_encode output has no }; and no newlines. Anchoring it to the script text that follows, or using [^\n]*?, would make it a bit less fragile.
| browser, | ||
| baseURL, | ||
| } ) => { | ||
| configure( { breakpoints: false, lazyLoad: false } ); |
There was a problem hiding this comment.
Nit: this is the same configure() call as the "disable breakpoints" test, but the title only talks about lazy load. A short comment that breakpoints are switched off here too would make that clear.
Cloudinary transformation segments such as w_800,h_600 contain commas, so splitting srcset on every comma broke each candidate into pieces. Parse candidates by their trailing descriptor instead and expose the descriptor through parseSrcset().
Cover the responsive breakpoints and lazy load delivery settings on a synced image: - min/max/step produce the matching srcset width entries - lazy load renders the SVG placeholder, data attributes and the CLDLB loader config with the blur placeholder - turning either setting off removes its markup
The regex only ended a candidate at a comma followed by whitespace or at the end of the string, and quietly returned what it had so far when it did not match. Valid input such as "a.jpg 1x,b.jpg 2x" gave an empty list, which made srcset checks pass without checking anything. Read a URL as a run of non-whitespace characters, as the HTML spec does, so commas inside Cloudinary URLs still stay part of the URL.
- Move saveSettings() and readSettings() to tests/e2e/utils/settings.js and base64-encode the JSON, so a quote in a value cannot break the PHP string. - Match the breakpoint w_ parameter exactly. - Check that every width left after breakpoints are off is a registered image size. - Stop the CLDLB regex at the end of the line. - Explain why the lazy load test also turns breakpoints off.
78b1c9a to
c90d1d6
Compare
Adds an e2e spec for the responsive breakpoints and lazy load delivery settings on a synced image. It also fixes the shared
srcsetUrls()helper, which split Cloudinary URLs apart at the commas inside their transformation segment (w_800,h_600,c_scale).Approach
tests/e2e/cloudinary-breakpoints-lazy-load.spec.js(@serial, real credentials needed forwp cloudinary sync). It uploads the 1200x900 fixture, embeds it in a post, and syncs once inbeforeAll.afterAll.src/srcsetafter load.max_width=1100,min_width=500,pixel_step=300must givesrcsetwidths1200w, 1100w, 800w, 500w. Each breakpoint URL is on Cloudinary and has the matchingw_transformation. Core never makes these widths for this image, so they can only come from the plugin.srcseton the server when lazy load is off (Responsive_Breakpoints::add_features()), so the srcset test turns lazy load off.src,data-cloudinary="lazy",data-size, theCLDBindonload,data-public-id,data-delivery, and theCLDLBconfig with the blur placeholder (e_blur:2000). With JS on,srcchanges to a Cloudinary URL.data-responsiveand the breakpoint widths are gone. With lazy load off, the placeholder attributes andCLDLBare gone andsrcis the Cloudinary URL from the server.utils/delivery.js: newparseSrcset()returns{ url, descriptor }pairs.srcsetUrls()now uses it.QA notes
npm run test:e2e:serial -- cloudinary-breakpoints-lazy-loadnpm run test:e2e:serial -- cloudinary-gallery-delivery(uses the changed helper)