Skip to content

Commit

Permalink
test: ✅ update components for svelte 5
Browse files Browse the repository at this point in the history
add test files
  • Loading branch information
spences10 committed Jun 29, 2024
1 parent 1bf5dd7 commit e2b2d1a
Show file tree
Hide file tree
Showing 7 changed files with 231 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/lib/components/chat.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
? 'chat-bubble-accent'
: 'chat-bubble-primary'}"
>
{@render children()}
{@render children?.()}
</section>
</div>
</div>
10 changes: 7 additions & 3 deletions src/lib/components/date-distance.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
<script lang="ts">
import { formatDistance } from 'date-fns'
export let date
interface Props {
date: number | string | Date
}
let { date }: Props = $props()
const distance = formatDistance(
new Date(Date.now()),
new Date(date)
new Date(date),
)
</script>

<span data-testid="date-distance">{distance}</span>
<span data-testid="date-distance">{distance}</span>
6 changes: 5 additions & 1 deletion src/lib/components/date-distance.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ test('renders formatted date distance', async () => {

vi.mocked(formatDistance).mockReturnValue(mockFormattedDistance)

render(DateDistance, { date: mockDate })
render(
DateDistance,
{ date: mockDate },
{ baseElement: document.body },
)

const element = screen.getByTestId('date-distance')
expect(element.textContent).toBe(mockFormattedDistance)
Expand Down
96 changes: 96 additions & 0 deletions src/lib/components/date-updated.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import {
cleanup,
render,
screen,
} from '@testing-library/svelte/svelte5'
import { format } from 'date-fns'
import { afterEach, expect, test, vi } from 'vitest'
import DateUpdated from './date-updated.svelte'

vi.mock('date-fns', () => ({
format: vi.fn(),
}))

// Clean up after each test
afterEach(() => {
cleanup()
vi.resetAllMocks()
})

test('renders formatted date with default size', async () => {
const mockDate = '2023-06-15'
const mockFormattedDate = 'June 15th 2023'

vi.mocked(format).mockReturnValue(mockFormattedDate)

await vi.waitFor(async () => {
render(DateUpdated, { date: mockDate })
})

const element = screen.getByText(mockFormattedDate)
expect(element).toBeDefined()
expect(element.classList.contains('text-base')).toBe(true)

expect(format).toHaveBeenCalledWith(
new Date(mockDate),
'MMMM do yyyy',
)
})

test('renders formatted date with small size', async () => {
const mockDate = '2023-06-15'
const mockFormattedDate = 'June 15th 2023'

vi.mocked(format).mockReturnValue(mockFormattedDate)

await vi.waitFor(async () => {
render(DateUpdated, { date: mockDate, small: 'true' })
})

const element = screen.getByText(mockFormattedDate)
expect(element).toBeDefined()
expect(element.classList.contains('text-xs')).toBe(true)

expect(format).toHaveBeenCalledWith(
new Date(mockDate),
'MMMM do yyyy',
)
})

test('renders current date when date prop is null', async () => {
const mockCurrentDate = new Date('2023-06-15')
vi.setSystemTime(mockCurrentDate)

const mockFormattedDate = 'June 15th 2023'
vi.mocked(format).mockReturnValue(mockFormattedDate)

await vi.waitFor(async () => {
render(DateUpdated, { date: null })
})

const element = screen.getByText(mockFormattedDate)
expect(element).toBeDefined()

expect(format).toHaveBeenCalledWith(mockCurrentDate, 'MMMM do yyyy')

vi.useRealTimers()
})

test('renders current date when date prop is undefined', async () => {
const mockCurrentDate = new Date('2023-06-15')
vi.setSystemTime(mockCurrentDate)

const mockFormattedDate = 'June 15th 2023'
vi.mocked(format).mockReturnValue(mockFormattedDate)

await vi.waitFor(async () => {
render(DateUpdated, { date: undefined })
})

const element = screen.getByText(mockFormattedDate)
expect(element).toBeDefined()

expect(format).toHaveBeenCalledWith(mockCurrentDate, 'MMMM do yyyy')

vi.useRealTimers()
})
24 changes: 18 additions & 6 deletions src/lib/components/details.svelte
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
<script lang="ts">
import type { Snippet } from 'svelte'
import { slide } from 'svelte/transition'
export let buttonText = ''
export let isOpen = false
export let styles = ''
interface Props {
buttonText?: string
isOpen?: boolean
styles?: string
children?: Snippet
}
let {
buttonText = '',
isOpen = $bindable(false),
styles = '',
children,
}: Props = $props()
</script>

<div>
<button
class="btn {styles} shadow-xl"
on:click={() => (isOpen = !isOpen)}
onclick={() => (isOpen = !isOpen)}
data-testid="details-button"
>
{isOpen ? `Close` : buttonText}
</button>
{#if isOpen}
<div transition:slide|global>
<slot />
<div transition:slide|global data-testid="details-content">
{@render children?.()}
</div>
{/if}
</div>
87 changes: 87 additions & 0 deletions src/lib/components/details.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import {
fireEvent,
render,
screen,
} from '@testing-library/svelte/svelte5'
import { describe, expect, test } from 'vitest'
import Details from './details.svelte'

describe('Details', () => {
test('renders with default props', async () => {
render(Details)
const button = screen.getByTestId('details-button')
expect(button.textContent?.trim()).toBe('')
expect(screen.queryByTestId('details-content')).toBeNull()
})

test('renders with custom button text', async () => {
render(Details, { props: { buttonText: 'Show Details' } })
const button = screen.getByTestId('details-button')
expect(button.textContent?.trim()).toBe('Show Details')
})

test.skip('opens and closes details', async () => {
const { container } = render(Details, {
props: {
buttonText: 'Show Details',
// children: () => 'Test Content',
},
})

console.log('=====================')
console.log(container.innerHTML)
console.log('=====================')

const button = screen.getByTestId('details-button')
expect(screen.queryByTestId('details-content')).toBeNull()

// Open details
await fireEvent.click(button)
const content = screen.getByTestId('details-content')
expect(content).toBeDefined()
expect(content.textContent).toContain('Test Content')
expect(button.textContent?.trim()).toBe('Close')

// Close details
await fireEvent.click(button)
expect(screen.queryByTestId('details-content')).toBeNull()
expect(button.textContent?.trim()).toBe('Show Details')
})

test('applies custom styles', async () => {
render(Details, { props: { styles: 'custom-class' } })
const button = screen.getByTestId('details-button')
expect(button.classList.contains('custom-class')).toBe(true)
})

test.skip('renders children when open', async () => {
render(Details, {
props: {
buttonText: 'Show Details',
// children: () => 'Test Content',
},
})

const button = screen.getByTestId('details-button')
await fireEvent.click(button)

const content = screen.getByTestId('details-content')
expect(content.textContent).toContain('Test Content')
})

test.skip('respects initial isOpen prop', async () => {
render(Details, {
props: {
buttonText: 'Show Details',
isOpen: true,
// children: () => 'Test Content',
},
})

const content = screen.getByTestId('details-content')
expect(content.textContent).toContain('Test Content')
expect(
screen.getByTestId('details-button').textContent?.trim(),
).toBe('Close')
})
})
32 changes: 17 additions & 15 deletions src/lib/components/footer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,24 @@
type PopularPostsPeriod = keyof PopularPosts
let selected_period: PopularPostsPeriod = 'popular_posts_yearly'
let posts: PopularPost[] = []
let show_current_visitor_data = false
let posts: PopularPost[] = $state([])
let show_current_visitor_data = $state(false)
$: {
$effect(() => {
posts = $popular_posts_store[
selected_period as PopularPostsPeriod
].slice(0, 6)
}
});
let total_visitors = 0
$: if ($visitors_store && $visitors_store.visitor_data) {
total_visitors = $visitors_store.visitor_data.reduce(
(total, visitor) => total + visitor.recent_visitors,
0,
)
}
let total_visitors = $state(0)
$effect(() => {
if ($visitors_store && $visitors_store.visitor_data) {
total_visitors = $visitors_store.visitor_data.reduce(
(total, visitor) => total + visitor.recent_visitors,
0,
)
}
});
</script>

<footer class="footer bg-primary p-10 text-primary-content">
Expand Down Expand Up @@ -54,10 +56,10 @@
{/each}

{#if total_visitors > 0}
<!-- svelte-ignore a11y-no-static-element-interactions -->
<!-- svelte-ignore a11y_no_static_element_interactions -->
<span
on:mouseenter={() => (show_current_visitor_data = true)}
on:mouseleave={() => (show_current_visitor_data = false)}
onmouseenter={() => (show_current_visitor_data = true)}
onmouseleave={() => (show_current_visitor_data = false)}
class="inline-block cursor-pointer"
>
<p
Expand All @@ -80,7 +82,7 @@
{#each SITE_LINKS as link}
<a
href={`/${link.slug}`}
on:click={() => Fathom.trackEvent(link.slug)}
onclick={() => Fathom.trackEvent(link.slug)}
class="text-primary-content hover:opacity-50"
>
{link.title}
Expand Down

0 comments on commit e2b2d1a

Please sign in to comment.