000%

Published Updated

NOTES · SEO / GEO / AEO14 · 2026.10

Verify changes, deploy, and recover

Compare the same URLs before and after changes and check the production build, content, status, and caches. Verify the version served by the production domain, then recover code, content, or data according to the failure.

§ 01SEO / GEO / AEO

Use the same URLs before and after changes

A build checks whether code can produce deployable output. Actual responses reveal whether the content, URLs, and dates supplied to search are correct. A successful build does not improve delivery if production still has noindex or the CDN serves the old body. Comparing the same URLs before and after a change shows which responses the changed code affected.

Use the URL list from diagnosis as verification input. Include normal public detail pages, first and subsequent listing pages, images and attachments, old URLs, missing URLs, and draft or withdrawn material. Save the initial status code, final URL, robots, canonical, title, and key body sentences. Collect the same values afterward to see what changed.

Record target URL, expected value, actual value, check time, and deployment version. Do not stop at finding the article in a public listing: open its detail page and compare it with the source. If only metadata changed, also verify that the original text, photos, and links remain intact.

States to check separately
Normal public detail page
Expected result
Intended content, canonical URL, and search permission
Where to look on failure
Public query, metadata, cache
Draft, not-yet-scheduled, or withdrawn material
Expected result
Absent from public listings and sitemap; source content hidden
Where to look on failure
Publication conditions, authentication, cache invalidation
Missing URL
Expected result
404 or intended 410, with an error screen
Where to look on failure
Routing, streaming, hosting
Old URL
Expected result
Permanent redirect to the chosen canonical URL
Where to look on failure
Redirect order and loops
Next listing page
Expected result
Next items and links provided
Where to look on failure
Pagination query and canonical URL
Public images and attachments
Expected result
Unauthenticated access and correct content type
Where to look on failure
Storage permissions, media proxy, WAF
§ 02SEO / GEO / AEO

Choose code checks that match the change

If publication checks or URL-generation functions changed, review inputs that produce different results: public, draft, not yet scheduled, withdrawn, and missing documents. Run the relevant existing tests. Check deployability through type checking and a production build. The commands below assume typecheck and build scripts in package.json; use the repository's actual names if different.

npm run typecheck npm run build

Even after type checks and builds pass, open pages in actual production mode. Check that production domains and public API addresses agree between build-time and runtime environments. Compare environment-specific values so verification-site noindex and authentication settings do not enter production unchanged.

If core publication states are wrong, valid articles become errors, or content and links disappear, correct the change and recheck the affected scope. Local checks at this stage do not establish indexing or external citations; track those after deployment.

§ 03SEO / GEO / AEO

Check rendering through build output and actual responses

First read package.json's build command, the Next.js version, next.config, and data-query and cache settings. Run the production build and open pages from that output. Check build output and deployment settings for statically generated routes, request-time routes, and revalidated routes. With output: export, inspect exported HTML, direct hosted URLs, and 404 handling.

A parser reads document strings into structure. Fetch a public detail URL with curl and use an HTML parser to extract article, h1, body paragraphs, and a href. Compare key source sentences with visible body elements. Text existing only in Next.js serialized data or script strings is different from HTML body content. Receive streaming responses to completion; do not infer a missing body from the first loading fragment alone.

In the browser, check both direct URL entry and navigation through listing links. Verify that key content and sources survive hydration and whether clicks or scrolling are required to fetch more material. Disabling JavaScript helps identify dependencies. Account for script-assisted streaming placement by comparing the source response, completed DOM, and search-tool render together.

For metadata, distinguish ordinary requests from the target crawler's response conditions. Next.js can stream metadata for some requests and wait for it for bots classified as HTML-only readers. Compare branches with curl using different User-Agent values. Establish actual bot visits and collection results from server logs and search tools. Compare the Metadata API guide on streaming and bot handling with the installed version.

Even if notFound() is called for missing articles, read the production HTTP status directly. After streaming starts, an error screen may arrive with 200. For paths requiring a real 404, place existence and publication checks before response headers are sent, and check noindex too. Next.js not-found rules explain status differences between streaming and non-streaming responses.

After publication, edits, and withdrawal, reread current detail-page, listing, sitemap, and metadata values. For static or cached pages, make the change with a populated cache and compare the first request with one after updating completes. Record public version, expected content, actual content, response time, and revalidation time. If old content remains, isolate whether it came from the data cache, page cache, or CDN.

