From 6afa1e1b4ec59af48bc4889c75f2b9808e60732e Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Tue, 20 Aug 2024 18:23:34 -0600 Subject: [PATCH] add some tests --- epicshop/.diffignore | 3 +- .../01.solution.props/calculator.test.ts | 32 ++++++++++ .../02.solution.narrow/calculator.test.ts | 32 ++++++++++ .../03.solution.derive/calculator.test.ts | 32 ++++++++++ .../calculator.test.ts | 32 ++++++++++ .../calculator.test.ts | 32 ++++++++++ .../06.solution.satisfies/calculator.test.ts | 32 ++++++++++ .../01.solution.style/boxes.test.ts | 34 +++++++++++ .../02.styling/02.problem.component/index.tsx | 1 + .../02.solution.component/box.test.tsx | 52 +++++++++++++++++ .../02.solution.component/boxes.test.ts | 34 +++++++++++ .../02.solution.component/index.tsx | 2 +- .../02.styling/03.problem.size-prop/index.tsx | 2 +- .../03.solution.size-prop/box.test.tsx | 58 +++++++++++++++++++ .../03.solution.size-prop/boxes.test.ts | 34 +++++++++++ .../03.solution.size-prop/index.tsx | 2 +- .../03.forms/01.solution.form/form.test.ts | 17 ++++++ package-lock.json | 55 ++++++++++++++++++ package.json | 1 + 19 files changed, 483 insertions(+), 4 deletions(-) create mode 100644 exercises/01.typescript/01.solution.props/calculator.test.ts create mode 100644 exercises/01.typescript/02.solution.narrow/calculator.test.ts create mode 100644 exercises/01.typescript/03.solution.derive/calculator.test.ts create mode 100644 exercises/01.typescript/04.solution.default-props/calculator.test.ts create mode 100644 exercises/01.typescript/05.solution.function-types/calculator.test.ts create mode 100644 exercises/01.typescript/06.solution.satisfies/calculator.test.ts create mode 100644 exercises/02.styling/01.solution.style/boxes.test.ts create mode 100644 exercises/02.styling/02.solution.component/box.test.tsx create mode 100644 exercises/02.styling/02.solution.component/boxes.test.ts create mode 100644 exercises/02.styling/03.solution.size-prop/box.test.tsx create mode 100644 exercises/02.styling/03.solution.size-prop/boxes.test.ts create mode 100644 exercises/03.forms/01.solution.form/form.test.ts diff --git a/epicshop/.diffignore b/epicshop/.diffignore index bfe3b8d32..18e3427cb 100644 --- a/epicshop/.diffignore +++ b/epicshop/.diffignore @@ -1 +1,2 @@ -tsconfig.json \ No newline at end of file +tsconfig.json +*.test.* diff --git a/exercises/01.typescript/01.solution.props/calculator.test.ts b/exercises/01.typescript/01.solution.props/calculator.test.ts new file mode 100644 index 000000000..8ff4d2e25 --- /dev/null +++ b/exercises/01.typescript/01.solution.props/calculator.test.ts @@ -0,0 +1,32 @@ +import { expect, testStep, dtl } from '@epic-web/workshop-utils/test' +const { screen } = dtl + +import './index.tsx' + +await testStep('Calculator h1 is rendered', () => + screen.findByText('Calculator'), +) + +const calculators = await testStep('Code elements are rendered', async () => { + const elements = await screen.findAllByRole('code') + expect(elements).toHaveLength(4) + return elements +}) + +const [add, subtract, multiply, divide] = calculators + +await testStep('Addition calculation is rendered correctly', async () => { + expect(add).toHaveTextContent('1 + 2 = 3') +}) + +await testStep('Subtraction calculation is rendered correctly', async () => { + expect(subtract).toHaveTextContent('1 - 2 = -1') +}) + +await testStep('Multiplication calculation is rendered correctly', async () => { + expect(multiply).toHaveTextContent('1 * 2 = 2') +}) + +await testStep('Division calculation is rendered correctly', async () => { + expect(divide).toHaveTextContent('1 / 2 = 0.5') +}) diff --git a/exercises/01.typescript/02.solution.narrow/calculator.test.ts b/exercises/01.typescript/02.solution.narrow/calculator.test.ts new file mode 100644 index 000000000..8ff4d2e25 --- /dev/null +++ b/exercises/01.typescript/02.solution.narrow/calculator.test.ts @@ -0,0 +1,32 @@ +import { expect, testStep, dtl } from '@epic-web/workshop-utils/test' +const { screen } = dtl + +import './index.tsx' + +await testStep('Calculator h1 is rendered', () => + screen.findByText('Calculator'), +) + +const calculators = await testStep('Code elements are rendered', async () => { + const elements = await screen.findAllByRole('code') + expect(elements).toHaveLength(4) + return elements +}) + +const [add, subtract, multiply, divide] = calculators + +await testStep('Addition calculation is rendered correctly', async () => { + expect(add).toHaveTextContent('1 + 2 = 3') +}) + +await testStep('Subtraction calculation is rendered correctly', async () => { + expect(subtract).toHaveTextContent('1 - 2 = -1') +}) + +await testStep('Multiplication calculation is rendered correctly', async () => { + expect(multiply).toHaveTextContent('1 * 2 = 2') +}) + +await testStep('Division calculation is rendered correctly', async () => { + expect(divide).toHaveTextContent('1 / 2 = 0.5') +}) diff --git a/exercises/01.typescript/03.solution.derive/calculator.test.ts b/exercises/01.typescript/03.solution.derive/calculator.test.ts new file mode 100644 index 000000000..8ff4d2e25 --- /dev/null +++ b/exercises/01.typescript/03.solution.derive/calculator.test.ts @@ -0,0 +1,32 @@ +import { expect, testStep, dtl } from '@epic-web/workshop-utils/test' +const { screen } = dtl + +import './index.tsx' + +await testStep('Calculator h1 is rendered', () => + screen.findByText('Calculator'), +) + +const calculators = await testStep('Code elements are rendered', async () => { + const elements = await screen.findAllByRole('code') + expect(elements).toHaveLength(4) + return elements +}) + +const [add, subtract, multiply, divide] = calculators + +await testStep('Addition calculation is rendered correctly', async () => { + expect(add).toHaveTextContent('1 + 2 = 3') +}) + +await testStep('Subtraction calculation is rendered correctly', async () => { + expect(subtract).toHaveTextContent('1 - 2 = -1') +}) + +await testStep('Multiplication calculation is rendered correctly', async () => { + expect(multiply).toHaveTextContent('1 * 2 = 2') +}) + +await testStep('Division calculation is rendered correctly', async () => { + expect(divide).toHaveTextContent('1 / 2 = 0.5') +}) diff --git a/exercises/01.typescript/04.solution.default-props/calculator.test.ts b/exercises/01.typescript/04.solution.default-props/calculator.test.ts new file mode 100644 index 000000000..22ad99297 --- /dev/null +++ b/exercises/01.typescript/04.solution.default-props/calculator.test.ts @@ -0,0 +1,32 @@ +import { expect, testStep, dtl } from '@epic-web/workshop-utils/test' +const { screen } = dtl + +import './index.tsx' + +await testStep('Calculator h1 is rendered', () => + screen.findByText('Calculator'), +) + +const calculators = await testStep('Code elements are rendered', async () => { + const elements = await screen.findAllByRole('code') + expect(elements).toHaveLength(4) + return elements +}) + +const [add, subtract, multiply, divide] = calculators + +await testStep('Addition calculation is rendered correctly', async () => { + expect(add).toHaveTextContent('1 + 2 = 3') +}) + +await testStep('Subtraction calculation is rendered correctly', async () => { + expect(subtract).toHaveTextContent('0 - 0 = 0') +}) + +await testStep('Multiplication calculation is rendered correctly', async () => { + expect(multiply).toHaveTextContent('1 * 0 = 0') +}) + +await testStep('Division calculation is rendered correctly', async () => { + expect(divide).toHaveTextContent('0 / 2 = 0') +}) diff --git a/exercises/01.typescript/05.solution.function-types/calculator.test.ts b/exercises/01.typescript/05.solution.function-types/calculator.test.ts new file mode 100644 index 000000000..22ad99297 --- /dev/null +++ b/exercises/01.typescript/05.solution.function-types/calculator.test.ts @@ -0,0 +1,32 @@ +import { expect, testStep, dtl } from '@epic-web/workshop-utils/test' +const { screen } = dtl + +import './index.tsx' + +await testStep('Calculator h1 is rendered', () => + screen.findByText('Calculator'), +) + +const calculators = await testStep('Code elements are rendered', async () => { + const elements = await screen.findAllByRole('code') + expect(elements).toHaveLength(4) + return elements +}) + +const [add, subtract, multiply, divide] = calculators + +await testStep('Addition calculation is rendered correctly', async () => { + expect(add).toHaveTextContent('1 + 2 = 3') +}) + +await testStep('Subtraction calculation is rendered correctly', async () => { + expect(subtract).toHaveTextContent('0 - 0 = 0') +}) + +await testStep('Multiplication calculation is rendered correctly', async () => { + expect(multiply).toHaveTextContent('1 * 0 = 0') +}) + +await testStep('Division calculation is rendered correctly', async () => { + expect(divide).toHaveTextContent('0 / 2 = 0') +}) diff --git a/exercises/01.typescript/06.solution.satisfies/calculator.test.ts b/exercises/01.typescript/06.solution.satisfies/calculator.test.ts new file mode 100644 index 000000000..22ad99297 --- /dev/null +++ b/exercises/01.typescript/06.solution.satisfies/calculator.test.ts @@ -0,0 +1,32 @@ +import { expect, testStep, dtl } from '@epic-web/workshop-utils/test' +const { screen } = dtl + +import './index.tsx' + +await testStep('Calculator h1 is rendered', () => + screen.findByText('Calculator'), +) + +const calculators = await testStep('Code elements are rendered', async () => { + const elements = await screen.findAllByRole('code') + expect(elements).toHaveLength(4) + return elements +}) + +const [add, subtract, multiply, divide] = calculators + +await testStep('Addition calculation is rendered correctly', async () => { + expect(add).toHaveTextContent('1 + 2 = 3') +}) + +await testStep('Subtraction calculation is rendered correctly', async () => { + expect(subtract).toHaveTextContent('0 - 0 = 0') +}) + +await testStep('Multiplication calculation is rendered correctly', async () => { + expect(multiply).toHaveTextContent('1 * 0 = 0') +}) + +await testStep('Division calculation is rendered correctly', async () => { + expect(divide).toHaveTextContent('0 / 2 = 0') +}) diff --git a/exercises/02.styling/01.solution.style/boxes.test.ts b/exercises/02.styling/01.solution.style/boxes.test.ts new file mode 100644 index 000000000..265b54d40 --- /dev/null +++ b/exercises/02.styling/01.solution.style/boxes.test.ts @@ -0,0 +1,34 @@ +import { expect, testStep, dtl } from '@epic-web/workshop-utils/test' +const { screen } = dtl + +import './index.tsx' + +await testStep('Small lightblue box is rendered correctly', async () => { + const smallBox = await screen.findByText('small lightblue box') + expect(smallBox).toHaveClass('box box--small') + expect(smallBox.style.backgroundColor).toBe('lightblue') + expect(smallBox.style.fontStyle).toBe('italic') +}) + +await testStep('Medium pink box is rendered correctly', async () => { + const mediumBox = await screen.findByText('medium pink box') + expect(mediumBox).toHaveClass('box box--medium') + expect(mediumBox.style.backgroundColor).toBe('pink') + expect(mediumBox.style.fontStyle).toBe('italic') +}) + +await testStep('Large orange box is rendered correctly', async () => { + const largeBox = await screen.findByText('large orange box') + expect(largeBox).toHaveClass('box box--large') + expect(largeBox.style.backgroundColor).toBe('orange') + expect(largeBox.style.fontStyle).toBe('italic') +}) + +await testStep('Sizeless colorless box is rendered correctly', async () => { + const sizelessColorlessBox = await screen.findByText('sizeless colorless box') + expect(sizelessColorlessBox).toHaveClass('box') + expect(sizelessColorlessBox).not.toHaveClass('box--small') + expect(sizelessColorlessBox).not.toHaveClass('box--medium') + expect(sizelessColorlessBox).not.toHaveClass('box--large') + expect(sizelessColorlessBox.style.fontStyle).toBe('italic') +}) diff --git a/exercises/02.styling/02.problem.component/index.tsx b/exercises/02.styling/02.problem.component/index.tsx index 33693a9e1..306f37ee8 100644 --- a/exercises/02.styling/02.problem.component/index.tsx +++ b/exercises/02.styling/02.problem.component/index.tsx @@ -4,6 +4,7 @@ import { createRoot } from 'react-dom/client' // 🐨 Make it render a div with the style, className, and children applied. // 🐨 Also automatically add the fontStyle: 'italic' style to the style prop so consumers don't have to provide that // 🐨 And automatically add the "box" className to the className prop so consumers don't have to provide that as well. +// 🚨 make sure to export the Box component so it can be imported in the test file. // 💯 as a bonus, have this accept any number of additional props (typed as React.ComponentProps<'div'>) // and apply those to the rendered div as well. diff --git a/exercises/02.styling/02.solution.component/box.test.tsx b/exercises/02.styling/02.solution.component/box.test.tsx new file mode 100644 index 000000000..76ac9d8bc --- /dev/null +++ b/exercises/02.styling/02.solution.component/box.test.tsx @@ -0,0 +1,52 @@ +import { expect, testStep, dtl } from '@epic-web/workshop-utils/test' +import { createRoot } from 'react-dom/client' +const { screen } = dtl + +import { Box } from './index.tsx' + +await testStep('Box component renders correctly', async () => { + document.body.innerHTML = '' + const root = document.createElement('div') + document.body.appendChild(root) + createRoot(root).render( + + Test Box + , + ) + + const boxElement = await screen.findByText('Test Box') + + expect(boxElement).toHaveClass('box box--small') + expect(boxElement.style.backgroundColor).toBe('lightblue') + expect(boxElement.style.fontStyle).toBe('italic') + expect(boxElement).toHaveTextContent('Test Box') +}) + +await testStep('Box component applies default props correctly', async () => { + document.body.innerHTML = '' + const root = document.createElement('div') + document.body.appendChild(root) + createRoot(root).render(Default Box) + + const boxElement = await screen.findByText('Default Box') + + expect(boxElement).toHaveClass('box') + expect(boxElement.style.fontStyle).toBe('italic') + expect(boxElement).toHaveTextContent('Default Box') +}) + +await testStep('Box component passes through additional props', async () => { + document.body.innerHTML = '' + const root = document.createElement('div') + document.body.appendChild(root) + createRoot(root).render( + + Custom Props Box + , + ) + + const boxElement = await screen.findByText('Custom Props Box') + + expect(boxElement).toHaveAttribute('data-testid', 'custom-box') + expect(boxElement).toHaveAttribute('aria-label', 'Custom Box') +}) diff --git a/exercises/02.styling/02.solution.component/boxes.test.ts b/exercises/02.styling/02.solution.component/boxes.test.ts new file mode 100644 index 000000000..265b54d40 --- /dev/null +++ b/exercises/02.styling/02.solution.component/boxes.test.ts @@ -0,0 +1,34 @@ +import { expect, testStep, dtl } from '@epic-web/workshop-utils/test' +const { screen } = dtl + +import './index.tsx' + +await testStep('Small lightblue box is rendered correctly', async () => { + const smallBox = await screen.findByText('small lightblue box') + expect(smallBox).toHaveClass('box box--small') + expect(smallBox.style.backgroundColor).toBe('lightblue') + expect(smallBox.style.fontStyle).toBe('italic') +}) + +await testStep('Medium pink box is rendered correctly', async () => { + const mediumBox = await screen.findByText('medium pink box') + expect(mediumBox).toHaveClass('box box--medium') + expect(mediumBox.style.backgroundColor).toBe('pink') + expect(mediumBox.style.fontStyle).toBe('italic') +}) + +await testStep('Large orange box is rendered correctly', async () => { + const largeBox = await screen.findByText('large orange box') + expect(largeBox).toHaveClass('box box--large') + expect(largeBox.style.backgroundColor).toBe('orange') + expect(largeBox.style.fontStyle).toBe('italic') +}) + +await testStep('Sizeless colorless box is rendered correctly', async () => { + const sizelessColorlessBox = await screen.findByText('sizeless colorless box') + expect(sizelessColorlessBox).toHaveClass('box') + expect(sizelessColorlessBox).not.toHaveClass('box--small') + expect(sizelessColorlessBox).not.toHaveClass('box--medium') + expect(sizelessColorlessBox).not.toHaveClass('box--large') + expect(sizelessColorlessBox.style.fontStyle).toBe('italic') +}) diff --git a/exercises/02.styling/02.solution.component/index.tsx b/exercises/02.styling/02.solution.component/index.tsx index 9dcef2283..6e4377fe6 100644 --- a/exercises/02.styling/02.solution.component/index.tsx +++ b/exercises/02.styling/02.solution.component/index.tsx @@ -1,6 +1,6 @@ import { createRoot } from 'react-dom/client' -function Box({ +export function Box({ style = {}, className = '', ...otherProps diff --git a/exercises/02.styling/03.problem.size-prop/index.tsx b/exercises/02.styling/03.problem.size-prop/index.tsx index e6d1c8922..f1bfc6251 100644 --- a/exercises/02.styling/03.problem.size-prop/index.tsx +++ b/exercises/02.styling/03.problem.size-prop/index.tsx @@ -1,6 +1,6 @@ import { createRoot } from 'react-dom/client' -function Box({ +export function Box({ // 💯 you can keep the style and className props here, but you can make this // still work if you remove them. Give that a shot if you want. style = {}, diff --git a/exercises/02.styling/03.solution.size-prop/box.test.tsx b/exercises/02.styling/03.solution.size-prop/box.test.tsx new file mode 100644 index 000000000..ec203c8c4 --- /dev/null +++ b/exercises/02.styling/03.solution.size-prop/box.test.tsx @@ -0,0 +1,58 @@ +import { expect, testStep, dtl } from '@epic-web/workshop-utils/test' +import { createRoot } from 'react-dom/client' +const { screen } = dtl + +import { Box } from './index.tsx' +await testStep('Box component renders correctly with size prop', async () => { + document.body.innerHTML = '' + const root = document.createElement('div') + document.body.appendChild(root) + createRoot(root).render( + + Small Box + , + ) + + const boxElement = await screen.findByText('Small Box') + + expect(boxElement).toHaveClass('box box--small') + expect(boxElement.style.backgroundColor).toBe('lightblue') + expect(boxElement.style.fontStyle).toBe('italic') + expect(boxElement).toHaveTextContent('Small Box') +}) + +await testStep('Box component applies default size correctly', async () => { + document.body.innerHTML = '' + const root = document.createElement('div') + document.body.appendChild(root) + createRoot(root).render(Default Size Box) + + const boxElement = await screen.findByText('Default Size Box') + + expect(boxElement).toHaveClass('box') + expect(boxElement).not.toHaveClass('box--small') + expect(boxElement).not.toHaveClass('box--medium') + expect(boxElement).not.toHaveClass('box--large') + expect(boxElement.style.fontStyle).toBe('italic') +}) + +await testStep('Box component handles all size options', async () => { + document.body.innerHTML = '' + const root = document.createElement('div') + document.body.appendChild(root) + createRoot(root).render( + <> + Small Box + Medium Box + Large Box + , + ) + + const smallBox = await screen.findByText('Small Box') + const mediumBox = await screen.findByText('Medium Box') + const largeBox = await screen.findByText('Large Box') + + expect(smallBox).toHaveClass('box box--small') + expect(mediumBox).toHaveClass('box box--medium') + expect(largeBox).toHaveClass('box box--large') +}) diff --git a/exercises/02.styling/03.solution.size-prop/boxes.test.ts b/exercises/02.styling/03.solution.size-prop/boxes.test.ts new file mode 100644 index 000000000..265b54d40 --- /dev/null +++ b/exercises/02.styling/03.solution.size-prop/boxes.test.ts @@ -0,0 +1,34 @@ +import { expect, testStep, dtl } from '@epic-web/workshop-utils/test' +const { screen } = dtl + +import './index.tsx' + +await testStep('Small lightblue box is rendered correctly', async () => { + const smallBox = await screen.findByText('small lightblue box') + expect(smallBox).toHaveClass('box box--small') + expect(smallBox.style.backgroundColor).toBe('lightblue') + expect(smallBox.style.fontStyle).toBe('italic') +}) + +await testStep('Medium pink box is rendered correctly', async () => { + const mediumBox = await screen.findByText('medium pink box') + expect(mediumBox).toHaveClass('box box--medium') + expect(mediumBox.style.backgroundColor).toBe('pink') + expect(mediumBox.style.fontStyle).toBe('italic') +}) + +await testStep('Large orange box is rendered correctly', async () => { + const largeBox = await screen.findByText('large orange box') + expect(largeBox).toHaveClass('box box--large') + expect(largeBox.style.backgroundColor).toBe('orange') + expect(largeBox.style.fontStyle).toBe('italic') +}) + +await testStep('Sizeless colorless box is rendered correctly', async () => { + const sizelessColorlessBox = await screen.findByText('sizeless colorless box') + expect(sizelessColorlessBox).toHaveClass('box') + expect(sizelessColorlessBox).not.toHaveClass('box--small') + expect(sizelessColorlessBox).not.toHaveClass('box--medium') + expect(sizelessColorlessBox).not.toHaveClass('box--large') + expect(sizelessColorlessBox.style.fontStyle).toBe('italic') +}) diff --git a/exercises/02.styling/03.solution.size-prop/index.tsx b/exercises/02.styling/03.solution.size-prop/index.tsx index bed5b00d5..d41550b88 100644 --- a/exercises/02.styling/03.solution.size-prop/index.tsx +++ b/exercises/02.styling/03.solution.size-prop/index.tsx @@ -1,6 +1,6 @@ import { createRoot } from 'react-dom/client' -function Box({ +export function Box({ size, ...otherProps }: { diff --git a/exercises/03.forms/01.solution.form/form.test.ts b/exercises/03.forms/01.solution.form/form.test.ts new file mode 100644 index 000000000..14dae0e55 --- /dev/null +++ b/exercises/03.forms/01.solution.form/form.test.ts @@ -0,0 +1,17 @@ +import { expect, testStep, dtl } from '@epic-web/workshop-utils/test' +const { screen } = dtl + +import './index.tsx' + +await testStep('Form is rendered', () => + dtl.waitFor(() => document.querySelector('form')), +) + +await testStep('Username input is rendered', async () => { + const usernameInput = await screen.findByLabelText(/username/i) + expect(usernameInput).toHaveAttribute('name', 'username') +}) + +await testStep('Submit button is rendered', () => + screen.findByRole('button', { name: /submit/i }), +) diff --git a/package-lock.json b/package-lock.json index 5c794b29f..2702e4d6f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ }, "devDependencies": { "@epic-web/config": "^1.5.3", + "@epic-web/workshop-utils": "file:///Users/kentcdodds/code/epicweb-dev/epicshop/packages/workshop-utils", "@types/react": "npm:types-react@19.0.0-alpha.5", "@types/react-dom": "npm:types-react-dom@19.0.0-alpha.5", "eslint": "^9.1.1", @@ -28,6 +29,56 @@ "npm": ">=8.16.0" } }, + "../epicshop/packages/workshop-utils": { + "name": "@epic-web/workshop-utils", + "version": "0.0.0-semantically-released", + "dev": true, + "dependencies": { + "@epic-web/cachified": "^5.2.0", + "@epic-web/remember": "^1.0.2", + "@kentcdodds/md-temp": "^9.0.1", + "@mdx-js/mdx": "^3.0.1", + "@playwright/test": "^1.44.1", + "@remix-run/node": "^2.9.2", + "@testing-library/dom": "^10.1.0", + "@testing-library/jest-dom": "^6.4.8", + "@total-typescript/ts-reset": "^0.5.1", + "@types/chai": "^4.3.17", + "@types/chai-dom": "^1.11.3", + "@vitest/expect": "^2.0.5", + "chai": "^5.1.1", + "chai-dom": "^1.12.0", + "chalk": "^5.3.0", + "chokidar": "^3.6.0", + "close-with-grace": "^1.3.0", + "cross-spawn": "^7.0.3", + "execa": "^9.1.0", + "fkill": "^9.0.0", + "fs-extra": "^11.2.0", + "glob": "^10.3.16", + "globby": "^14.0.1", + "lru-cache": "^10.2.2", + "md5-hex": "^5.0.0", + "mdast-util-mdx-jsx": "^3.1.2", + "mdx-bundler": "^10.0.2", + "p-queue": "^8.0.1", + "rehype": "^13.0.1", + "remark": "^15.0.1", + "remark-autolink-headings": "^7.0.1", + "remark-emoji": "^4.0.1", + "remark-gfm": "^4.0.0", + "unified": "^11.0.4", + "unist-util-remove-position": "^5.0.0", + "unist-util-visit": "^5.0.0", + "zod": "^3.23.8" + }, + "devDependencies": { + "@types/hast": "^3.0.4", + "@types/mdast": "^4.0.4", + "@types/node": "^20.12.12", + "tshy": "^1.14.0" + } + }, "node_modules/@babel/runtime": { "version": "7.24.6", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.6.tgz", @@ -57,6 +108,10 @@ "tslib": "^2.6.2" } }, + "node_modules/@epic-web/workshop-utils": { + "resolved": "../epicshop/packages/workshop-utils", + "link": true + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", diff --git a/package.json b/package.json index 4d7313c1f..36ec4c0c9 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ }, "devDependencies": { "@epic-web/config": "^1.5.3", + "@epic-web/workshop-utils": "file:///Users/kentcdodds/code/epicweb-dev/epicshop/packages/workshop-utils", "@types/react": "npm:types-react@19.0.0-alpha.5", "@types/react-dom": "npm:types-react-dom@19.0.0-alpha.5", "eslint": "^9.1.1",