mirror of
https://github.com/supabase/supabase.git
synced 2026-10-05 01:15:03 +03:00
## What kind of change does this PR introduce? - Resolves FE-1960 - Resolves FE-1983 - Resolves DEPR-207 ## What is the current behavior? Page titles between surfaces are inconsistent and vague. Sometimes they say the product name: ``` My Project | My Org | Supabase ``` ...even when on a specific surface like Database > Tables. Other times they show the entity name but skip over the project or org name : ``` Edge Functions | Supabase ``` ## What is the new behavior? Page titles *mostly* (see below) follow the same format: ``` users | Table Editor | My Project | My Org | Supabase hello-world | Logs | Edge Functions | My Project | My Org | Supabase Backups | Database | My Project | My Org | Supabase Authentication | My Project | My Org | Supabase ``` That format is: entity, section, surface, project, org, brand ## Additional context This is stacked PR 1/5 for page title improvements. Includes the core title utility and ProjectLayout integration/tests. Follow-up stacked PRs are based on this branch: - https://github.com/supabase/supabase/pull/43534 - https://github.com/supabase/supabase/pull/43535 - https://github.com/supabase/supabase/pull/43536 - https://github.com/supabase/supabase/pull/43537 This one should be merged first. The others (listed right above) can _then_ be merged in any order.
95 lines
2.7 KiB
TypeScript
95 lines
2.7 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
|
|
import { buildStudioPageTitle, STUDIO_PAGE_TITLE_SEPARATOR } from './page-title'
|
|
|
|
describe('buildStudioPageTitle', () => {
|
|
it('builds a project-scoped title in most-specific-first order', () => {
|
|
expect(
|
|
buildStudioPageTitle({
|
|
surface: 'Database',
|
|
project: 'Acme Project',
|
|
org: 'Acme Org',
|
|
brand: 'Supabase',
|
|
})
|
|
).toBe(
|
|
`Database${STUDIO_PAGE_TITLE_SEPARATOR}Acme Project${STUDIO_PAGE_TITLE_SEPARATOR}Acme Org${STUDIO_PAGE_TITLE_SEPARATOR}Supabase`
|
|
)
|
|
})
|
|
|
|
it('includes entity and section when provided', () => {
|
|
expect(
|
|
buildStudioPageTitle({
|
|
entity: 'users',
|
|
section: 'Tables',
|
|
surface: 'Database',
|
|
project: 'Acme Project',
|
|
org: 'Acme Org',
|
|
brand: 'Supabase',
|
|
})
|
|
).toBe(
|
|
`users${STUDIO_PAGE_TITLE_SEPARATOR}Tables${STUDIO_PAGE_TITLE_SEPARATOR}Database${STUDIO_PAGE_TITLE_SEPARATOR}Acme Project${STUDIO_PAGE_TITLE_SEPARATOR}Acme Org${STUDIO_PAGE_TITLE_SEPARATOR}Supabase`
|
|
)
|
|
})
|
|
|
|
it('omits missing segments', () => {
|
|
expect(
|
|
buildStudioPageTitle({
|
|
section: 'Authentication',
|
|
project: 'Acme Project',
|
|
brand: 'Supabase',
|
|
})
|
|
).toBe(
|
|
`Authentication${STUDIO_PAGE_TITLE_SEPARATOR}Acme Project${STUDIO_PAGE_TITLE_SEPARATOR}Supabase`
|
|
)
|
|
})
|
|
|
|
it('deduplicates adjacent segments case-insensitively', () => {
|
|
expect(
|
|
buildStudioPageTitle({
|
|
section: 'Database',
|
|
surface: 'database',
|
|
project: 'Acme Project',
|
|
org: 'Acme Org',
|
|
brand: 'Supabase',
|
|
})
|
|
).toBe(
|
|
`Database${STUDIO_PAGE_TITLE_SEPARATOR}Acme Project${STUDIO_PAGE_TITLE_SEPARATOR}Acme Org${STUDIO_PAGE_TITLE_SEPARATOR}Supabase`
|
|
)
|
|
})
|
|
|
|
it('normalizes whitespace in each segment', () => {
|
|
expect(
|
|
buildStudioPageTitle({
|
|
entity: ' hello world ',
|
|
surface: ' Edge Functions ',
|
|
brand: ' Supabase ',
|
|
})
|
|
).toBe(
|
|
`hello world${STUDIO_PAGE_TITLE_SEPARATOR}Edge Functions${STUDIO_PAGE_TITLE_SEPARATOR}Supabase`
|
|
)
|
|
})
|
|
|
|
it('truncates very long segments', () => {
|
|
const longName = 'x'.repeat(80)
|
|
|
|
expect(
|
|
buildStudioPageTitle({
|
|
entity: longName,
|
|
surface: 'Table Editor',
|
|
brand: 'Supabase',
|
|
})
|
|
).toBe(
|
|
`${'x'.repeat(59)}…${STUDIO_PAGE_TITLE_SEPARATOR}Table Editor${STUDIO_PAGE_TITLE_SEPARATOR}Supabase`
|
|
)
|
|
})
|
|
|
|
it('supports custom brand titles', () => {
|
|
expect(
|
|
buildStudioPageTitle({
|
|
surface: 'Settings',
|
|
brand: 'Supabase Studio',
|
|
})
|
|
).toBe(`Settings${STUDIO_PAGE_TITLE_SEPARATOR}Supabase Studio`)
|
|
})
|
|
})
|