§ 04SEO / GEO / AEO

Inspect responses, metadata, and content

Run the commands below in the verification environment. Saving HTML and headers separately lets you compare X-Robots-Tag in the headers without overlooking it. Change the address and filenames for each URL checked.

CHECK_URL='https://example.com/guides/opening-hours' curl -sS -D after.headers -o after.html "$CHECK_URL" rg -n -i 'HTTP/|location:|x-robots-tag:|content-type:' after.headers rg -n -i 'canonical|noindex|<title|application/ld\+json' after.html

A public canonical URL should return a successful status, the intended canonical, and robots instructions that do not block search. Find the direct answer and source links in the actual body. If a 200 response shows login, a bot challenge, or “not found,” fix access settings or error handling. When removing search exclusion, noindex must be absent from both meta and headers.

Streaming sends a response in pieces as they become ready. Tag placement can differ with Next.js streaming metadata and server rendering. Read the completed response and browser DOM together. If ordinary and bot User-Agents receive different responses, investigate code and CDN policies. Naming Googlebot in curl reproduces a response branch; evidence of actual Google crawling comes from URL Inspection and server records.

§ 05SEO / GEO / AEO

Compare the example's expected responses directly

Request these paths from the exercise server running in production mode. Expect 200 and opening-hours content for public articles, 404 and search exclusion for drafts and missing articles, and generated content for the archive page. The sitemap should include public detail and archive URLs and exclude draft URLs.

curl -sS -D guide.headers -o guide.html http://localhost:3027/guides/opening-hours curl -sS -D draft.headers -o draft.html http://localhost:3027/guides/draft-guide curl -sS -D missing.headers -o missing.html http://localhost:3027/guides/missing curl -sS http://localhost:3027/archive/opening-2025 curl -sS http://localhost:3027/sitemap.xml

Use an HTML parser to read the article body and data-revision. Compare whether title, canonical, and JSON-LD use the same manuscript. Distinguish serialized strings inside script from actual body elements. Record local request results separately from production-domain results.

Also request /archive/missing and /policies/opening-hours. The former should return 404 and noindex without canonical; the latter should return 200 with opening-hours guidance. Check server-log exceptions as well as status codes. The archive page's file is app/archive/opening-2025/page.tsx.

§ 06SEO / GEO / AEO

Find content, URL, and date mismatches with an HTML parser

Save check-pages.mjs and the following validate-dates.mjs in the exercise folder alongside identity-time.mjs. Install the HTML parser with npm install --save-dev cheerio@1.2.0. Start the exercise's production server and run node check-pages.mjs http://localhost:3027.

// Install: npm install --save-dev cheerio@1.2.0 // Run: node check-pages.mjs http://localhost:3027 import assert from 'node:assert/strict'; import { load } from 'cheerio'; import { validateDates } from './validate-dates.mjs'; const base = new URL(process.argv[2] || 'http://localhost:3027'); const origin = 'https://example.com'; // Same value as SITE_ORIGIN in the sample const results = []; for (const [path, status] of [ ['/guides/opening-hours', 200], ['/guides/draft-guide', 404], ['/guides/missing', 404], ['/archive/opening-2025', 200], ['/archive/missing', 404], ['/policies/opening-hours', 200], ]) { const response = await fetch(new URL(path, base), { redirect: 'manual', signal: AbortSignal.timeout(10000), }); assert.equal(response.status, status, path + ': status'); const $ = load(await response.text()); const canonicals = $('link[rel="canonical"]'); const robots = $('meta[name="robots"]').map((_, e) => $(e).attr('content')).get().join(',') + ',' + (response.headers.get('x-robots-tag') || ''); if (status === 404) { assert.match(robots, /noindex/i, path + ': noindex'); assert.equal(canonicals.length, 0, path + ': inherited canonical'); assert.equal($('article[data-revision]').length, 0, path + ': leaked article'); } else { assert.equal(canonicals.length, 1, path + ': canonical count'); assert.equal(canonicals.attr('href'), origin + path, path + ': canonical'); assert.doesNotMatch(robots, /noindex/i, path + ': index blocked'); } if (path === '/guides/opening-hours') { const data = JSON.parse($('script[type="application/ld+json"]').text()); assert.equal(data.url, origin + path); assert.equal(data.name, $('article h1').text()); validateDates($, data); const body = $('article').clone(); body.find('script').remove(); assert.match(body.text(), /first Sunday of each month and public holidays/); assert.equal($('article a').attr('href'), '/policies/opening-hours'); } results.push({ path, status, passed: true }); } const xml = await fetch(new URL('/sitemap.xml', base)); assert.equal(xml.status, 200); const $xml = load(await xml.text(), { xmlMode: true }); const urls = $xml('loc').map((_, e) => $xml(e).text()).get(); assert(urls.includes(origin + '/guides/opening-hours')); assert(urls.includes(origin + '/archive/opening-2025')); assert(urls.includes(origin + '/policies/opening-hours')); assert(!urls.some(url => /draft-guide|missing/.test(url))); const moved = await fetch(new URL('/guides/library-hours', base), { redirect: 'manual' }); assert.equal(moved.status, 308); assert.equal(new URL(moved.headers.get('location'), base).pathname, '/guides/opening-hours'); console.log(JSON.stringify({ pages: results, sitemap: urls }, null, 2));

