Resux Media QA

ResuxImg, ResuxPicture, ResuxVideo

Responsive media regression page for lazy loading, placeholders, fallback behavior, cache URLs, and quality/format handling. Open browser network tab and verify lazy assets are not requested before scrolling into view.

Expected: lazy item should not request before scrollExpected: one 404, then fallbackExpected: video placeholder after failed videoExpected: works after client-side navigation, no hard refresh

Cache URL (1d)

/_resux/generated/images/5b7bbd2f.webp?src=%2Fmedia-test%2Fimages%2Fhero-large.webp&original=%2Fmedia-test%2Fimages%2Fhero-large.jpg&w=1400&q=88&f=webp&cache=1d

Cache URL (7d)

/_resux/generated/images/c1933d20.avif?src=%2Fmedia-test%2Fimages%2Fhero-square.avif&original=%2Fmedia-test%2Fimages%2Fhero-square.jpg&w=1200&q=90&f=avif&cache=7d

No Format/Quality URL

/_resux/generated/images/752c32f6.jpeg?src=%2Fmedia-test%2Fimages%2Fhero-large.jpg&w=1200&cache=1d

ResuxImg

Lazy placeholders, fallback, format and cache behavior

Lazy image with default Resux placeholder

lazy loading="lazy" :placeholder="true" placeholderClass="bg-slate-800/70"
Lazy image with default placeholder

Lazy image with custom placeholder image

lazy placeholder="/media-test/images/custom-placeholder.jpg"
Lazy image with custom placeholder

Lazy image with text placeholder

lazy placeholder="Loading image..."
Lazy image with text placeholder

Eager image with no placeholder

loading="eager" placeholder=undefined
Eager PNG image

Image with fallbackSrc configured

src="/media-test/images/hero-wide.jpg" fallbackSrc="/media-test/images/hero-square.jpg" width="860" fit="cover"
Image fallback configuration

Image with placeholder only

src="/media-test/images/hero-large.jpg" lazy :placeholder="true"
Image placeholder test

format=undefined, quality=undefined

:format="undefined" :quality="undefined" modifiers={ format:false, quality:false }
Undefined format and quality

format=null, quality=null

:format="null" :quality="null" modifiers={ format:false, quality:false }
Null format and quality

format="", quality=""

format="" quality="" modifiers={ format:false, quality:false }
Empty format and quality

Cached transformed image

format="webp" quality=88 cache="1d"
Cached transformed webp

Original vs transformed quality comparison

format=null quality=null vs explicit format="webp" quality=88
Original quality comparison

ResuxPicture

Multi-source picture, placeholder, fallback, quality controls

Lazy picture with default Resux placeholder

lazy :placeholder="true" placeholderClass="bg-slate-800/60" formats="avif,webp,jpg"
Lazy picture default placeholder

Lazy picture with custom placeholder image

lazy placeholder="/media-test/images/custom-placeholder.jpg"
Lazy picture custom placeholder

Lazy picture with text placeholder

lazy placeholder="Loading picture..."
Lazy picture text placeholder

Picture with multiple source definitions

:sources="[{ src, format:'webp', media:'(min-width:768px)' }, { src, format:null, media:'(max-width:767px)' }]"
Picture explicit multiple sources

Picture with fallback configuration

src="/media-test/images/hero-large.jpg" fallback="/media-test/images/hero-square.jpg" fallbackSrc="/media-test/images/hero-square.jpg"
Picture fallback configuration

Picture format=null (no conversion)

:format="null" :quality="88" modifiers={ format:false }
Picture format null

Picture quality=null (no compression)

formats="webp,jpg" :quality="null" modifiers={ quality:false }
Picture quality null

Cached transformed picture

formats="avif,webp,jpg" quality=88 cache="7d"
Cached transformed picture

Non-cached transformed picture

formats="webp,jpg" quality=88 :cache="false"
Non-cached transformed picture

ResuxVideo

Lazy load, poster/placeholder/fallback, multi-source

Eager video with controls

src + controls + preload="metadata"
…
0:000:00

Lazy video with poster

lazy poster controls
…
0:000:00

Lazy video with themed custom controls

lazy controls controlsAccent="#22d3ee" controlsBackground="rgba(15,23,42,.80)" controlsColor="#f8fafc"
…
0:000:00

Lazy video with default Resux placeholder

lazy :placeholder="true" controls
…
0:000:00

Lazy video with skeleton placeholder

