diff --git a/exercises/04.dom/01.solution.ref/tilt.test.ts b/exercises/04.dom/01.solution.ref/tilt.test.ts new file mode 100644 index 000000000..d03536576 --- /dev/null +++ b/exercises/04.dom/01.solution.ref/tilt.test.ts @@ -0,0 +1,10 @@ +import { expect, testStep, dtl } from '@epic-web/workshop-utils/test' + +import './index.tsx' + +await testStep('VanillaTilt is initialized', async () => { + await dtl.waitFor(() => { + const tiltElement = document.querySelector('.tilt-root') + expect(tiltElement).toHaveProperty('vanillaTilt') + }) +}) diff --git a/exercises/04.dom/01.solution.ref/toggle.test.ts b/exercises/04.dom/01.solution.ref/toggle.test.ts new file mode 100644 index 000000000..54485bcf0 --- /dev/null +++ b/exercises/04.dom/01.solution.ref/toggle.test.ts @@ -0,0 +1,56 @@ +import { expect, testStep, dtl } from '@epic-web/workshop-utils/test' +const { screen, fireEvent } = dtl + +import './index.tsx' + +const toggleButton = await testStep( + 'The user can see the toggle visibility button', + async () => { + const result = await screen.findByRole('button', { + name: /toggle visibility/i, + }) + expect(result).toBeInTheDocument() + return result + }, +) + +await testStep('The Tilt component is initially visible', async () => { + return dtl.waitFor(() => { + const result = document.querySelector('.tilt-root') + expect(result).toBeInTheDocument() + return result + }) +}) + +const countButton = await testStep( + 'The count button is visible inside the Tilt component', + async () => { + const result = await screen.findByRole('button', { name: /0/i }) + expect(result).toBeInTheDocument() + return result + }, +) + +await testStep('The user can increment the count', async () => { + fireEvent.click(countButton) + const updatedButton = await screen.findByRole('button', { name: /1/i }) + expect(updatedButton).toBeInTheDocument() +}) + +await testStep( + 'The user can toggle the Tilt component visibility', + async () => { + fireEvent.click(toggleButton) + await dtl.waitFor(() => { + expect(document.querySelector('.tilt-root')).not.toBeInTheDocument() + }) + + fireEvent.click(toggleButton) + const visibleTiltElement = await dtl.waitFor(() => { + const result = document.querySelector('.tilt-root') + expect(result).toBeInTheDocument() + return result + }) + expect(visibleTiltElement).toBeInTheDocument() + }, +) diff --git a/exercises/04.dom/02.problem.deps/index.tsx b/exercises/04.dom/02.problem.deps/index.tsx index 2ad0d6562..db7f5574f 100644 --- a/exercises/04.dom/02.problem.deps/index.tsx +++ b/exercises/04.dom/02.problem.deps/index.tsx @@ -70,10 +70,10 @@ function App() { onChange={event => { const formData = new FormData(event.currentTarget) setOptions({ - max: formData.get('max') as any, - speed: formData.get('speed') as any, + max: Number(formData.get('max')), + speed: Number(formData.get('speed')), glare: formData.get('glare') === 'on', - maxGlare: formData.get('maxGlare') as any, + maxGlare: Number(formData.get('maxGlare')), }) }} > diff --git a/exercises/04.dom/02.solution.deps/index.tsx b/exercises/04.dom/02.solution.deps/index.tsx index 6eb802522..70a5b07e9 100644 --- a/exercises/04.dom/02.solution.deps/index.tsx +++ b/exercises/04.dom/02.solution.deps/index.tsx @@ -61,10 +61,10 @@ function App() { onChange={event => { const formData = new FormData(event.currentTarget) setOptions({ - max: formData.get('max') as any, - speed: formData.get('speed') as any, + max: Number(formData.get('max')), + speed: Number(formData.get('speed')), glare: formData.get('glare') === 'on', - maxGlare: formData.get('maxGlare') as any, + maxGlare: Number(formData.get('maxGlare')), }) }} > diff --git a/exercises/04.dom/02.solution.deps/tilt.test.ts b/exercises/04.dom/02.solution.deps/tilt.test.ts new file mode 100644 index 000000000..2091e73c0 --- /dev/null +++ b/exercises/04.dom/02.solution.deps/tilt.test.ts @@ -0,0 +1,50 @@ +import { expect, testStep, dtl } from '@epic-web/workshop-utils/test' +import type VanillaTilt from 'vanilla-tilt' +const { screen, fireEvent, waitFor } = dtl + +interface HTMLVanillaTiltElement extends HTMLDivElement { + vanillaTilt?: VanillaTilt +} + +import './index.tsx' + +const tiltElement = await testStep('Initialize tilt element', async () => { + const result = await waitFor(() => { + const element = document.querySelector('.tilt-root') + expect(element).toBeInTheDocument() + return element + }) + await waitFor(() => { + expect(result).toHaveProperty('vanillaTilt') + }) + return result as HTMLVanillaTiltElement +}) + +await testStep('Find count button', async () => { + const button = await screen.findByRole('button', { name: /0/i }) + expect(button).toBeInTheDocument() + return button as HTMLButtonElement +}) + +const maxInput = await testStep('Find max input', async () => { + const input = (await screen.findByLabelText('Max:')) as HTMLInputElement + expect(input).toBeInTheDocument() + return input as HTMLInputElement +}) + +await testStep('Tilt effect resets when options change', async () => { + const initialVanillaTilt = tiltElement.vanillaTilt + fireEvent.change(maxInput, { target: { value: '30' } }) + await waitFor(() => { + expect(tiltElement.vanillaTilt).not.toBe(initialVanillaTilt) + }) +}) + +await testStep('Tilt effect uses updated options', async () => { + const newMax = 35 + fireEvent.change(maxInput, { target: { value: newMax.toString() } }) + await waitFor(() => { + // @ts-expect-error this is not exposed + expect(tiltElement.vanillaTilt?.settings.max).toBe(newMax) + }) +}) diff --git a/exercises/04.dom/02.solution.deps/toggle.test.ts b/exercises/04.dom/02.solution.deps/toggle.test.ts new file mode 100644 index 000000000..54485bcf0 --- /dev/null +++ b/exercises/04.dom/02.solution.deps/toggle.test.ts @@ -0,0 +1,56 @@ +import { expect, testStep, dtl } from '@epic-web/workshop-utils/test' +const { screen, fireEvent } = dtl + +import './index.tsx' + +const toggleButton = await testStep( + 'The user can see the toggle visibility button', + async () => { + const result = await screen.findByRole('button', { + name: /toggle visibility/i, + }) + expect(result).toBeInTheDocument() + return result + }, +) + +await testStep('The Tilt component is initially visible', async () => { + return dtl.waitFor(() => { + const result = document.querySelector('.tilt-root') + expect(result).toBeInTheDocument() + return result + }) +}) + +const countButton = await testStep( + 'The count button is visible inside the Tilt component', + async () => { + const result = await screen.findByRole('button', { name: /0/i }) + expect(result).toBeInTheDocument() + return result + }, +) + +await testStep('The user can increment the count', async () => { + fireEvent.click(countButton) + const updatedButton = await screen.findByRole('button', { name: /1/i }) + expect(updatedButton).toBeInTheDocument() +}) + +await testStep( + 'The user can toggle the Tilt component visibility', + async () => { + fireEvent.click(toggleButton) + await dtl.waitFor(() => { + expect(document.querySelector('.tilt-root')).not.toBeInTheDocument() + }) + + fireEvent.click(toggleButton) + const visibleTiltElement = await dtl.waitFor(() => { + const result = document.querySelector('.tilt-root') + expect(result).toBeInTheDocument() + return result + }) + expect(visibleTiltElement).toBeInTheDocument() + }, +) diff --git a/exercises/04.dom/03.problem.primitives/index.tsx b/exercises/04.dom/03.problem.primitives/index.tsx index 4d4cc5393..133400369 100644 --- a/exercises/04.dom/03.problem.primitives/index.tsx +++ b/exercises/04.dom/03.problem.primitives/index.tsx @@ -63,10 +63,10 @@ function App() { onChange={event => { const formData = new FormData(event.currentTarget) setOptions({ - max: formData.get('max') as any, - speed: formData.get('speed') as any, + max: Number(formData.get('max')), + speed: Number(formData.get('speed')), glare: formData.get('glare') === 'on', - maxGlare: formData.get('maxGlare') as any, + maxGlare: Number(formData.get('maxGlare')), }) }} > diff --git a/exercises/04.dom/03.solution.primitives/index.tsx b/exercises/04.dom/03.solution.primitives/index.tsx index 3749844df..1ecb23d9f 100644 --- a/exercises/04.dom/03.solution.primitives/index.tsx +++ b/exercises/04.dom/03.solution.primitives/index.tsx @@ -60,10 +60,10 @@ function App() { onChange={event => { const formData = new FormData(event.currentTarget) setOptions({ - max: formData.get('max') as any, - speed: formData.get('speed') as any, + max: Number(formData.get('max')), + speed: Number(formData.get('speed')), glare: formData.get('glare') === 'on', - maxGlare: formData.get('maxGlare') as any, + maxGlare: Number(formData.get('maxGlare')), }) }} > diff --git a/exercises/04.dom/03.solution.primitives/tilt.test.ts b/exercises/04.dom/03.solution.primitives/tilt.test.ts new file mode 100644 index 000000000..ea0023a9f --- /dev/null +++ b/exercises/04.dom/03.solution.primitives/tilt.test.ts @@ -0,0 +1,59 @@ +import { expect, testStep, dtl } from '@epic-web/workshop-utils/test' +import type VanillaTilt from 'vanilla-tilt' +const { screen, fireEvent, waitFor } = dtl + +interface HTMLVanillaTiltElement extends HTMLDivElement { + vanillaTilt?: VanillaTilt +} + +import './index.tsx' + +const tiltElement = await testStep('Initialize tilt element', async () => { + const result = await waitFor(() => { + const element = document.querySelector('.tilt-root') + expect(element).toBeInTheDocument() + return element + }) + await waitFor(() => { + expect(result).toHaveProperty('vanillaTilt') + }) + return result as HTMLVanillaTiltElement +}) + +const countButton = await testStep('Find count button', async () => { + const button = await screen.findByRole('button', { name: /0/i }) + expect(button).toBeInTheDocument() + return button as HTMLButtonElement +}) + +const maxInput = await testStep('Find max input', async () => { + const input = (await screen.findByLabelText('Max:')) as HTMLInputElement + expect(input).toBeInTheDocument() + return input as HTMLInputElement +}) + +await testStep('Tilt effect persists after count increment', async () => { + const initialVanillaTilt = tiltElement.vanillaTilt + fireEvent.click(countButton) + await screen.findByRole('button', { name: /1/i }) + expect(tiltElement.vanillaTilt, 'vanilla tilt was reinitialized').toBe( + initialVanillaTilt, + ) +}) + +await testStep('Tilt effect resets when options change', async () => { + const initialVanillaTilt = tiltElement.vanillaTilt + fireEvent.change(maxInput, { target: { value: '30' } }) + await waitFor(() => { + expect(tiltElement.vanillaTilt).not.toBe(initialVanillaTilt) + }) +}) + +await testStep('Tilt effect uses updated options', async () => { + const newMax = 35 + fireEvent.change(maxInput, { target: { value: newMax.toString() } }) + await waitFor(() => { + // @ts-expect-error this is not exposed + expect(tiltElement.vanillaTilt?.settings.max).toBe(newMax) + }) +}) diff --git a/exercises/04.dom/03.solution.primitives/toggle.test.ts b/exercises/04.dom/03.solution.primitives/toggle.test.ts new file mode 100644 index 000000000..54485bcf0 --- /dev/null +++ b/exercises/04.dom/03.solution.primitives/toggle.test.ts @@ -0,0 +1,56 @@ +import { expect, testStep, dtl } from '@epic-web/workshop-utils/test' +const { screen, fireEvent } = dtl + +import './index.tsx' + +const toggleButton = await testStep( + 'The user can see the toggle visibility button', + async () => { + const result = await screen.findByRole('button', { + name: /toggle visibility/i, + }) + expect(result).toBeInTheDocument() + return result + }, +) + +await testStep('The Tilt component is initially visible', async () => { + return dtl.waitFor(() => { + const result = document.querySelector('.tilt-root') + expect(result).toBeInTheDocument() + return result + }) +}) + +const countButton = await testStep( + 'The count button is visible inside the Tilt component', + async () => { + const result = await screen.findByRole('button', { name: /0/i }) + expect(result).toBeInTheDocument() + return result + }, +) + +await testStep('The user can increment the count', async () => { + fireEvent.click(countButton) + const updatedButton = await screen.findByRole('button', { name: /1/i }) + expect(updatedButton).toBeInTheDocument() +}) + +await testStep( + 'The user can toggle the Tilt component visibility', + async () => { + fireEvent.click(toggleButton) + await dtl.waitFor(() => { + expect(document.querySelector('.tilt-root')).not.toBeInTheDocument() + }) + + fireEvent.click(toggleButton) + const visibleTiltElement = await dtl.waitFor(() => { + const result = document.querySelector('.tilt-root') + expect(result).toBeInTheDocument() + return result + }) + expect(visibleTiltElement).toBeInTheDocument() + }, +) diff --git a/exercises/05.unique-ids/01.problem.use-id/index.tsx b/exercises/05.unique-ids/01.problem.use-id/index.tsx index e4c194ab9..fdbe25450 100644 --- a/exercises/05.unique-ids/01.problem.use-id/index.tsx +++ b/exercises/05.unique-ids/01.problem.use-id/index.tsx @@ -74,10 +74,10 @@ function App() { onChange={event => { const formData = new FormData(event.currentTarget) setOptions({ - max: formData.get('max') as any, - speed: formData.get('speed') as any, + max: Number(formData.get('max')), + speed: Number(formData.get('speed')), glare: formData.get('glare') === 'on', - maxGlare: formData.get('maxGlare') as any, + maxGlare: Number(formData.get('maxGlare')), }) }} > diff --git a/exercises/05.unique-ids/01.solution.use-id/index.tsx b/exercises/05.unique-ids/01.solution.use-id/index.tsx index deb9b2120..900f0de02 100644 --- a/exercises/05.unique-ids/01.solution.use-id/index.tsx +++ b/exercises/05.unique-ids/01.solution.use-id/index.tsx @@ -72,10 +72,10 @@ function App() { onChange={event => { const formData = new FormData(event.currentTarget) setOptions({ - max: formData.get('max') as any, - speed: formData.get('speed') as any, + max: Number(formData.get('max')), + speed: Number(formData.get('speed')), glare: formData.get('glare') === 'on', - maxGlare: formData.get('maxGlare') as any, + maxGlare: Number(formData.get('maxGlare')), }) }} > diff --git a/exercises/05.unique-ids/01.solution.use-id/tilt.test.ts b/exercises/05.unique-ids/01.solution.use-id/tilt.test.ts new file mode 100644 index 000000000..a6148e36a --- /dev/null +++ b/exercises/05.unique-ids/01.solution.use-id/tilt.test.ts @@ -0,0 +1,59 @@ +import { expect, testStep, dtl } from '@epic-web/workshop-utils/test' +import type VanillaTilt from 'vanilla-tilt' +const { screen, fireEvent, waitFor } = dtl + +interface HTMLVanillaTiltElement extends HTMLDivElement { + vanillaTilt?: VanillaTilt +} + +import './index.tsx' + +const tiltElement = await testStep('Initialize tilt element', async () => { + const result = await waitFor(() => { + const element = document.querySelector('.tilt-root') + expect(element).toBeInTheDocument() + return element + }) + await waitFor(() => { + expect(result).toHaveProperty('vanillaTilt') + }) + return result as HTMLVanillaTiltElement +}) + +const countButton = await testStep('Find count button', async () => { + const button = await screen.findByRole('button', { name: /0/i }) + expect(button).toBeInTheDocument() + return button as HTMLButtonElement +}) + +const maxInput = await testStep('Find max input', async () => { + const input = (await screen.findByLabelText('Max')) as HTMLInputElement + expect(input).toBeInTheDocument() + return input as HTMLInputElement +}) + +await testStep('Tilt effect persists after count increment', async () => { + const initialVanillaTilt = tiltElement.vanillaTilt + fireEvent.click(countButton) + await screen.findByRole('button', { name: /1/i }) + expect(tiltElement.vanillaTilt, 'vanilla tilt was reinitialized').toBe( + initialVanillaTilt, + ) +}) + +await testStep('Tilt effect resets when options change', async () => { + const initialVanillaTilt = tiltElement.vanillaTilt + fireEvent.change(maxInput, { target: { value: '30' } }) + await waitFor(() => { + expect(tiltElement.vanillaTilt).not.toBe(initialVanillaTilt) + }) +}) + +await testStep('Tilt effect uses updated options', async () => { + const newMax = 35 + fireEvent.change(maxInput, { target: { value: newMax.toString() } }) + await waitFor(() => { + // @ts-expect-error this is not exposed + expect(tiltElement.vanillaTilt?.settings.max).toBe(newMax) + }) +})