validateDates distinguishes publication and modification rows through data-date. It compares each row's label, datetime, and visible date with JSON-LD. Merely checking that a date value exists somewhere misses swapped publication and modification dates or a visible year changed to 1999. Finally, the check covers the old slug's 308 redirect and the sitemap.

The output lists the status of six pages and the sitemap URLs. It appears only after the old slug's 308 also passes. datePublished: label means a wrong label; dateModified: visible text means a visible-date mismatch; inherited canonical means an error page inherited a canonical URL. Save the failing item's actual HTML, then correct the relevant output field.

import assert from 'node:assert/strict'; import { formatContentDate } from './identity-time.mjs'; export function validateDates($, data) { for (const [key, label] of [['datePublished', 'Published'], ['dateModified', 'Updated']]) { const row = $(`article [data-date="${key}"]`); const expected = data[key]; assert.equal(row.length, expected === undefined ? 0 : 1, key + ': row count'); if (expected === undefined) continue; assert.equal(row.find('[data-label]').text().trim(), label, key + ': label'); assert.equal(row.find('time').length, 1, key + ': time count'); assert.equal(row.find('time').attr('datetime'), expected, key + ': datetime'); assert.equal(row.find('time').text().trim(), formatContentDate(expected), key + ': visible text'); } }

formatContentDate uses the same display policy for the page and the check. Regression tests create swapped labels, swapped datetime values, and a changed visible year, confirming that each fails. Compare both valid and invalid input to verify that the check itself catches errors.

Save the next file as validate-dates.test.mjs. Run node --test validate-dates.test.mjs in the exercise folder where Cheerio was installed to check one valid input and three altered error cases.

import test from 'node:test'; import assert from 'node:assert/strict'; import { load } from 'cheerio'; import { validateDates } from './validate-dates.mjs'; const data = { datePublished: '2026-10-01', dateModified: '2026-10-23T09:00:00+09:00' }; const html = `<article><p data-date="datePublished"><span data-label>Published</span><time datetime="2026-10-01">2026-10-1</time></p><p data-date="dateModified"><span data-label>Updated</span><time datetime="2026-10-23T09:00:00+09:00">2026-10-23</time></p></article>`; test('Correct labels, machine dates, and visible dates pass', () => validateDates(load(html), data)); test('Swapped labels, swapped machine values, and wrong visible years each fail', () => { const labelSwap = html.replace('Published', 'TEMP').replace('Updated', 'Published').replace('TEMP', 'Updated'); const valueSwap = html.replace('datetime="2026-10-01"', 'datetime="TEMP"') .replace('datetime="2026-10-23T09:00:00+09:00"', 'datetime="2026-10-01"') .replace('datetime="TEMP"', 'datetime="2026-10-23T09:00:00+09:00"'); for (const bad of [labelSwap, valueSwap, html.replace('2026-10-1', '1999-1-1')]) assert.throws(() => validateDates(load(bad), data)); });

Visible labels are checked because identical date numbers can have different meanings. Showing the effective date in a “Published” row can make future operating hours appear current. validateDates checks publication and modification labels against their values. Compare the manuscript and its evidence to verify that applicable-period statements match the actual operational facts.

§ 07SEO / GEO / AEO

Use content and links directly in the browser

Open the listing in an unauthenticated window and click the first, middle, and last articles. Follow pagination and related-article links. Check that Back and Reload retain the same content. Actually open photos and attachments and play videos. Check that source links do not lead to unrelated documents with merely similar titles.