lazy placeholder="/media-test/videos/placeholder.jpg"
…
0:000:00

Lazy video with custom placeholder image

lazy placeholder="/media-test/images/custom-placeholder.jpg"
…
0:000:00

Lazy video with text placeholder

lazy placeholder="Loading video..."
…
0:000:00

Lazy autoplay muted loop video

lazy autoplay muted loop playsinline
…

Lazy video with multiple sources

:sources="[{ src:'/sample-video-alt.mp4', type:'video/mp4' }, { src:'/sample-video.mp4', type:'video/mp4' }]"
…
0:000:00

Lazy video with speed control

lazy controls speedControl :speeds="[0.5, 0.75, 1, 1.25, 1.5, 2]" :defaultSpeed="1"
…
0:000:00

Lazy video inside responsive card grid

lazy aspect-ratio="16 / 9" class="card media"
…
0:000:00

Video with fallback poster configuration

src="/media-test/videos/sample-video.mp4" fallbackPoster="/media-test/videos/sample-poster.jpg"
…
0:000:00

Video quality setting control test (in-video UI)

quality-control + :qualities + speed-control inside ResuxVideo overlay

Quality and speed controls are rendered inside the video UI. Switching quality should update source selection in-place without a full-page reload.

…
0:000:00
…
0:000:00

ResuxVideo Advanced

Hero preload, deferred chunk loading, and skip overlay controls

Advanced runtime checks for click-to-skip zones, hero/preload hints, and poster-first deferred loading. Expected behavior: no hard refresh, no scroll reset, no router navigation, and one reveal/load cycle per video.

Skip overlay controls (default 1s)

controls lazy skipControls :skipSeconds="1"

Tap/click left half to skip backward and right half to skip forward by 10s without any page refresh.

…
0:000:00

Skip overlay controls (back 5s, forward 15s)

skipControls :skipBackwardSeconds="5" :skipForwardSeconds="15" skipLabel="Jump"

Left/right click zones should skip by different durations and never trigger router navigation.

…
0:000:00

Hero priority preload mode

hero priority preloadLink :lazy="false" loading="eager"

Hero video should render eager with high fetch priority and preload link, without hard refresh.

…
0:000:00

Chunk/range-friendly lazy mode

lazy chunkLoading preload="metadata"

Uses metadata-first loading hints and lazy reveal to reduce heavy initial transfers.

…
0:000:00

Poster-first then page-ready chunk loading

deferUntilPageReady revealOnPageReady chunkLoading poster

Starts as poster/placeholder first, then reveals video load after full page ready with no reload.

…
0:000:00

Hero + defer + chunk + skip combo

hero deferUntilPageReady chunkLoading skipControls :skipSeconds="5"

Combines hero hints, deferred chunk loading, and skip controls while keeping SPA runtime stable.

…
0:000:00

ResuxVideo Capability Matrix

Full ResuxVideo capability tests

This section validates all supported ResuxVideo behavior in grouped scenarios A-K. Groups are collapsible and mounted on demand to keep initial page load lighter while still covering lazy reveal, controls, fallbacks, speed, quality, and runtime navigation behavior.

No hard refresh allowed while scrolling or interacting.Router must ignore media/control interactions.Most tests are lazy to reduce initial network load.Each card includes debug attributes for DevTools checks.
A. Basic video typesCore formats, poster and control combinations.Expand

1. Basic MP4 video

src="/media-test/videos/sample-video.mp4" controls

Expected: MP4 plays with controls.

…
0:000:00

2. Basic WebM video

src="/media-test/videos/sample-video.webm" controls

Expected: WebM source should play directly.

…
0:000:00

3. Multiple sources: WebM first, MP4 fallback

:sources="[{webm},{mp4}]" controls

Expected: browser tries WebM then MP4 fallback without navigation.

…
0:000:00

4. Video with poster

poster="/media-test/videos/sample-poster.jpg"

Expected: poster is visible before playback.

…
0:000:00

5. Video without poster

no poster prop

Expected: loads without poster image and no navigation.

…
0:000:00

6. Video with controls

controls

Expected: controls are visible and interactive.

…
0:000:00

7. Video without controls

:controls="false"

Expected: no controls UI rendered.

…
B. Loading modesEager/lazy variations and reveal behavior.Expand

1. Eager video

:lazy="false" loading="eager"

Expected: requests on initial render.

…
0:000:00

2. Lazy video

lazy loading="lazy"

