mirror of
https://github.com/supabase/supabase.git
synced 2026-05-16 15:49:19 +08:00
## Summary Eliminates the Google Search Console "Missing field 'item' (in 'itemListElement')" critical error on 230 `/docs/guides/*` pages. The schema was emitting `ListItem`s without an `item` field for intermediate category nodes that lack a URL in the docs nav. Per [Google's spec](https://developers.google.com/search/docs/appearance/structured-data/breadcrumb), `item` is required on every BreadcrumbList position except the last leaf — so url-less items are filtered out instead. Also fixes a smaller quality gap surfaced during preview verification: the `auth` section root in `NavigationMenu.constants.ts` was missing a `url`, so auth trails were dropping the "Auth" breadcrumb level (`Docs > Guides > JSON Web Tokens (JWT) > Overview` instead of `Docs > Guides > Auth > JSON Web Tokens (JWT) > Overview`). Every other section root already has a `url`; auth was the lone outlier. ## Testing Tested locally via vitest (`pnpm --filter docs exec vitest run lib/json-ld.test.ts`): - [x] All-urls chain: every `itemListElement` has string `item` and `name` - [x] Leaf-url-mismatch: leaf uses `pathname` even when the chain leaf URL differs - [x] All-url-less chain: returns `null` - [x] Empty chain: returns `null` Tested on the preview deploy against 7 representative GSC-flagged paths: - [x] `/docs/guides/getting-started/ai-prompts` — 4 positions, 0 missing - [x] `/docs/guides/getting-started/ai-skills` — 4 positions, 0 missing - [x] `/docs/guides/auth/jwts` — 4 positions, 0 missing (after auth fix: includes "Auth") - [x] `/docs/guides/auth/social-login/auth-google` — 4 positions, 0 missing (after auth fix: includes "Auth") - [x] `/docs/guides/database/postgres-js` — 4 positions, 0 missing - [x] `/docs/guides/storage/quickstart` — 4 positions, 0 missing - [x] `/docs/guides/platform/migrating-within-supabase/dashboard-restore` — 5 positions, 0 missing Post-merge: - [ ] validator.schema.org against deployed URL: 0 errors - [ ] GSC "Validate fix" on the breadcrumb issue (1-2 week re-crawl window) ## Linear - fixes GROWTH-835 <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved breadcrumb validation to filter incomplete entries and avoid broken documentation links. * Restored root link for the Auth navigation section so the Auth menu item now navigates to /guides/auth. * **Tests** * Added comprehensive tests covering breadcrumb generation and edge cases. * **Refactor** * Streamlined breadcrumb JSON‑LD schema generation for clearer output and maintainability. [](https://app.coderabbit.ai/change-stack/supabase/supabase/pull/45744) <!-- end of auto-generated comment: release notes by coderabbit.ai -->
60 lines
1.7 KiB
TypeScript
60 lines
1.7 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
import { breadcrumbListSchema } from './json-ld'
|
|
|
|
describe('breadcrumbListSchema', () => {
|
|
let warn: ReturnType<typeof vi.spyOn>
|
|
|
|
beforeEach(() => {
|
|
warn = vi.spyOn(console, 'warn').mockImplementation(() => {})
|
|
})
|
|
|
|
afterEach(() => {
|
|
warn.mockRestore()
|
|
})
|
|
|
|
it('emits item and name on every position when all chain items have urls', () => {
|
|
const result = breadcrumbListSchema({
|
|
pathname: '/guides/auth/jwts',
|
|
chain: [
|
|
{ name: 'Authentication', url: '/guides/auth' },
|
|
{ name: 'JWTs', url: '/guides/auth/jwts' },
|
|
],
|
|
})
|
|
|
|
expect(result).not.toBeNull()
|
|
expect(result!.itemListElement).toHaveLength(4)
|
|
for (const entry of result!.itemListElement) {
|
|
expect(typeof entry.item).toBe('string')
|
|
expect(entry.item).toMatch(/^https?:\/\//)
|
|
expect(typeof entry.name).toBe('string')
|
|
}
|
|
})
|
|
|
|
it('uses pathname for the leaf url even when chain leaf url differs', () => {
|
|
const result = breadcrumbListSchema({
|
|
pathname: '/guides/database/postgres-js',
|
|
chain: [{ name: 'Postgres.js', url: '/guides/database/postgres-js-old' }],
|
|
})
|
|
|
|
expect(result).not.toBeNull()
|
|
const leaf = result!.itemListElement.at(-1)
|
|
expect(leaf?.item).toMatch(/\/guides\/database\/postgres-js$/)
|
|
})
|
|
|
|
it('returns null when every chain item is url-less', () => {
|
|
const result = breadcrumbListSchema({
|
|
pathname: '/guides/some-broken-route',
|
|
chain: [{ name: 'Category A' }, { name: 'Category B' }],
|
|
})
|
|
|
|
expect(result).toBeNull()
|
|
})
|
|
|
|
it('returns null on an empty chain', () => {
|
|
const result = breadcrumbListSchema({ pathname: '/guides', chain: [] })
|
|
|
|
expect(result).toBeNull()
|
|
})
|
|
})
|