Read how titles, long URLs, and code wrap on wide and narrow screens. If a table becomes vertical, check that each value retains its column label. Switch themes to compare text/background contrast, and switch languages to verify that paragraphs and links remain.

The browser's Network tab shows requests, responses, and transfer timing; Console shows execution messages and errors. Inspect failed document, image, and script responses and trace their functional impact. If content absent from HTML appears only in the browser, compare DOM and data requests before and after JavaScript runs. Check Google's processed result again through URL Inspection after deployment.

§ 08SEO / GEO / AEO

Compare sitemaps, links, and structured data

Compare the sitemap URL set with the expected public-data URL set. Classify duplicates, omissions, withdrawn URLs, and redirects separately. For sitemap indexes, read child files too. When collecting status codes for all targets, limit concurrency and request rate to account for service load, and save failing URLs with reasons.

Check that detail-page canonical, sitemap URL, and internal links agree. If every page's modification date was overwritten with deployment time, fix the generator. For hreflang, check successful responses and reciprocal references on the other language page.

Parse every application/ld+json block on the page as JSON. Fix syntax errors first, then compare titles, dates, authors, and URLs with visible content. A rich result is a search presentation with extra information beyond a standard link. Further check Google's supported types with Rich Results Test. Distinguish missing required fields from missing recommended fields when comparing warnings with the type's documentation.

§ 09SEO / GEO / AEO

Compare publication, edits, withdrawal, and restoration through the same paths

If content functionality changed, check one article's lifecycle. A draft should be absent from public views; after publication, listing, detail, sitemap, and sharing information should agree. After editing title, dates, or evidence, check that old values do not remain in caches. After withdrawal, verify that public links, internal search, and your own chatbot no longer use it.

Test restoration by publishing a test document, editing it, withdrawing it, then republishing an earlier revision. Read the restored content, sources, and images, and verify that the current working draft remains. Preserve the original publication date and record the content-changing restoration time as the modification date.

Compare whether a new content type uses the same publication rules in listing, detail, and sitemap. If its page appears but it is missing from the sitemap, related links, or monitoring, fix registration. A combined listing with two sources must not silently treat one failed query as empty data. The user interface may report partial failure, but sitemap and monitoring jobs that establish a complete list must record incomplete results distinctly.

Compare original text, photos, and links on redesigned main and archive pages. Include post-click areas, videos, and browser-specific display outside automated checks in the verification scope. Navigate from listings to details, related articles, and sources, comparing content and linked addresses.

§ 10SEO / GEO / AEO

Verify the deployment version and production domain

Before deployment, inspect changed files and content lists and record the previous working version's identifier. If code and content both changed, record the deployed combination. Change storage structures in an order that preserves readability of existing data. Separating new-field addition, data backfill, read switching, and old-field removal reduces conflicts between intermediate versions.

Check build completion and commit or release ID in the deployment tool. Then verify that the actual production domain points to that deployment. Request preview and production URLs separately. Re-request affected public paths and compare headers, body, canonical URL, and sitemap.

With CMS and CDN caches, check revalidation and invalidation along the content-update path. If the article changes but listing, sitemap, or sharing card remains old, identify the data and cache each reads. All public paths should agree after editing or withdrawing the latest article.

§ 11SEO / GEO / AEO

Check DNS, TLS, caches, and frontend blocking on production paths

Use dig to query DNS A, AAAA, and CNAME records. dig is a DNS-query tool. Compare actual answers with hosting instructions and check configured IPv4 and IPv6 paths separately. Replace example.com and paths below with the public addresses being checked.

dig +noall +answer example.com A dig +noall +answer example.com AAAA dig +noall +answer www.example.com CNAME CHECK_URL='https://example.com/guides/opening-hours' curl -sS --max-time 30 -D infra.headers -o infra.html \ -w 'status=%{http_code} dns=%{time_namelookup} connect=%{time_connect} tls=%{time_appconnect} first_byte=%{time_starttransfer} total=%{time_total}\n' \ "$CHECK_URL" rg -n -i 'HTTP/|location:|cache-control:|age:|etag:|vary:|x-robots-tag:|content-type:' infra.headers

curl sends requests to URLs. -D saves response headers, -o saves the body, and -w prints specified measurements. --max-time 30 allows up to 30 seconds for the whole request. Reported times are cumulative seconds since request start. time_appconnect marks TLS connection completion; time_starttransfer marks the first response byte. Both include earlier stages, so neither alone is server processing time.