Expected: request starts only near viewport.

…
0:000:00

3. Lazy video far below fold

lazy + spacer

Expected: no request until deep scroll.

…
0:000:00

4. Lazy video custom rootMargin

root-margin="900px 0px"

Expected: reveals early via rootMargin.

…
0:000:00

5. Lazy video custom threshold

threshold="0.4"

Expected: waits for more visibility before reveal.

…
0:000:00

6. Lazy video preload=none

lazy preload="none"

Expected: remains none until reveal logic runs.

…
0:000:00

7. Lazy preload metadata after reveal

lazy preload="metadata"

Expected: SSR uses preload=none, reveal flips to metadata.

…
0:000:00

8. Eager preload metadata

loading="eager" preload="metadata"

Expected: metadata preload on initial render.

…
0:000:00

9. Eager preload auto

loading="eager" preload="auto"

Expected: auto preload without route navigation.

…
0:000:00
C. Playback modesAutoplay, muted, loop, and reduced motion behavior.Expand

1. Muted autoplay loop video

autoplay muted loop

Expected: loops silently with autoplay policy compliance.

…

2. Muted autoplay playsinline

autoplay muted playsinline

Expected: inline autoplay on supported devices.

…

3. Loop-only video

loop

Expected: loops when user starts playback.

…
0:000:00

4. Muted-only video

muted

Expected: starts muted; no navigation side effects.

…
0:000:00

5. Playsinline-only video

playsinline

Expected: requests inline playback mode.

…
0:000:00

6. Video respecting prefers-reduced-motion

autoplay muted :force-autoplay="false"

Expected: autoplay is skipped under reduced motion.

…

7. Video with forceAutoplay

autoplay muted :force-autoplay="true"

Expected: autoplay attempted even with reduced motion setting.

…
D. Responsive / layout modesAspect ratios, sizing, and container behavior.Expand

1. 16:9 video

aspect-ratio="16 / 9"

Expected: widescreen ratio maintained.

…
0:000:00

2. 4:3 video

aspect-ratio="4 / 3"

Expected: 4:3 frame preserved.

…
0:000:00

3. 1:1 square video

aspect-ratio="1 / 1"

Expected: square container.

…
0:000:00

4. Portrait video container

aspect-ratio="9 / 16"

Expected: portrait layout container.

…
0:000:00

5. Full-width responsive video

class="w-full"

Expected: fills container width responsively.

…
0:000:00

6. Video inside card grid

card grid container

Expected: stable sizing in grid.

…
0:000:00

7. Video inside narrow mobile-like container

max-width: 360px

Expected: no horizontal overflow in narrow container.

…
0:000:00

8. Video with fixed width/height

:width="640" :height="360"

Expected: fixed dimensions respected.

…
0:000:00

9. Video with CSS class override

class="ring-2 ring-emerald-400"

Expected: class styling applies cleanly.

…
0:000:00

10. Video with inline style override

style="border-radius:24px; box-shadow:..."

Expected: inline style override applies.

…
0:000:00
E. Placeholder and poster testsPoster/placeholder/fallback combinations including breakage.Expand

1. placeholder=true default Resux logo

placeholder

Expected: default placeholder logo before reveal.

…
0:000:00

2. Custom image placeholder

placeholder="/media-test/videos/placeholder.jpg"

Expected: custom image placeholder visible.

…
0:000:00

3. Text placeholder

placeholder="Loading video..."

Expected: text placeholder visible.

…
0:000:00

4. Skeleton placeholder

placeholder="/media-test/videos/placeholder.jpg"

Expected: skeleton-like placeholder image.

…
0:000:00

5. Poster only

poster="/media-test/videos/sample-poster.jpg"

Expected: poster shown before playback.

…
0:000:00

6. Poster with fallbackPoster

poster + fallbackPoster

Expected: fallbackPoster available for error path.

…
0:000:00

7. Broken poster with fallbackPoster

poster=missing fallbackPoster=valid

Expected: fallbackPoster takes over.

…
0:000:00

8. Broken poster with placeholder

poster=missing placeholder=true

Expected: placeholder remains visible.

…
0:000:00

9. Broken video with fallbackPoster

src=missing fallbackPoster=valid

Expected: fallbackPoster after error, no reload.

…
0:000:00

10. Broken video with text placeholder

src=missing placeholder="Video unavailable"

Expected: text placeholder/fallback state shown.

…
0:000:00

11. Broken video with default logo placeholder

