Skip to content

Commit

Permalink
finish in-browser tests
Browse files Browse the repository at this point in the history
  • Loading branch information
kentcdodds committed Sep 22, 2024
1 parent 167833b commit 3f79ded
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 7 deletions.
2 changes: 1 addition & 1 deletion exercises/02.context/01.problem.memo-context/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ function useFooter() {
return context
}

const Footer = memo(function Footer() {
const Footer = memo(function FooterImpl() {
const { color, name } = useFooter()
return (
<footer style={{ color }}>
Expand Down
2 changes: 1 addition & 1 deletion exercises/02.context/01.solution.memo-context/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ function useFooter() {
return context
}

const Footer = memo(function Footer() {
const Footer = memo(function FooterImpl() {
const { color, name } = useFooter()
return (
<footer style={{ color }}>
Expand Down
57 changes: 57 additions & 0 deletions exercises/02.context/01.solution.memo-context/memo-context.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { getComponentCalls } from '#shared/get-component-calls'
import { testStep, expect, dtl } from '@epic-web/workshop-utils/test'

const { screen, fireEvent } = dtl

await import('./index.tsx')

await testStep(
'changing the app counter should not re-render the Footer component',
async () => {
// Find the app count button
const appCountButton = await screen.findByRole('button', {
name: /the app count is/i,
})

// Get the component calls when clicking the app count button
const componentNames = await getComponentCalls(async () => {
fireEvent.click(appCountButton)
// Give components time to render
await new Promise((resolve) => setTimeout(resolve, 10))
})

expect(componentNames).toEqual(['App', 'FooterSetters', 'Main'])
},
)

await testStep('changing footer color should re-render Footer', async () => {
// Find the color button
const colorButton = await screen.findByRole('button', { name: /blue/i })

// Get the component calls when changing the color
const componentNames = await getComponentCalls(async () => {
fireEvent.click(colorButton)
// Give components time to render
await new Promise((resolve) => setTimeout(resolve, 10))
})

expect(componentNames).toEqual(
expect.arrayContaining(['App', 'FooterSetters', 'Main', 'FooterImpl']),
)
})

await testStep('changing footer name should re-render Footer', async () => {
// Find the name input
const nameInput = await screen.findByLabelText(/name/i)

// Get the component calls when changing the name
const componentNames = await getComponentCalls(async () => {
fireEvent.change(nameInput, { target: { value: 'New Name' } })
// Give components time to render
await new Promise((resolve) => setTimeout(resolve, 10))
})

expect(componentNames).toEqual(
expect.arrayContaining(['App', 'FooterSetters', 'Main', 'FooterImpl']),
)
})
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function useFooter() {
return context
}

const Footer = memo(function Footer() {
const Footer = memo(function FooterImpl() {
const { color, name } = useFooter()
return (
<footer style={{ color }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function useFooter() {
return context
}

const Footer = memo(function Footer() {
const Footer = memo(function FooterImpl() {
const { color, name } = useFooter()
return (
<footer style={{ color }}>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { getComponentCalls } from '#shared/get-component-calls'
import { testStep, expect, dtl } from '@epic-web/workshop-utils/test'

const { screen, fireEvent } = dtl

await import('./index.tsx')

await testStep(
'changing the app counter should not re-render the Footer component',
async () => {
const appCountButton = await screen.findByRole('button', {
name: /the app count is/i,
})

const componentNames = await getComponentCalls(async () => {
fireEvent.click(appCountButton)
await new Promise((resolve) => setTimeout(resolve, 10))
})

expect(componentNames).toEqual([
'App',
'FooterProvider',
'FooterSetters',
'Main',
])
},
)

await testStep(
'changing footer color should not re-render App or Main',
async () => {
const colorButton = await screen.findByRole('button', { name: /blue/i })

const componentNames = await getComponentCalls(async () => {
fireEvent.click(colorButton)
await new Promise((resolve) => setTimeout(resolve, 10))
})

expect(componentNames).toEqual(
expect.arrayContaining(['FooterSetters', 'FooterImpl', 'FooterProvider']),
)
expect(componentNames).not.toContain('App')
expect(componentNames).not.toContain('Main')
},
)

await testStep(
'changing footer name should not re-render App or Main',
async () => {
const nameInput = await screen.findByLabelText(/name/i)

const componentNames = await getComponentCalls(async () => {
fireEvent.change(nameInput, { target: { value: 'New Name' } })
await new Promise((resolve) => setTimeout(resolve, 10))
})

expect(componentNames).toEqual(
expect.arrayContaining(['FooterSetters', 'FooterImpl', 'FooterProvider']),
)
expect(componentNames).not.toContain('App')
expect(componentNames).not.toContain('Main')
},
)
2 changes: 1 addition & 1 deletion exercises/02.context/03.problem.split-context/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function useFooter() {

// 🐨 create a useFooterDispatch function similar to the hook above

const Footer = memo(function Footer() {
const Footer = memo(function FooterImpl() {
// 🐨 update this to useFooterState
const { color, name } = useFooter()
return (
Expand Down
4 changes: 2 additions & 2 deletions exercises/02.context/03.solution.split-context/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ function useFooterDispatch() {
return context
}

const Footer = memo(function Footer() {
const Footer = memo(function FooterImpl() {
const { color, name } = useFooterState()
return (
<footer style={{ color }}>
Expand All @@ -62,7 +62,7 @@ function Main({ footer }: { footer: React.ReactNode }) {
)
}

const FooterSetters = memo(function FooterSetters() {
const FooterSetters = memo(function FooterImplSetters() {
const { setColor, setName } = useFooterDispatch()
return (
<>
Expand Down
56 changes: 56 additions & 0 deletions exercises/02.context/03.solution.split-context/split.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { getComponentCalls } from '#shared/get-component-calls'
import { testStep, expect, dtl } from '@epic-web/workshop-utils/test'

const { screen, fireEvent } = dtl

await import('./index.tsx')

await testStep(
'FooterSetters should not re-render when footer state changes',
async () => {
const colorButton = await screen.findByRole('button', { name: /blue/i })

const componentNames = await getComponentCalls(async () => {
fireEvent.click(colorButton)
await new Promise((resolve) => setTimeout(resolve, 10))
})

expect(componentNames).toContain('FooterImpl')
expect(componentNames).not.toContain('FooterSetters')
},
)

await testStep(
'FooterSetters should not re-render when footer name changes',
async () => {
const nameInput = await screen.findByLabelText(/name/i)

const componentNames = await getComponentCalls(async () => {
fireEvent.change(nameInput, { target: { value: 'New Name' } })
await new Promise((resolve) => setTimeout(resolve, 10))
})

expect(componentNames).toContain('FooterImpl')
expect(componentNames).not.toContain('FooterSetters')
},
)

await testStep(
'FooterSetters should render only once during initial render',
async () => {
const componentNames = await getComponentCalls(async () => {
// Force a re-render of the entire app
const appCountButton = await screen.findByRole('button', {
name: /the app count is/i,
})
fireEvent.click(appCountButton)
await new Promise((resolve) => setTimeout(resolve, 10))
})

const footerSettersCount = componentNames.filter(
(name) => name === 'FooterSetters',
).length

expect(footerSettersCount).toBe(0)
},
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { testStep } from '@epic-web/workshop-utils/test'

await testStep(
`There is no real test for this because it's basically impossible to test. (Consider that an invitation to try if you want!)`,
async () => {
await import('./index.tsx')
},
)

0 comments on commit 3f79ded

Please sign in to comment.