Use curl's default TLS certificate verification. On failure, check domain name, expiry, certificate chain, and connection path. Results obtained with -k cannot establish certificate validity because verification was skipped. Also request HTTP URLs to verify redirects to the HTTPS canonical URL.

Save headers and body for first and repeat requests to the same URL. Age reports the age of a cached response; read platform-specific cache-status headers too. Even on a cache hit, compare the body with the latest published version. After editing or withdrawing verification material, track when detail pages, listings, sitemaps, and images update.

Find the check's timestamp and path in WAF and CDN logs and connect them to origin logs. If a public article returns a challenge, 403, or 429, identify the matching rule. The core content delivered to people and crawlers should use the same public material. Also verify the body in actual search-tool crawl results.

§ 12SEO / GEO / AEO

Recover according to the failure type

If public detail pages become 5xx or private material leaks after deployment, first restore the previous working deployment or block publication on the affected path. If only metadata is wrong and content is intact, narrowly revert the confirmed configuration cause. After recovery, recheck the originally failing URL and adjacent states.

Rolling back code does not automatically restore CMS content or database changes. Restore wrongly published content through CMS history. For schema changes, first check whether earlier code can read the current data. Making a full database restore the default first response can lose valid subsequent entries.

Record failure symptoms, affected URLs, deployment ID, recovery time, and post-recovery observations. Once production responses recover, separately track how long old material remains in search and AI observations. Search recrawling occurs on a different schedule from production-code deployment.

If external search does not change immediately after recovery, first check its latest crawl time. While a failure-era response remains in the search system, old material may appear despite a healthy current server. Connecting the recovered response with subsequent crawl results helps decide whether more code changes are needed or whether external data updates need checking.

§ 13SEO / GEO / AEO

Reproduce image, article, and feed failures through requests

For image optimization, check file size, access after withdrawal, and candidate widths together. Inputs include a large source, a small 200px source, withdrawal during transformation, and concurrent same-width requests. Save media.test.mjs below in the image-exercise folder and run node --test media.test.mjs. The server starts on a random local port and closes afterward.

