|
|
|
|
@ -1,7 +1,5 @@
|
|
|
|
|
import { render, screen } from '@testing-library/react'
|
|
|
|
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
|
|
|
|
|
|
|
|
// Import component after mocks are set up
|
|
|
|
|
import Description from './index'
|
|
|
|
|
|
|
|
|
|
// ================================
|
|
|
|
|
@ -30,20 +28,18 @@ const commonTranslations: Record<string, string> = {
|
|
|
|
|
'operation.in': 'in',
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Mock getLocaleOnServer and translate
|
|
|
|
|
vi.mock('@/i18n-config/server', () => ({
|
|
|
|
|
getLocaleOnServer: vi.fn(() => Promise.resolve(mockDefaultLocale)),
|
|
|
|
|
getTranslation: vi.fn((locale: string, ns: string) => {
|
|
|
|
|
return Promise.resolve({
|
|
|
|
|
t: (key: string) => {
|
|
|
|
|
if (ns === 'plugin')
|
|
|
|
|
return pluginTranslations[key] || key
|
|
|
|
|
if (ns === 'common')
|
|
|
|
|
return commonTranslations[key] || key
|
|
|
|
|
return key
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
}),
|
|
|
|
|
// Mock i18n hooks
|
|
|
|
|
vi.mock('#i18n', () => ({
|
|
|
|
|
useLocale: vi.fn(() => mockDefaultLocale),
|
|
|
|
|
useTranslation: vi.fn((ns: string) => ({
|
|
|
|
|
t: (key: string) => {
|
|
|
|
|
if (ns === 'plugin')
|
|
|
|
|
return pluginTranslations[key] || key
|
|
|
|
|
if (ns === 'common')
|
|
|
|
|
return commonTranslations[key] || key
|
|
|
|
|
return key
|
|
|
|
|
},
|
|
|
|
|
})),
|
|
|
|
|
}))
|
|
|
|
|
|
|
|
|
|
// ================================
|
|
|
|
|
@ -59,29 +55,29 @@ describe('Description', () => {
|
|
|
|
|
// Rendering Tests
|
|
|
|
|
// ================================
|
|
|
|
|
describe('Rendering', () => {
|
|
|
|
|
it('should render without crashing', async () => {
|
|
|
|
|
const { container } = render(await Description({}))
|
|
|
|
|
it('should render without crashing', () => {
|
|
|
|
|
const { container } = render(<Description />)
|
|
|
|
|
|
|
|
|
|
expect(container.firstChild).toBeInTheDocument()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should render h1 heading with empower text', async () => {
|
|
|
|
|
render(await Description({}))
|
|
|
|
|
it('should render h1 heading with empower text', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
const heading = screen.getByRole('heading', { level: 1 })
|
|
|
|
|
expect(heading).toBeInTheDocument()
|
|
|
|
|
expect(heading).toHaveTextContent('Empower your AI development')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should render h2 subheading', async () => {
|
|
|
|
|
render(await Description({}))
|
|
|
|
|
it('should render h2 subheading', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
const subheading = screen.getByRole('heading', { level: 2 })
|
|
|
|
|
expect(subheading).toBeInTheDocument()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should apply correct CSS classes to h1', async () => {
|
|
|
|
|
render(await Description({}))
|
|
|
|
|
it('should apply correct CSS classes to h1', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
const heading = screen.getByRole('heading', { level: 1 })
|
|
|
|
|
expect(heading).toHaveClass('title-4xl-semi-bold')
|
|
|
|
|
@ -90,8 +86,8 @@ describe('Description', () => {
|
|
|
|
|
expect(heading).toHaveClass('text-text-primary')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should apply correct CSS classes to h2', async () => {
|
|
|
|
|
render(await Description({}))
|
|
|
|
|
it('should apply correct CSS classes to h2', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
const subheading = screen.getByRole('heading', { level: 2 })
|
|
|
|
|
expect(subheading).toHaveClass('body-md-regular')
|
|
|
|
|
@ -104,14 +100,18 @@ describe('Description', () => {
|
|
|
|
|
// Non-Chinese Locale Rendering Tests
|
|
|
|
|
// ================================
|
|
|
|
|
describe('Non-Chinese Locale Rendering', () => {
|
|
|
|
|
it('should render discover text for en-US locale', async () => {
|
|
|
|
|
render(await Description({ locale: 'en-US' }))
|
|
|
|
|
beforeEach(() => {
|
|
|
|
|
mockDefaultLocale = 'en-US'
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should render discover text for en-US locale', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
expect(screen.getByText(/Discover/)).toBeInTheDocument()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should render all category names', async () => {
|
|
|
|
|
render(await Description({ locale: 'en-US' }))
|
|
|
|
|
it('should render all category names', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
expect(screen.getByText('Models')).toBeInTheDocument()
|
|
|
|
|
expect(screen.getByText('Tools')).toBeInTheDocument()
|
|
|
|
|
@ -122,36 +122,36 @@ describe('Description', () => {
|
|
|
|
|
expect(screen.getByText('Bundles')).toBeInTheDocument()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should render "and" conjunction text', async () => {
|
|
|
|
|
render(await Description({ locale: 'en-US' }))
|
|
|
|
|
it('should render "and" conjunction text', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
const subheading = screen.getByRole('heading', { level: 2 })
|
|
|
|
|
expect(subheading.textContent).toContain('and')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should render "in" preposition at the end for non-Chinese locales', async () => {
|
|
|
|
|
render(await Description({ locale: 'en-US' }))
|
|
|
|
|
it('should render "in" preposition at the end for non-Chinese locales', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
expect(screen.getByText('in')).toBeInTheDocument()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should render Dify Marketplace text at the end for non-Chinese locales', async () => {
|
|
|
|
|
render(await Description({ locale: 'en-US' }))
|
|
|
|
|
it('should render Dify Marketplace text at the end for non-Chinese locales', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
const subheading = screen.getByRole('heading', { level: 2 })
|
|
|
|
|
expect(subheading.textContent).toContain('Dify Marketplace')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should render category spans with styled underline effect', async () => {
|
|
|
|
|
const { container } = render(await Description({ locale: 'en-US' }))
|
|
|
|
|
it('should render category spans with styled underline effect', () => {
|
|
|
|
|
const { container } = render(<Description />)
|
|
|
|
|
|
|
|
|
|
const styledSpans = container.querySelectorAll('.body-md-medium.relative.z-\\[1\\]')
|
|
|
|
|
// 7 category spans (models, tools, datasources, triggers, agents, extensions, bundles)
|
|
|
|
|
expect(styledSpans.length).toBe(7)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should apply text-text-secondary class to category spans', async () => {
|
|
|
|
|
const { container } = render(await Description({ locale: 'en-US' }))
|
|
|
|
|
it('should apply text-text-secondary class to category spans', () => {
|
|
|
|
|
const { container } = render(<Description />)
|
|
|
|
|
|
|
|
|
|
const styledSpans = container.querySelectorAll('.text-text-secondary')
|
|
|
|
|
expect(styledSpans.length).toBeGreaterThanOrEqual(7)
|
|
|
|
|
@ -162,29 +162,33 @@ describe('Description', () => {
|
|
|
|
|
// Chinese (zh-Hans) Locale Rendering Tests
|
|
|
|
|
// ================================
|
|
|
|
|
describe('Chinese (zh-Hans) Locale Rendering', () => {
|
|
|
|
|
it('should render "in" text at the beginning for zh-Hans locale', async () => {
|
|
|
|
|
render(await Description({ locale: 'zh-Hans' }))
|
|
|
|
|
beforeEach(() => {
|
|
|
|
|
mockDefaultLocale = 'zh-Hans'
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should render "in" text at the beginning for zh-Hans locale', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
// In zh-Hans mode, "in" appears at the beginning
|
|
|
|
|
const inElements = screen.getAllByText('in')
|
|
|
|
|
expect(inElements.length).toBeGreaterThanOrEqual(1)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should render Dify Marketplace text for zh-Hans locale', async () => {
|
|
|
|
|
render(await Description({ locale: 'zh-Hans' }))
|
|
|
|
|
it('should render Dify Marketplace text for zh-Hans locale', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
const subheading = screen.getByRole('heading', { level: 2 })
|
|
|
|
|
expect(subheading.textContent).toContain('Dify Marketplace')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should render discover text for zh-Hans locale', async () => {
|
|
|
|
|
render(await Description({ locale: 'zh-Hans' }))
|
|
|
|
|
it('should render discover text for zh-Hans locale', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
expect(screen.getByText(/Discover/)).toBeInTheDocument()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should render all categories for zh-Hans locale', async () => {
|
|
|
|
|
render(await Description({ locale: 'zh-Hans' }))
|
|
|
|
|
it('should render all categories for zh-Hans locale', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
expect(screen.getByText('Models')).toBeInTheDocument()
|
|
|
|
|
expect(screen.getByText('Tools')).toBeInTheDocument()
|
|
|
|
|
@ -195,8 +199,8 @@ describe('Description', () => {
|
|
|
|
|
expect(screen.getByText('Bundles')).toBeInTheDocument()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should render both zh-Hans specific elements and shared elements', async () => {
|
|
|
|
|
render(await Description({ locale: 'zh-Hans' }))
|
|
|
|
|
it('should render both zh-Hans specific elements and shared elements', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
// zh-Hans has specific element order: "in" -> Dify Marketplace -> Discover
|
|
|
|
|
// then the same category list with "and" -> Bundles
|
|
|
|
|
@ -206,61 +210,57 @@ describe('Description', () => {
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// ================================
|
|
|
|
|
// Locale Prop Variations Tests
|
|
|
|
|
// Locale Variations Tests
|
|
|
|
|
// ================================
|
|
|
|
|
describe('Locale Prop Variations', () => {
|
|
|
|
|
it('should use default locale when locale prop is undefined', async () => {
|
|
|
|
|
describe('Locale Variations', () => {
|
|
|
|
|
it('should use en-US locale by default', () => {
|
|
|
|
|
mockDefaultLocale = 'en-US'
|
|
|
|
|
render(await Description({}))
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
// Should use the default locale from getLocaleOnServer
|
|
|
|
|
expect(screen.getByText('Empower your AI development')).toBeInTheDocument()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should use provided locale prop instead of default', async () => {
|
|
|
|
|
it('should handle ja-JP locale as non-Chinese', () => {
|
|
|
|
|
mockDefaultLocale = 'ja-JP'
|
|
|
|
|
render(await Description({ locale: 'en-US' }))
|
|
|
|
|
|
|
|
|
|
// The locale prop should be used, triggering non-Chinese rendering
|
|
|
|
|
const subheading = screen.getByRole('heading', { level: 2 })
|
|
|
|
|
expect(subheading).toBeInTheDocument()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should handle ja-JP locale as non-Chinese', async () => {
|
|
|
|
|
render(await Description({ locale: 'ja-JP' }))
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
// Should render in non-Chinese format (discover first, then "in Dify Marketplace" at end)
|
|
|
|
|
const subheading = screen.getByRole('heading', { level: 2 })
|
|
|
|
|
expect(subheading.textContent).toContain('Dify Marketplace')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should handle ko-KR locale as non-Chinese', async () => {
|
|
|
|
|
render(await Description({ locale: 'ko-KR' }))
|
|
|
|
|
it('should handle ko-KR locale as non-Chinese', () => {
|
|
|
|
|
mockDefaultLocale = 'ko-KR'
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
// Should render in non-Chinese format
|
|
|
|
|
expect(screen.getByText('Empower your AI development')).toBeInTheDocument()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should handle de-DE locale as non-Chinese', async () => {
|
|
|
|
|
render(await Description({ locale: 'de-DE' }))
|
|
|
|
|
it('should handle de-DE locale as non-Chinese', () => {
|
|
|
|
|
mockDefaultLocale = 'de-DE'
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
expect(screen.getByText('Empower your AI development')).toBeInTheDocument()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should handle fr-FR locale as non-Chinese', async () => {
|
|
|
|
|
render(await Description({ locale: 'fr-FR' }))
|
|
|
|
|
it('should handle fr-FR locale as non-Chinese', () => {
|
|
|
|
|
mockDefaultLocale = 'fr-FR'
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
expect(screen.getByText('Empower your AI development')).toBeInTheDocument()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should handle pt-BR locale as non-Chinese', async () => {
|
|
|
|
|
render(await Description({ locale: 'pt-BR' }))
|
|
|
|
|
it('should handle pt-BR locale as non-Chinese', () => {
|
|
|
|
|
mockDefaultLocale = 'pt-BR'
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
expect(screen.getByText('Empower your AI development')).toBeInTheDocument()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should handle es-ES locale as non-Chinese', async () => {
|
|
|
|
|
render(await Description({ locale: 'es-ES' }))
|
|
|
|
|
it('should handle es-ES locale as non-Chinese', () => {
|
|
|
|
|
mockDefaultLocale = 'es-ES'
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
expect(screen.getByText('Empower your AI development')).toBeInTheDocument()
|
|
|
|
|
})
|
|
|
|
|
@ -270,24 +270,27 @@ describe('Description', () => {
|
|
|
|
|
// Conditional Rendering Tests
|
|
|
|
|
// ================================
|
|
|
|
|
describe('Conditional Rendering', () => {
|
|
|
|
|
it('should render zh-Hans specific content when locale is zh-Hans', async () => {
|
|
|
|
|
const { container } = render(await Description({ locale: 'zh-Hans' }))
|
|
|
|
|
it('should render zh-Hans specific content when locale is zh-Hans', () => {
|
|
|
|
|
mockDefaultLocale = 'zh-Hans'
|
|
|
|
|
const { container } = render(<Description />)
|
|
|
|
|
|
|
|
|
|
// zh-Hans has additional span with mr-1 before "in" text at the start
|
|
|
|
|
const mrSpan = container.querySelector('span.mr-1')
|
|
|
|
|
expect(mrSpan).toBeInTheDocument()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should render non-Chinese specific content when locale is not zh-Hans', async () => {
|
|
|
|
|
render(await Description({ locale: 'en-US' }))
|
|
|
|
|
it('should render non-Chinese specific content when locale is not zh-Hans', () => {
|
|
|
|
|
mockDefaultLocale = 'en-US'
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
// Non-Chinese has "in" and "Dify Marketplace" at the end
|
|
|
|
|
const subheading = screen.getByRole('heading', { level: 2 })
|
|
|
|
|
expect(subheading.textContent).toContain('Dify Marketplace')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should not render zh-Hans intro content for non-Chinese locales', async () => {
|
|
|
|
|
render(await Description({ locale: 'en-US' }))
|
|
|
|
|
it('should not render zh-Hans intro content for non-Chinese locales', () => {
|
|
|
|
|
mockDefaultLocale = 'en-US'
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
// For en-US, the order should be Discover ... in Dify Marketplace
|
|
|
|
|
// The "in" text should only appear once at the end
|
|
|
|
|
@ -303,8 +306,9 @@ describe('Description', () => {
|
|
|
|
|
expect(inIndex).toBeLessThan(marketplaceIndex)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should render zh-Hans with proper word order', async () => {
|
|
|
|
|
render(await Description({ locale: 'zh-Hans' }))
|
|
|
|
|
it('should render zh-Hans with proper word order', () => {
|
|
|
|
|
mockDefaultLocale = 'zh-Hans'
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
const subheading = screen.getByRole('heading', { level: 2 })
|
|
|
|
|
const content = subheading.textContent || ''
|
|
|
|
|
@ -323,58 +327,58 @@ describe('Description', () => {
|
|
|
|
|
// Category Styling Tests
|
|
|
|
|
// ================================
|
|
|
|
|
describe('Category Styling', () => {
|
|
|
|
|
it('should apply underline effect with after pseudo-element styling', async () => {
|
|
|
|
|
const { container } = render(await Description({}))
|
|
|
|
|
it('should apply underline effect with after pseudo-element styling', () => {
|
|
|
|
|
const { container } = render(<Description />)
|
|
|
|
|
|
|
|
|
|
const categorySpan = container.querySelector('.after\\:absolute')
|
|
|
|
|
expect(categorySpan).toBeInTheDocument()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should apply correct after pseudo-element classes', async () => {
|
|
|
|
|
const { container } = render(await Description({}))
|
|
|
|
|
it('should apply correct after pseudo-element classes', () => {
|
|
|
|
|
const { container } = render(<Description />)
|
|
|
|
|
|
|
|
|
|
// Check for the specific after pseudo-element classes
|
|
|
|
|
const categorySpans = container.querySelectorAll('.after\\:bottom-\\[1\\.5px\\]')
|
|
|
|
|
expect(categorySpans.length).toBe(7)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should apply full width to after element', async () => {
|
|
|
|
|
const { container } = render(await Description({}))
|
|
|
|
|
it('should apply full width to after element', () => {
|
|
|
|
|
const { container } = render(<Description />)
|
|
|
|
|
|
|
|
|
|
const categorySpans = container.querySelectorAll('.after\\:w-full')
|
|
|
|
|
expect(categorySpans.length).toBe(7)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should apply correct height to after element', async () => {
|
|
|
|
|
const { container } = render(await Description({}))
|
|
|
|
|
it('should apply correct height to after element', () => {
|
|
|
|
|
const { container } = render(<Description />)
|
|
|
|
|
|
|
|
|
|
const categorySpans = container.querySelectorAll('.after\\:h-2')
|
|
|
|
|
expect(categorySpans.length).toBe(7)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should apply bg-text-text-selected to after element', async () => {
|
|
|
|
|
const { container } = render(await Description({}))
|
|
|
|
|
it('should apply bg-text-text-selected to after element', () => {
|
|
|
|
|
const { container } = render(<Description />)
|
|
|
|
|
|
|
|
|
|
const categorySpans = container.querySelectorAll('.after\\:bg-text-text-selected')
|
|
|
|
|
expect(categorySpans.length).toBe(7)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should have z-index 1 on category spans', async () => {
|
|
|
|
|
const { container } = render(await Description({}))
|
|
|
|
|
it('should have z-index 1 on category spans', () => {
|
|
|
|
|
const { container } = render(<Description />)
|
|
|
|
|
|
|
|
|
|
const categorySpans = container.querySelectorAll('.z-\\[1\\]')
|
|
|
|
|
expect(categorySpans.length).toBe(7)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should apply left margin to category spans', async () => {
|
|
|
|
|
const { container } = render(await Description({}))
|
|
|
|
|
it('should apply left margin to category spans', () => {
|
|
|
|
|
const { container } = render(<Description />)
|
|
|
|
|
|
|
|
|
|
const categorySpans = container.querySelectorAll('.ml-1')
|
|
|
|
|
expect(categorySpans.length).toBeGreaterThanOrEqual(7)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should apply both left and right margin to specific spans', async () => {
|
|
|
|
|
const { container } = render(await Description({}))
|
|
|
|
|
it('should apply both left and right margin to specific spans', () => {
|
|
|
|
|
const { container } = render(<Description />)
|
|
|
|
|
|
|
|
|
|
// Extensions and Bundles spans have both ml-1 and mr-1
|
|
|
|
|
const extensionsBundlesSpans = container.querySelectorAll('.ml-1.mr-1')
|
|
|
|
|
@ -386,28 +390,17 @@ describe('Description', () => {
|
|
|
|
|
// Edge Cases Tests
|
|
|
|
|
// ================================
|
|
|
|
|
describe('Edge Cases', () => {
|
|
|
|
|
it('should handle empty props object', async () => {
|
|
|
|
|
const { container } = render(await Description({}))
|
|
|
|
|
|
|
|
|
|
expect(container.firstChild).toBeInTheDocument()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should render fragment as root element', async () => {
|
|
|
|
|
const { container } = render(await Description({}))
|
|
|
|
|
it('should render fragment as root element', () => {
|
|
|
|
|
const { container } = render(<Description />)
|
|
|
|
|
|
|
|
|
|
// Fragment renders h1 and h2 as direct children
|
|
|
|
|
expect(container.querySelector('h1')).toBeInTheDocument()
|
|
|
|
|
expect(container.querySelector('h2')).toBeInTheDocument()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should handle locale prop with undefined value', async () => {
|
|
|
|
|
render(await Description({ locale: undefined }))
|
|
|
|
|
|
|
|
|
|
expect(screen.getByRole('heading', { level: 1 })).toBeInTheDocument()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should handle zh-Hant as non-Chinese simplified', async () => {
|
|
|
|
|
render(await Description({ locale: 'zh-Hant' }))
|
|
|
|
|
it('should handle zh-Hant as non-Chinese simplified', () => {
|
|
|
|
|
mockDefaultLocale = 'zh-Hant'
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
// zh-Hant is different from zh-Hans, should use non-Chinese format
|
|
|
|
|
const subheading = screen.getByRole('heading', { level: 2 })
|
|
|
|
|
@ -426,8 +419,8 @@ describe('Description', () => {
|
|
|
|
|
// Content Structure Tests
|
|
|
|
|
// ================================
|
|
|
|
|
describe('Content Structure', () => {
|
|
|
|
|
it('should have comma separators between categories', async () => {
|
|
|
|
|
render(await Description({}))
|
|
|
|
|
it('should have comma separators between categories', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
const subheading = screen.getByRole('heading', { level: 2 })
|
|
|
|
|
const content = subheading.textContent || ''
|
|
|
|
|
@ -436,8 +429,8 @@ describe('Description', () => {
|
|
|
|
|
expect(content).toMatch(/Models[^\n\r,\u2028\u2029]*,.*Tools[^\n\r,\u2028\u2029]*,.*Data Sources[^\n\r,\u2028\u2029]*,.*Triggers[^\n\r,\u2028\u2029]*,.*Agent Strategies[^\n\r,\u2028\u2029]*,.*Extensions/)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should have "and" before last category (Bundles)', async () => {
|
|
|
|
|
render(await Description({}))
|
|
|
|
|
it('should have "and" before last category (Bundles)', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
const subheading = screen.getByRole('heading', { level: 2 })
|
|
|
|
|
const content = subheading.textContent || ''
|
|
|
|
|
@ -449,8 +442,9 @@ describe('Description', () => {
|
|
|
|
|
expect(andIndex).toBeLessThan(bundlesIndex)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should render all text elements in correct order for en-US', async () => {
|
|
|
|
|
render(await Description({ locale: 'en-US' }))
|
|
|
|
|
it('should render all text elements in correct order for en-US', () => {
|
|
|
|
|
mockDefaultLocale = 'en-US'
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
const subheading = screen.getByRole('heading', { level: 2 })
|
|
|
|
|
const content = subheading.textContent || ''
|
|
|
|
|
@ -477,8 +471,9 @@ describe('Description', () => {
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should render all text elements in correct order for zh-Hans', async () => {
|
|
|
|
|
render(await Description({ locale: 'zh-Hans' }))
|
|
|
|
|
it('should render all text elements in correct order for zh-Hans', () => {
|
|
|
|
|
mockDefaultLocale = 'zh-Hans'
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
const subheading = screen.getByRole('heading', { level: 2 })
|
|
|
|
|
const content = subheading.textContent || ''
|
|
|
|
|
@ -499,82 +494,48 @@ describe('Description', () => {
|
|
|
|
|
// Layout Tests
|
|
|
|
|
// ================================
|
|
|
|
|
describe('Layout', () => {
|
|
|
|
|
it('should have shrink-0 on h1 heading', async () => {
|
|
|
|
|
render(await Description({}))
|
|
|
|
|
it('should have shrink-0 on h1 heading', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
const heading = screen.getByRole('heading', { level: 1 })
|
|
|
|
|
expect(heading).toHaveClass('shrink-0')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should have shrink-0 on h2 subheading', async () => {
|
|
|
|
|
render(await Description({}))
|
|
|
|
|
it('should have shrink-0 on h2 subheading', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
const subheading = screen.getByRole('heading', { level: 2 })
|
|
|
|
|
expect(subheading).toHaveClass('shrink-0')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should have flex layout on h2', async () => {
|
|
|
|
|
render(await Description({}))
|
|
|
|
|
it('should have flex layout on h2', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
const subheading = screen.getByRole('heading', { level: 2 })
|
|
|
|
|
expect(subheading).toHaveClass('flex')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should have items-center on h2', async () => {
|
|
|
|
|
render(await Description({}))
|
|
|
|
|
it('should have items-center on h2', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
const subheading = screen.getByRole('heading', { level: 2 })
|
|
|
|
|
expect(subheading).toHaveClass('items-center')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should have justify-center on h2', async () => {
|
|
|
|
|
render(await Description({}))
|
|
|
|
|
it('should have justify-center on h2', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
const subheading = screen.getByRole('heading', { level: 2 })
|
|
|
|
|
expect(subheading).toHaveClass('justify-center')
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// ================================
|
|
|
|
|
// Translation Function Tests
|
|
|
|
|
// ================================
|
|
|
|
|
describe('Translation Functions', () => {
|
|
|
|
|
it('should call getTranslation for plugin namespace', async () => {
|
|
|
|
|
const { getTranslation } = await import('@/i18n-config/server')
|
|
|
|
|
render(await Description({ locale: 'en-US' }))
|
|
|
|
|
|
|
|
|
|
expect(getTranslation).toHaveBeenCalledWith('en-US', 'plugin')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should call getTranslation for common namespace', async () => {
|
|
|
|
|
const { getTranslation } = await import('@/i18n-config/server')
|
|
|
|
|
render(await Description({ locale: 'en-US' }))
|
|
|
|
|
|
|
|
|
|
expect(getTranslation).toHaveBeenCalledWith('en-US', 'common')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should call getLocaleOnServer when locale prop is undefined', async () => {
|
|
|
|
|
const { getLocaleOnServer } = await import('@/i18n-config/server')
|
|
|
|
|
render(await Description({}))
|
|
|
|
|
|
|
|
|
|
expect(getLocaleOnServer).toHaveBeenCalled()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should use locale prop when provided', async () => {
|
|
|
|
|
const { getTranslation } = await import('@/i18n-config/server')
|
|
|
|
|
render(await Description({ locale: 'ja-JP' }))
|
|
|
|
|
|
|
|
|
|
expect(getTranslation).toHaveBeenCalledWith('ja-JP', 'plugin')
|
|
|
|
|
expect(getTranslation).toHaveBeenCalledWith('ja-JP', 'common')
|
|
|
|
|
})
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// ================================
|
|
|
|
|
// Accessibility Tests
|
|
|
|
|
// ================================
|
|
|
|
|
describe('Accessibility', () => {
|
|
|
|
|
it('should have proper heading hierarchy', async () => {
|
|
|
|
|
render(await Description({}))
|
|
|
|
|
it('should have proper heading hierarchy', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
const h1 = screen.getByRole('heading', { level: 1 })
|
|
|
|
|
const h2 = screen.getByRole('heading', { level: 2 })
|
|
|
|
|
@ -583,22 +544,22 @@ describe('Description', () => {
|
|
|
|
|
expect(h2).toBeInTheDocument()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should have readable text content', async () => {
|
|
|
|
|
render(await Description({}))
|
|
|
|
|
it('should have readable text content', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
const h1 = screen.getByRole('heading', { level: 1 })
|
|
|
|
|
expect(h1.textContent).not.toBe('')
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should have visible h1 heading', async () => {
|
|
|
|
|
render(await Description({}))
|
|
|
|
|
it('should have visible h1 heading', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
const heading = screen.getByRole('heading', { level: 1 })
|
|
|
|
|
expect(heading).toBeVisible()
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should have visible h2 heading', async () => {
|
|
|
|
|
render(await Description({}))
|
|
|
|
|
it('should have visible h2 heading', () => {
|
|
|
|
|
render(<Description />)
|
|
|
|
|
|
|
|
|
|
const subheading = screen.getByRole('heading', { level: 2 })
|
|
|
|
|
expect(subheading).toBeVisible()
|
|
|
|
|
@ -615,8 +576,8 @@ describe('Description Integration', () => {
|
|
|
|
|
mockDefaultLocale = 'en-US'
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should render complete component structure', async () => {
|
|
|
|
|
const { container } = render(await Description({ locale: 'en-US' }))
|
|
|
|
|
it('should render complete component structure', () => {
|
|
|
|
|
const { container } = render(<Description />)
|
|
|
|
|
|
|
|
|
|
// Main headings
|
|
|
|
|
expect(container.querySelector('h1')).toBeInTheDocument()
|
|
|
|
|
@ -627,8 +588,9 @@ describe('Description Integration', () => {
|
|
|
|
|
expect(categorySpans.length).toBe(7)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should render complete zh-Hans structure', async () => {
|
|
|
|
|
const { container } = render(await Description({ locale: 'zh-Hans' }))
|
|
|
|
|
it('should render complete zh-Hans structure', () => {
|
|
|
|
|
mockDefaultLocale = 'zh-Hans'
|
|
|
|
|
const { container } = render(<Description />)
|
|
|
|
|
|
|
|
|
|
// Main headings
|
|
|
|
|
expect(container.querySelector('h1')).toBeInTheDocument()
|
|
|
|
|
@ -639,14 +601,16 @@ describe('Description Integration', () => {
|
|
|
|
|
expect(categorySpans.length).toBe(7)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should correctly switch between zh-Hans and en-US layouts', async () => {
|
|
|
|
|
it('should correctly differentiate between zh-Hans and en-US layouts', () => {
|
|
|
|
|
// Render en-US
|
|
|
|
|
const { container: enContainer, unmount: unmountEn } = render(await Description({ locale: 'en-US' }))
|
|
|
|
|
mockDefaultLocale = 'en-US'
|
|
|
|
|
const { container: enContainer, unmount: unmountEn } = render(<Description />)
|
|
|
|
|
const enContent = enContainer.querySelector('h2')?.textContent || ''
|
|
|
|
|
unmountEn()
|
|
|
|
|
|
|
|
|
|
// Render zh-Hans
|
|
|
|
|
const { container: zhContainer } = render(await Description({ locale: 'zh-Hans' }))
|
|
|
|
|
mockDefaultLocale = 'zh-Hans'
|
|
|
|
|
const { container: zhContainer } = render(<Description />)
|
|
|
|
|
const zhContent = zhContainer.querySelector('h2')?.textContent || ''
|
|
|
|
|
|
|
|
|
|
// Both should have all categories
|
|
|
|
|
@ -666,14 +630,16 @@ describe('Description Integration', () => {
|
|
|
|
|
expect(zhMarketplaceIndex).toBeLessThan(zhDiscoverIndex)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
it('should maintain consistent styling across locales', async () => {
|
|
|
|
|
it('should maintain consistent styling across locales', () => {
|
|
|
|
|
// Render en-US
|
|
|
|
|
const { container: enContainer, unmount: unmountEn } = render(await Description({ locale: 'en-US' }))
|
|
|
|
|
mockDefaultLocale = 'en-US'
|
|
|
|
|
const { container: enContainer, unmount: unmountEn } = render(<Description />)
|
|
|
|
|
const enCategoryCount = enContainer.querySelectorAll('.body-md-medium').length
|
|
|
|
|
unmountEn()
|
|
|
|
|
|
|
|
|
|
// Render zh-Hans
|
|
|
|
|
const { container: zhContainer } = render(await Description({ locale: 'zh-Hans' }))
|
|
|
|
|
mockDefaultLocale = 'zh-Hans'
|
|
|
|
|
const { container: zhContainer } = render(<Description />)
|
|
|
|
|
const zhCategoryCount = zhContainer.querySelectorAll('.body-md-medium').length
|
|
|
|
|
|
|
|
|
|
// Both should have same number of styled category spans
|
|
|
|
|
|