src=missing placeholder=true

Expected: default placeholder persists on error.

…
0:000:00
F. Multiple source testsSource ordering, lazy source assignment, and failure handling.Expand

1. Multiple sources eager

:lazy="false" :sources="[webm,mp4]"

Expected: eager source resolution without router activity.

…
0:000:00

2. Multiple sources lazy

lazy :sources="[webm,mp4]"

Expected: no source requests before reveal.

…
0:000:00

3. Multiple sources with poster

poster + sources

Expected: poster shown while choosing source.

…
0:000:00

4. Multiple sources with placeholder

placeholder + sources

Expected: placeholder shown pre-reveal.

…
0:000:00

5. First source missing, second works

sources=[missing,mp4]

Expected: first failure then second source works.

…
0:000:00

6. All sources fail + fallback placeholder

sources=[missing,missing] fallbackPoster+placeholder

Expected: fallback placeholder state, no retry loop.

…
0:000:00

7. No requests before lazy reveal

lazy + sources + root-margin="0px"

Expected: source requests start only on intersection.

…
0:000:00

8. No duplicate source requests after navigation

lazy + sources + debug attrs

Expected: one reveal/load cycle after route return.

…
0:000:00
G. Speed control testsBuilt-in speed UI behavior across lazy/eager/navigation paths.Expand

1. Speed control with default speeds

speed-control

Expected: default speeds cycle in control.

…
0:000:00

2. Speed control custom speeds

speed-control :speeds="[0.25,0.5,1,1.25,1.5,2]"

Expected: custom list cycles in order.

…
0:000:00

3. Speed defaultSpeed=1.25

speed-control :default-speed="1.25"

Expected: initial speed label starts at 1.25x.

…
0:000:00

4. showSpeedIcon=false

speed-control :show-speed-icon="false"

Expected: speed text shown without icon.

…
0:000:00

5. Custom speed label

speed-control speed-label="Rate"

Expected: button aria label uses custom text.

…
0:000:00

6. Speed control on lazy video

lazy speed-control

Expected: speed works after lazy reveal.

…
0:000:00

7. Speed control on eager video

:lazy="false" loading="eager" speed-control

Expected: speed control works eagerly.

…
0:000:00

8. Speed control after client-side navigation

speed-control + debug

Expected: still one controls init after returning to /media.

…
0:000:00

9. Speed control must not hard refresh

speed-control

Expected: clicking speed never reloads page.

…
0:000:00

10. Speed control must not trigger router nav

speed-control

Expected: speed clicks are ignored by router interceptor.

…
0:000:00
H. Quality control testsIn-video quality selector behavior across lazy/eager/runtime scenarios.Expand

1. Quality selector enabled

quality-control + :qualities (in-player)

Expected: selecting quality swaps source in-place.

2. Quality selector with defaultQuality

default quality = 720p

Expected: starts on configured default quality.

3. Quality selector without defaultQuality

no default, first option fallback

Expected: first quality option used.

4. 360p/720p/1080p assets

sample-360/sample-720/sample-1080

Expected: all local quality assets are selectable.

5. One missing quality source

include missing quality URL

Expected: missing quality handled without reload.

6. Advanced per-quality sources

webm+mp4 for each quality

Expected: format fallback works per selected quality.

7. Quality selector on lazy video

lazy + selector

Expected: no request until reveal.

8. Quality selector on eager video

eager + selector

Expected: selected source loads eagerly.

9. Quality switch preserves time

capture currentTime and restore

Expected: time is restored after switch.

10. Quality switch resumes if playing

capture paused state

Expected: auto-resume only when previously playing.

11. Quality switch no hard refresh

selector interactions

Expected: no document reload.

12. Quality switch no router nav

in-player selector + controls

Expected: no route navigation.

13. Quality control after navigation

navigate away/back

Expected: selector and video still function.

14. Far-below-fold quality control

quality harness below spacer

Expected: delayed loading until deep scroll.

Quality harness: selector + preserve-time + resume-if-playing

buttons/select switch quality -> capture currentTime + playing state -> remount -> restore

Expected: switching quality should not hard refresh, should preserve approximate playback time, and resume only if the video was already playing.

Manual check: use in-video quality selector while playing and verify time continuity and playback resume behavior.

…
0:000:00
…
0:000:00
…
0:000:00
I. Combined controlsSpeed + quality combined scenarios.Expand

1. Speed + quality controls together

