Developer testing guide

HTTP Range request testing for MP4, MOV, and WebM

A video can download successfully while seeking still fails. Players commonly request byte ranges, so origin, CDN, cache, and application responses must preserve Range semantics end to end.

Verified . Range responses are checked for status, headers, length, boundary behavior, and byte equality against the original asset.

Practical checklist

  • Confirm Accept-Ranges and an exact Content-Length.
  • Request the first, middle, and final byte ranges.
  • Validate Content-Range and returned byte count.
  • Test invalid and unsatisfiable ranges.

Verify a valid partial response

Send Range: bytes=0-1023 and expect status 206, Content-Range with the full object size, and exactly 1,024 response bytes. Compare those bytes with the same slice from a complete download.

Cover range edge cases

Test open-ended ranges, suffix ranges, the final byte, a start beyond the object length, and malformed headers. Unsatisfiable ranges should return 416 with Content-Range: bytes */size.

Test through the production path

Run the same checks against the public download route and the R2 asset hostname. A proxy or cache layer can accidentally remove Range, Content-Length, ETag, or cache validators.

Expected results

  • Valid ranges return 206 and the requested bytes only.
  • Unsatisfiable ranges return 416 with the full size.
  • The native player seeks without downloading the entire object again.

Common failure modes

  • Returning 200 for every Range request.
  • Using the partial length as the total Content-Range size.
  • Compressing binary video responses in a way that changes byte offsets.

Check the fixture with curl

Download the representative file and print the response status, MIME type, and transferred byte count.

Shell
curl --fail --location --silent --show-error \
  --output sample-3s.mp4 \
  --write-out 'status=%{http_code}\ncontent_type=%{content_type}\nbytes=%{size_download}\n' \
  'https://assets.testfiles.dev/video/sample-3s.mp4'

Fetch and upload the video fixture with Playwright

Fetch the published fixture as a buffer, assign it to a real file input, and verify the browser receives the registered name, MIME type, and byte size.

TypeScript
import { test, expect } from "@playwright/test";

test("uploads a verified video fixture", async ({ page, request }) => {
  const response = await request.get("https://assets.testfiles.dev/video/sample-3s.mp4");
  expect(response.ok()).toBeTruthy();
  expect(response.headers()["content-type"] ?? "").toContain("video/mp4");

  const buffer = await response.body();
  expect(buffer).toHaveLength(122786);

  await page.setContent('<input id="fixture" type="file">');
  await page.locator("#fixture").setInputFiles({
    name: "sample-3s.mp4",
    mimeType: "video/mp4",
    buffer,
  });

  const selected = await page.locator("#fixture").evaluate((input: HTMLInputElement) => ({
    name: input.files?.[0]?.name,
    type: input.files?.[0]?.type,
    size: input.files?.[0]?.size,
  }));
  expect(selected).toEqual({
    name: "sample-3s.mp4",
    type: "video/mp4",
    size: 122786,
  });
});

cURL Range verification

Inspect production headers and write the first 1,024 bytes to a temporary file.

Shell
curl --fail --silent --show-error \
  --range 0-1023 \
  --dump-header - \
  --output /tmp/testfiles-range.bin \
  https://testfiles.dev/download/video/sample-3s.mp4

test "$(wc -c < /tmp/testfiles-range.bin | tr -d ' ')" = "1024"

Use stable sample files

These fixtures have stable URLs, recorded MIME types, byte sizes, SHA-256 values, and dedicated detail pages.

Format references

Copied