import test from 'node:test'; import assert from 'node:assert/strict'; import sharp from 'sharp'; import { createMediaStore } from './media-store.mjs'; import { createDemoServer, sampleImage } from './media-demo.mjs'; import { article, renderArticle } from './article-jsonld.mjs'; import { renderFeed, escapeXml } from './feed.mjs'; const now = '2026-10-24T09:00:00+09:00'; test('Concurrent same-width requests transform once and return the actual pixel width', async () => { const store = await createMediaStore(await sampleImage()); const [a, b] = await Promise.all([store.read(640), store.read(640)]); assert.deepEqual(a.body, b.body); assert.equal(store.stats().transforms, 1); assert.equal((await sharp(a.body).metadata()).width, 640); assert.equal(a.headers['Cache-Control'], 'private, no-store, max-age=0'); assert.equal((await store.read(999)).status, 400); }); test('Withdrawal during transformation makes pending requests return 404 and blocks originals and derivatives', async () => { const store = await createMediaStore(await sampleImage()); const pending = store.read(640); store.setPublished(false); assert.equal((await pending).status, 404); for (const width of [null, 320, 640, 1280]) assert.equal((await store.read(width)).status, 404); store.setPublished(true); assert.equal((await store.read(640)).status, 200); assert.equal(store.stats().transforms, 1); }); test('Small originals are not enlarged and srcset contains no duplicate widths', async () => { const source = await sharp({ create: { width: 200, height: 100, channels: 3, background: 'red' } }).jpeg().toBuffer(); const store = await createMediaStore(source); assert.equal((await store.read(1280)).width, 200); const server = createDemoServer(store); await new Promise(resolve => server.listen(0, '127.0.0.1', resolve)); try { const base = `http://127.0.0.1:${server.address().port}`; const html = await (await fetch(base)).text(); assert.equal((html.match(/ 200w/g) ?? []).length, 1); assert(!html.includes('1280w')); await fetch(base + '/media/photo?w=640'); store.setPublished(false); for (const path of ['/media/photo', '/media/photo?w=640', '/news/new-hours', '/']) assert.equal((await fetch(base + path)).status, 404); const feed = await (await fetch(base + '/rss.xml')).text(); assert(!feed.includes('<item>')); } finally { await new Promise(resolve => server.close(resolve)); } }); test('Visible image, sharing image, Article.image, and dates use the same source', () => { const { html, structured } = renderArticle('https://example.com', { path: '/media/photo?w=1280', width: 1280, height: 800 }, now); assert.equal(structured.image[0], 'https://example.com/media/photo?w=1280'); assert(html.includes(`src="${structured.image[0]}"`)); assert(html.includes(`content="${structured.image[0]}"`)); assert(html.includes(`datetime="${structured.datePublished}"`)); assert(html.includes(`datetime="${structured.dateModified}"`)); assert.throws(() => renderArticle('https://example.com', { path: '/photo' }, '2026-09-01T00:00:00Z')); }); test('The feed excludes drafts, withdrawn and scheduled posts and retains ID and first publication after edits and moves', () => { const changed = { ...article, path: '/news/revised-hours', summary: 'A & B < C', contentModifiedAt: now }; const xml = renderFeed([changed, { ...article, id: 'draft', status: 'draft' }, { ...article, id: 'withdrawn', status: 'withdrawn' }, { ...article, id: 'future', publicFrom: '2027-01-01T00:00:00Z' }], 'https://example.com', now); assert.equal((xml.match(/<item>/g) ?? []).length, 1); assert(xml.includes('A &amp;amp; B &amp;lt; C')); assert(xml.includes('/#document-new-hours</guid>')); assert(xml.includes('/news/revised-hours</link>')); assert(xml.includes('Wed, 30 Sep 2026 00:00:00 GMT')); assert(!renderFeed([{ ...article, status: 'withdrawn' }], 'https://example.com', now).includes('<item>')); }); test('The feed preserves date precision and rejects forbidden XML characters and reversed dates', () => { const xml = renderFeed([{ ...article, publishedAt: '2026-09-30' }], 'https://example.com', now); assert(!xml.includes('<pubDate>')); assert.throws(() => escapeXml('bad\u0000')); assert.throws(() => escapeXml('bad\uD800')); assert.throws(() => renderFeed([{ ...article, contentModifiedAt: '2026-09-01' }], 'https://example.com', now)); });

The first test checks that two concurrent reads produce only one transformation. The second withdraws during transformation and checks both the pending request and subsequent source/derivative requests. The third checks that a 200px source is not labeled 1280w and verifies withdrawal through the actual HTTP path. The article test checks that dates and images reach HTML and JSON-LD from the same input. Feed tests cover excluding drafts, scheduled and withdrawn posts, stable IDs, date precision, and XML special characters.

In the browser, additionally verify that article photos decode and RSS parses as XML without errors. Click the four-second video link, paste the URL into a new window, and check that the same notice appears. Existing content and video seeking must still work after image-delivery changes so readers can reach the evidence.

After generating the video file, save the following as video.test.mjs and run node --test video.test.mjs. Request ranges at the beginning, end, and through the end of the file, comparing received bytes with the source. Check that out-of-file and reversed ranges return 416.

import test from 'node:test'; import assert from 'node:assert/strict'; import { readFile } from 'node:fs/promises'; import { createDemoServer } from './media-demo.mjs'; // Run after creating talk.mp4 with node make-video-demo.mjs. test('Video byte ranges return the requested bytes and reject out-of-file requests', async () => { const file = await readFile(new URL('./talk.mp4', import.meta.url)); const server = createDemoServer(null); await new Promise(resolve => server.listen(0, '127.0.0.1', resolve)); try { const url = `http://127.0.0.1:${server.address().port}/talk.mp4`; for (const [range, start, end] of [ ['bytes=0-99', 0, 99], ['bytes=-100', file.length - 100, file.length - 1], [`bytes=${file.length - 100}-`, file.length - 100, file.length - 1], ]) { const response = await fetch(url, { headers: { Range: range } }); assert.equal(response.status, 206); assert.equal(response.headers.get('content-range'), `bytes ${start}-${end}/${file.length}`); assert.deepEqual(Buffer.from(await response.arrayBuffer()), file.subarray(start, end + 1)); } for (const range of ['bytes=999999999-', 'bytes=20-10', 'bytes=-0', 'bytes=-']) assert.equal((await fetch(url, { headers: { Range: range } })).status, 416); } finally { await new Promise(resolve => server.close(resolve)); } });

— FIN —