speed-control + quality-control (in-player)

Expected: both controls coexist.

2. Speed + quality + lazy

lazy + speed-control + quality-control

Expected: lazy reveal then both controls work.

3. Speed + quality + poster

poster + controls

Expected: poster shown before load.

4. Speed + quality + placeholder

placeholder + controls

Expected: placeholder behavior maintained.

5. Speed + quality + multiple formats

webm+mp4 per quality

Expected: format fallback preserved.

6. Speed + quality + broken source fallback

quality includes missing URL

Expected: broken quality path handled safely.

7. Speed + quality in responsive grid

grid layout

Expected: controls stay usable in grid.

8. Speed + quality far below fold

spacer + lazy

Expected: delayed load + controls still functional.

Combined harness: speed + quality + lazy + poster + placeholder

quality selector + speedControl + lazy + format fallback (webm/mp4) + error quality option

Expected: speed and quality controls can be used together without router navigation, hard refresh, or duplicate loading loops.

…
0:000:00
…
0:000:00
J. Error and edge casesInvalid/missing source permutations and failure handling.Expand

1. Missing video source

src="/media-test/videos/missing-video.mp4"

Expected: error state + fallback path, no reload.

…
0:000:00

2. Missing first source, valid second source

sources=[missing,mp4]

Expected: second source used.

…
0:000:00

3. Missing all sources

sources=[missing,missing]

Expected: fallback placeholder state, no loops.

…
0:000:00

4. Invalid video URL

src="/media-test/videos/%%%bad%%%.mp4"

Expected: handled as error without navigation.

…
0:000:00

5. Empty src

src=""

Expected: no crash and no route navigation.

…
0:000:00

6. src=null

:src="null"

Expected: no source assignment; stable UI.

…
0:000:00

7. sources=[]

:sources="[]"

Expected: handles empty sources array safely.

…
0:000:00

8. qualities=[] (selector harness)

quality options = []

Expected: selector disabled safely.

9. Missing selected defaultQuality

default quality not in options

Expected: fallback quality chosen.

10. Invalid selected quality source

quality url missing

Expected: error fallback and no hard refresh.

11. Broken poster

poster=missing

Expected: poster fail does not reload app.

…
0:000:00

12. Broken fallbackPoster

fallbackPoster=missing

Expected: placeholder path still safe.

…
0:000:00

13. Error must not retry forever

broken source + observe network

Expected: one failure path, no infinite retries.

…
0:000:00

14. Error must not hard refresh

broken source

Expected: no document reload.

…
0:000:00

15. Error must not duplicate video.load()

broken source + lazy

Expected: no repeated load loop for same failed source.

…
0:000:00
K. Navigation / runtime activation testsManual runtime checks for SPA navigation and re-activation idempotency.Expand

1. Direct load /media

open /media directly

Expected: no hard refresh while revealing videos.

2. Navigate away and back to /media

use app links

Expected: videos initialize once and still lazy-load correctly.

3. Browser back/forward

history back/forward

Expected: no duplicate observers or listeners.

4. Scroll into video section after navigation

navigate then scroll

Expected: in-place reveal only.

5. Speed control after navigation

change route then adjust speed

Expected: speed control still works without reload.

6. Quality control after navigation

change route then quality switch

Expected: quality switch still works safely.

7. Far-below-fold lazy video after navigation

navigate back then deep scroll

Expected: loads when near viewport.

8. No duplicate observers after navigation

inspect data-resux-observed

Expected: one observation cycle per element.

9. No duplicate listeners after navigation

interact controls repeatedly

Expected: no multi-fire handler behavior.

10. No hard refresh at any point

watch network + scroll position

Expected: no full document reload.

Manual navigation/runtime checklist

direct load /media -> navigate away/back -> browser back/forward -> deep scroll -> speed/quality interactions
  1. Open `/media` directly and scroll through capability groups.
  2. Navigate to another route, return to `/media`, then re-open groups G/H/I.
  3. Use browser back/forward and verify scroll/interactions still work.
  4. Inspect `data-resux-observed` / `data-resux-video-controls-ready` markers for duplicated state.
  5. Verify no hard refresh, no scroll reset, and no duplicate media requests.

Lazy Network Check

Far below fold lazy video

The spacer below keeps this example off-screen initially. Confirm in network tab that the video request starts only after scroll.

Lazy video far down page

lazy loading="lazy" root-margin="0px 0px" threshold="0.01"
…
0:000:00