diff options
Diffstat (limited to '')
19 files changed, 391 insertions, 541 deletions
diff --git a/.changeset/hungry-ravens-cheat.md b/.changeset/hungry-ravens-cheat.md new file mode 100644 index 000000000..982c0b7bf --- /dev/null +++ b/.changeset/hungry-ravens-cheat.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Add component hydration in Markdown E2E tests diff --git a/packages/astro/e2e/fixtures/preact-component/src/components/JSXComponent.jsx b/packages/astro/e2e/fixtures/preact-component/src/components/JSXComponent.jsx index 6cc7b7858..16b98f6d4 100644 --- a/packages/astro/e2e/fixtures/preact-component/src/components/JSXComponent.jsx +++ b/packages/astro/e2e/fixtures/preact-component/src/components/JSXComponent.jsx @@ -1,5 +1,5 @@ import { h } from 'preact'; export default function({ id }) { - return <div id={id}>Preact client:only component</div> + return <div id={id}>Framework client:only component</div> } diff --git a/packages/astro/e2e/fixtures/preact-component/src/pages/index.astro b/packages/astro/e2e/fixtures/preact-component/src/pages/index.astro index 946b90be0..2fe26a575 100644 --- a/packages/astro/e2e/fixtures/preact-component/src/pages/index.astro +++ b/packages/astro/e2e/fixtures/preact-component/src/pages/index.astro @@ -8,10 +8,10 @@ const someProps = { --- <html> - <head> - <!-- Head Stuff --> - </head> - <body> + <head> + <!-- Head Stuff --> + </head> + <body> <Counter id="server-only" {...someProps}> <h1>Hello, server!</h1> </Counter> @@ -24,14 +24,14 @@ const someProps = { <h1>Hello, client:load!</h1> </Counter> - <Counter id="client-visible" {...someProps} client:visible> + <Counter id="client-visible" {...someProps} client:visible> <h1>Hello, client:visible!</h1> </Counter> - <Counter id="client-media" {...someProps} client:media="(max-width: 50em)"> + <Counter id="client-media" {...someProps} client:media="(max-width: 50em)"> <h1>Hello, client:media!</h1> </Counter> <PreactComponent id="client-only" client:only="preact" /> - </body> + </body> </html> diff --git a/packages/astro/e2e/fixtures/preact-component/src/pages/markdown.md b/packages/astro/e2e/fixtures/preact-component/src/pages/markdown.md new file mode 100644 index 000000000..c05e2ae52 --- /dev/null +++ b/packages/astro/e2e/fixtures/preact-component/src/pages/markdown.md @@ -0,0 +1,31 @@ +--- +setup: | + import Counter from '../components/Counter.jsx'; + import PreactComponent from '../components/JSXComponent.jsx'; + + const someProps = { + count: 0, + }; +--- + +<Counter id="server-only" {...someProps}> + # Hello, server! +</Counter> + +<Counter id="client-idle" {...someProps} client:idle> + # Hello, client:idle! +</Counter> + +<Counter id="client-load" {...someProps} client:load> + # Hello, client:load! +</Counter> + +<Counter id="client-visible" {...someProps} client:visible> + # Hello, client:visible! +</Counter> + +<Counter id="client-media" {...someProps} client:media="(max-width: 50em)"> + # Hello, client:media! +</Counter> + +<PreactComponent id="client-only" client:only="preact" /> diff --git a/packages/astro/e2e/fixtures/react-component/src/components/JSXComponent.jsx b/packages/astro/e2e/fixtures/react-component/src/components/JSXComponent.jsx index 90a4d7c42..dcafa028c 100644 --- a/packages/astro/e2e/fixtures/react-component/src/components/JSXComponent.jsx +++ b/packages/astro/e2e/fixtures/react-component/src/components/JSXComponent.jsx @@ -1,5 +1,5 @@ import React from 'react'; export default function({ id }) { - return <div id={id}>React client:only component</div> + return <div id={id}>Framework client:only component</div> } diff --git a/packages/astro/e2e/fixtures/react-component/src/pages/index.astro b/packages/astro/e2e/fixtures/react-component/src/pages/index.astro index 388fc1d98..0a9a212d0 100644 --- a/packages/astro/e2e/fixtures/react-component/src/pages/index.astro +++ b/packages/astro/e2e/fixtures/react-component/src/pages/index.astro @@ -8,10 +8,10 @@ const someProps = { --- <html> - <head> - <!-- Head Stuff --> - </head> - <body> + <head> + <!-- Head Stuff --> + </head> + <body> <Counter id="server-only" {...someProps}> <h1>Hello, server!</h1> </Counter> @@ -24,7 +24,7 @@ const someProps = { <h1>Hello, client:load!</h1> </Counter> - <Counter id="client-visible" {...someProps} client:visible> + <Counter id="client-visible" {...someProps} client:visible> <h1>Hello, client:visible!</h1> </Counter> @@ -33,5 +33,5 @@ const someProps = { </Counter> <ReactComponent id="client-only" client:only="react" /> - </body> + </body> </html> diff --git a/packages/astro/e2e/fixtures/react-component/src/pages/markdown.md b/packages/astro/e2e/fixtures/react-component/src/pages/markdown.md new file mode 100644 index 000000000..5461fc48a --- /dev/null +++ b/packages/astro/e2e/fixtures/react-component/src/pages/markdown.md @@ -0,0 +1,31 @@ +--- +setup: | + import Counter from '../components/Counter.jsx'; + import ReactComponent from '../components/JSXComponent.jsx'; + + const someProps = { + count: 0, + }; +--- + +<Counter id="server-only" {...someProps}> + # Hello, server! +</Counter> + +<Counter id="client-idle" {...someProps} client:idle> + # Hello, client:idle! +</Counter> + +<Counter id="client-load" {...someProps} client:load> + # Hello, client:load! +</Counter> + +<Counter id="client-visible" {...someProps} client:visible> + # Hello, client:visible! +</Counter> + +<Counter id="client-media" {...someProps} client:media="(max-width: 50em)"> + # Hello, client:media! +</Counter> + +<ReactComponent id="client-only" client:only="react" /> diff --git a/packages/astro/e2e/fixtures/solid-component/src/components/SolidComponent.jsx b/packages/astro/e2e/fixtures/solid-component/src/components/SolidComponent.jsx new file mode 100644 index 000000000..248fd10d6 --- /dev/null +++ b/packages/astro/e2e/fixtures/solid-component/src/components/SolidComponent.jsx @@ -0,0 +1,5 @@ +export default function SolidComponent({ id }) { + return ( + <div id={id}>Framework client:only component</div> + ); +} diff --git a/packages/astro/e2e/fixtures/solid-component/src/pages/index.astro b/packages/astro/e2e/fixtures/solid-component/src/pages/index.astro index 91013ad0e..9cfbedc7c 100644 --- a/packages/astro/e2e/fixtures/solid-component/src/pages/index.astro +++ b/packages/astro/e2e/fixtures/solid-component/src/pages/index.astro @@ -1,5 +1,6 @@ --- import Counter from '../components/Counter.jsx'; +import SolidComponent from '../components/SolidComponent.jsx'; const someProps = { count: 0, @@ -7,10 +8,10 @@ const someProps = { --- <html> - <head> - <!-- Head Stuff --> - </head> - <body> + <head> + <!-- Head Stuff --> + </head> + <body> <Counter id="server-only" {...someProps}> <h1>Hello, server!</h1> </Counter> @@ -23,12 +24,14 @@ const someProps = { <h1>Hello, client:load!</h1> </Counter> - <Counter id="client-visible" {...someProps} client:visible> + <Counter id="client-visible" {...someProps} client:visible> <h1>Hello, client:visible!</h1> </Counter> <Counter id="client-media" {...someProps} client:media="(max-width: 50em)"> <h1>Hello, client:media!</h1> </Counter> - </body> + + <SolidComponent id="client-only" client:only="solid" /> + </body> </html> diff --git a/packages/astro/e2e/fixtures/solid-component/src/pages/markdown.md b/packages/astro/e2e/fixtures/solid-component/src/pages/markdown.md new file mode 100644 index 000000000..22d546481 --- /dev/null +++ b/packages/astro/e2e/fixtures/solid-component/src/pages/markdown.md @@ -0,0 +1,31 @@ +--- +setup: | + import Counter from '../components/Counter.jsx'; + import SolidComponent from '../components/SolidComponent.jsx'; + + const someProps = { + count: 0, + }; +--- + +<Counter id="server-only" {...someProps}> + # Hello, server! +</Counter> + +<Counter id="client-idle" {...someProps} client:idle> + # Hello, client:idle! +</Counter> + +<Counter id="client-load" {...someProps} client:load> + # Hello, client:load! +</Counter> + +<Counter id="client-visible" {...someProps} client:visible> + # Hello, client:visible! +</Counter> + +<Counter id="client-media" {...someProps} client:media="(max-width: 50em)"> + # Hello, client:media! +</Counter> + +<SolidComponent id="client-only" client:only="solid" /> diff --git a/packages/astro/e2e/fixtures/svelte-component/src/components/Counter.svelte b/packages/astro/e2e/fixtures/svelte-component/src/components/Counter.svelte index a2353f071..2f05ce798 100644 --- a/packages/astro/e2e/fixtures/svelte-component/src/components/Counter.svelte +++ b/packages/astro/e2e/fixtures/svelte-component/src/components/Counter.svelte @@ -1,7 +1,6 @@ <script lang="ts"> export let id: string; - - let count = 0; + export let count: number = 0; function add() { count += 1; diff --git a/packages/astro/e2e/fixtures/svelte-component/src/components/SvelteComponent.svelte b/packages/astro/e2e/fixtures/svelte-component/src/components/SvelteComponent.svelte new file mode 100644 index 000000000..ff6894c00 --- /dev/null +++ b/packages/astro/e2e/fixtures/svelte-component/src/components/SvelteComponent.svelte @@ -0,0 +1,5 @@ +<script lang="ts"> + export let id: string; +</script> + +<div {id}>Framework client:only component</div> diff --git a/packages/astro/e2e/fixtures/svelte-component/src/pages/index.astro b/packages/astro/e2e/fixtures/svelte-component/src/pages/index.astro index 3c8117124..9bd8f23bf 100644 --- a/packages/astro/e2e/fixtures/svelte-component/src/pages/index.astro +++ b/packages/astro/e2e/fixtures/svelte-component/src/pages/index.astro @@ -1,5 +1,6 @@ --- import Counter from '../components/Counter.svelte'; +import SvelteComponent from '../components/SvelteComponent.svelte'; const someProps = { count: 0, @@ -7,28 +8,30 @@ const someProps = { --- <html> - <head> - <!-- Head Stuff --> - </head> - <body> - <Counter id="server-only"> + <head> + <!-- Head Stuff --> + </head> + <body> + <Counter id="server-only" {...someProps}> <h1>Hello, server!</h1> </Counter> - <Counter id="client-idle" client:idle> + <Counter id="client-idle" {...someProps} client:idle> <h1>Hello, client:idle!</h1> </Counter> - <Counter id="client-load" client:load> + <Counter id="client-load" {...someProps} client:load> <h1>Hello, client:load!</h1> </Counter> - <Counter id="client-visible" client:visible> + <Counter id="client-visible" {...someProps} client:visible> <h1>Hello, client:visible!</h1> </Counter> - <Counter id="client-media" client:media="(max-width: 50rem)"> + <Counter id="client-media" {...someProps} client:media="(max-width: 50em)"> <h1>Hello, client:media!</h1> </Counter> - </body> + + <SvelteComponent id="client-only" client:only="svelte" /> + </body> </html> diff --git a/packages/astro/e2e/fixtures/svelte-component/src/pages/markdown.md b/packages/astro/e2e/fixtures/svelte-component/src/pages/markdown.md new file mode 100644 index 000000000..0030bccd1 --- /dev/null +++ b/packages/astro/e2e/fixtures/svelte-component/src/pages/markdown.md @@ -0,0 +1,31 @@ +--- +setup: | + import Counter from '../components/Counter.svelte'; + import SvelteComponent from '../components/SvelteComponent.svelte'; + + const someProps = { + count: 0, + }; +--- + +<Counter id="server-only" {...someProps}> + # Hello, server! +</Counter> + +<Counter id="client-idle" {...someProps} client:idle> + # Hello, client:idle! +</Counter> + +<Counter id="client-load" {...someProps} client:load> + # Hello, client:load! +</Counter> + +<Counter id="client-visible" {...someProps} client:visible> + # Hello, client:visible! +</Counter> + +<Counter id="client-media" {...someProps} client:media="(max-width: 50em)"> + # Hello, client:media! +</Counter> + +<SvelteComponent id="client-only" client:only="svelte" /> diff --git a/packages/astro/e2e/preact-component.test.js b/packages/astro/e2e/preact-component.test.js index c53c28f61..f7b79e9da 100644 --- a/packages/astro/e2e/preact-component.test.js +++ b/packages/astro/e2e/preact-component.test.js @@ -1,145 +1,19 @@ -import { test as base, expect } from '@playwright/test'; -import { loadFixture } from './test-utils.js'; +import { prepareTestFactory } from './shared-component-tests.js'; -const test = base.extend({ - astro: async ({}, use) => { - const fixture = await loadFixture({ root: './fixtures/preact-component/' }); - await use(fixture); - }, -}); - -let devServer; - -test.beforeEach(async ({ astro }) => { - devServer = await astro.startDevServer(); -}); - -test.afterEach(async () => { - await devServer.stop(); -}); - -test.describe('Preact components', () => { - test('server only', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - const counter = page.locator('#server-only'); - await expect(counter, 'component is visible').toBeVisible(); - - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - const inc = counter.locator('.increment'); - await inc.click(); - - await expect(count, 'count incremented by 1').toHaveText('0'); - }); - - test('client:idle', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - const counter = page.locator('#client-idle'); - await expect(counter, 'component is visible').toBeVisible(); - - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - const inc = counter.locator('.increment'); - await inc.click(); - - await expect(count, 'count incremented by 1').toHaveText('1'); - }); - - test('client:load', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - const counter = page.locator('#client-load'); - await expect(counter, 'component is visible').toBeVisible(); - - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - const inc = counter.locator('.increment'); - await inc.click(); - - await expect(count, 'count incremented by 1').toHaveText('1'); - }); - - test('client:visible', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - // Make sure the component is on screen to trigger hydration - const counter = page.locator('#client-visible'); - await counter.scrollIntoViewIfNeeded(); - await expect(counter, 'component is visible').toBeVisible(); - - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - const inc = counter.locator('.increment'); - await inc.click(); - - await expect(count, 'count incremented by 1').toHaveText('1'); - }); - - test('client:media', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - const counter = page.locator('#client-media'); - await expect(counter, 'component is visible').toBeVisible(); +const { test, createTests } = prepareTestFactory({ root: './fixtures/preact-component/' }); - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - const inc = counter.locator('.increment'); - await inc.click(); - await expect(count, 'component not hydrated yet').toHaveText('0'); - - // Reset the viewport to hydrate the component (max-width: 50rem) - await page.setViewportSize({ width: 414, height: 1124 }); - await inc.click(); - await expect(count, 'count incremented by 1').toHaveText('1'); +test.describe('Preact components in Astro files', () => { + createTests({ + pageUrl: '/', + pageSourceFilePath: './src/pages/index.astro', + componentFilePath: './src/components/JSXComponent.jsx', }); +}); - test('client:only', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - const label = page.locator('#client-only'); - await expect(label, 'component is visible').toBeVisible(); - - await expect(label, 'slot text is visible').toHaveText('Preact client:only component'); - }); - - test('HMR', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - const counter = page.locator('#client-idle'); - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - // Edit the component's initial count prop - await astro.editFile('./src/pages/index.astro', (original) => - original.replace('id="client-idle" {...someProps}', 'id="client-idle" count={5}') - ); - - await expect(count, 'count prop updated').toHaveText('5'); - await expect(counter, 'component styles persisted').toHaveCSS('display', 'grid'); - - // Edit the component's slot text - await astro.editFile('./src/components/JSXComponent.jsx', (original) => - original.replace('Preact client:only component', 'Updated preact client:only component') - ); - - const label = page.locator('#client-only'); - await expect(label, 'client:only component is visible').toBeVisible(); - await expect(label, 'client:only slot text is visible').toHaveText( - 'Updated preact client:only component' - ); - - // Edit the imported CSS file - await astro.editFile('./src/components/Counter.css', (original) => - original.replace('font-size: 2em;', 'font-size: 24px;') - ); - - await expect(count, 'imported styles updated').toHaveCSS('font-size', '24px'); +test.describe('Preact components in Markdown files', () => { + createTests({ + pageUrl: '/markdown/', + pageSourceFilePath: './src/pages/markdown.md', + componentFilePath: './src/components/JSXComponent.jsx', }); }); diff --git a/packages/astro/e2e/react-component.test.js b/packages/astro/e2e/react-component.test.js index de39d512f..05f8c1a87 100644 --- a/packages/astro/e2e/react-component.test.js +++ b/packages/astro/e2e/react-component.test.js @@ -1,145 +1,19 @@ -import { test as base, expect } from '@playwright/test'; -import { loadFixture } from './test-utils.js'; +import { prepareTestFactory } from './shared-component-tests.js'; -const test = base.extend({ - astro: async ({}, use) => { - const fixture = await loadFixture({ root: './fixtures/react-component/' }); - await use(fixture); - }, -}); - -let devServer; - -test.beforeEach(async ({ astro }) => { - devServer = await astro.startDevServer(); -}); - -test.afterEach(async () => { - await devServer.stop(); -}); - -test.describe('React components', () => { - test('server only', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - const counter = page.locator('#server-only'); - await expect(counter, 'component is visible').toBeVisible(); - - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - const inc = counter.locator('.increment'); - await inc.click(); - - await expect(count, 'component not hydrated').toHaveText('0'); - }); - - test('client:idle', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - const counter = page.locator('#client-idle'); - await expect(counter, 'component is visible').toBeVisible(); - - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - const inc = counter.locator('.increment'); - await inc.click(); - - await expect(count, 'count incremented by 1').toHaveText('1'); - }); - - test('client:load', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - const counter = page.locator('#client-load'); - await expect(counter, 'component is visible').toBeVisible(); - - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - const inc = counter.locator('.increment'); - await inc.click(); - - await expect(count, 'count incremented by 1').toHaveText('1'); - }); - - test('client:visible', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - // Make sure the component is on screen to trigger hydration - const counter = page.locator('#client-visible'); - await counter.scrollIntoViewIfNeeded(); - await expect(counter, 'component is visible').toBeVisible(); - - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - const inc = counter.locator('.increment'); - await inc.click(); - - await expect(count, 'count incremented by 1').toHaveText('1'); - }); - - test('client:media', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - const counter = page.locator('#client-media'); - await expect(counter, 'component is visible').toBeVisible(); +const { test, createTests } = prepareTestFactory({ root: './fixtures/react-component/' }); - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - const inc = counter.locator('.increment'); - await inc.click(); - await expect(count, 'component not hydrated yet').toHaveText('0'); - - // Reset the viewport to hydrate the component (max-width: 50rem) - await page.setViewportSize({ width: 414, height: 1124 }); - await inc.click(); - await expect(count, 'count incremented by 1').toHaveText('1'); +test.describe('React components in Astro files', () => { + createTests({ + pageUrl: '/', + pageSourceFilePath: './src/pages/index.astro', + componentFilePath: './src/components/JSXComponent.jsx', }); +}); - test('client:only', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - const label = page.locator('#client-only'); - await expect(label, 'component is visible').toBeVisible(); - - await expect(label, 'slot text is visible').toHaveText('React client:only component'); - }); - - test('HMR', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - const counter = page.locator('#client-idle'); - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - // Edit the component's initial count prop - await astro.editFile('./src/pages/index.astro', (original) => - original.replace('id="client-idle" {...someProps}', 'id="client-idle" count={5}') - ); - - await expect(count, 'count prop updated').toHaveText('5'); - await expect(counter, 'component styles persisted').toHaveCSS('display', 'grid'); - - // Edit the component's slot text - await astro.editFile('./src/components/JSXComponent.jsx', (original) => - original.replace('React client:only component', 'Updated react client:only component') - ); - - const label = page.locator('#client-only'); - await expect(label, 'client:only component is visible').toBeVisible(); - await expect(label, 'client:only slot text is visible').toHaveText( - 'Updated react client:only component' - ); - - // Edit the imported CSS file - await astro.editFile('./src/components/Counter.css', (original) => - original.replace('font-size: 2em;', 'font-size: 24px;') - ); - - await expect(count, 'imported CSS updated').toHaveCSS('font-size', '24px'); +test.describe('React components in Markdown files', () => { + createTests({ + pageUrl: '/markdown/', + pageSourceFilePath: './src/pages/markdown.md', + componentFilePath: './src/components/JSXComponent.jsx', }); }); diff --git a/packages/astro/e2e/shared-component-tests.js b/packages/astro/e2e/shared-component-tests.js new file mode 100644 index 000000000..a43b46168 --- /dev/null +++ b/packages/astro/e2e/shared-component-tests.js @@ -0,0 +1,160 @@ +import { test as base, expect } from '@playwright/test'; +import { loadFixture } from './test-utils.js'; + +export function prepareTestFactory({ root }) { + const test = base.extend({ + astro: async ({}, use) => { + const fixture = await loadFixture({ root }); + await use(fixture); + }, + }); + + let devServer; + + test.beforeEach(async ({ astro }) => { + devServer = await astro.startDevServer(); + }); + + test.afterEach(async () => { + await devServer.stop(); + }); + + const createTests = ({ + pageUrl, + pageSourceFilePath, + componentFilePath, + counterCssFilePath, + }) => { + test('server only', async ({ page, astro }) => { + await page.goto(astro.resolveUrl(pageUrl)); + + const counter = page.locator('#server-only'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'component not hydrated').toHaveText('0'); + }); + + test('client:idle', async ({ page, astro }) => { + await page.goto(astro.resolveUrl(pageUrl)); + + const counter = page.locator('#client-idle'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('client:load', async ({ page, astro }) => { + await page.goto(astro.resolveUrl(pageUrl)); + + const counter = page.locator('#client-load'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('client:visible', async ({ page, astro }) => { + await page.goto(astro.resolveUrl(pageUrl)); + + // Make sure the component is on screen to trigger hydration + const counter = page.locator('#client-visible'); + await counter.scrollIntoViewIfNeeded(); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('client:media', async ({ page, astro }) => { + await page.goto(astro.resolveUrl(pageUrl)); + + const counter = page.locator('#client-media'); + await expect(counter, 'component is visible').toBeVisible(); + + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + const inc = counter.locator('.increment'); + await inc.click(); + await expect(count, 'component not hydrated yet').toHaveText('0'); + + // Reset the viewport to hydrate the component (max-width: 50rem) + await page.setViewportSize({ width: 414, height: 1124 }); + await inc.click(); + await expect(count, 'count incremented by 1').toHaveText('1'); + }); + + test('client:only', async ({ page, astro }) => { + await page.goto(astro.resolveUrl(pageUrl)); + + const label = page.locator('#client-only'); + await expect(label, 'component is visible').toBeVisible(); + + await expect(label, 'slot text is visible').toHaveText('Framework client:only component'); + }); + + test('HMR', async ({ page, astro }) => { + await page.goto(astro.resolveUrl(pageUrl)); + + const counter = page.locator('#client-idle'); + const count = counter.locator('pre'); + await expect(count, 'initial count is 0').toHaveText('0'); + + // Edit the component's initial count prop + await astro.editFile(pageSourceFilePath, (original) => + original.replace('id="client-idle" {...someProps}', 'id="client-idle" count={5}') + ); + + await expect(count, 'count prop updated').toHaveText('5'); + await expect(counter, 'component styles persisted').toHaveCSS('display', 'grid'); + + // Edit the client:only component's slot text + await astro.editFile(componentFilePath, (original) => + original.replace('Framework client:only component', 'Updated framework client:only component') + ); + + const label = page.locator('#client-only'); + await expect(label, 'client:only component is visible').toBeVisible(); + await expect(label, 'client:only slot text is visible').toHaveText( + 'Updated framework client:only component' + ); + + // Edit the imported CSS file + await astro.editFile(counterCssFilePath || './src/components/Counter.css', (original) => + original.replace('font-size: 2em;', 'font-size: 24px;') + ); + + await expect(count, 'imported CSS updated').toHaveCSS('font-size', '24px'); + + // Revert our edits + astro.resetAllFiles(); + }); + } + + return { + test, + createTests, + }; +} diff --git a/packages/astro/e2e/solid-component.test.js b/packages/astro/e2e/solid-component.test.js index 149cae3df..3a200c67e 100644 --- a/packages/astro/e2e/solid-component.test.js +++ b/packages/astro/e2e/solid-component.test.js @@ -1,125 +1,19 @@ -import { test as base, expect } from '@playwright/test'; -import { loadFixture } from './test-utils.js'; +import { prepareTestFactory } from './shared-component-tests.js'; -const test = base.extend({ - astro: async ({}, use) => { - const fixture = await loadFixture({ root: './fixtures/solid-component/' }); - await use(fixture); - }, -}); - -let devServer; - -test.beforeEach(async ({ astro }) => { - devServer = await astro.startDevServer(); -}); - -test.afterEach(async () => { - await devServer.stop(); -}); - -test.describe('Solid components', () => { - test('server only', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - const counter = page.locator('#server-only'); - await expect(counter, 'component is visible').toBeVisible(); - - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - const inc = counter.locator('.increment'); - await inc.click(); - - await expect(count, 'component not hydrated').toHaveText('0'); - }); - - test('client:idle', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - const counter = page.locator('#client-idle'); - await expect(counter, 'component is visible').toBeVisible(); - - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - const inc = counter.locator('.increment'); - await inc.click(); - - await expect(count, 'count incremented by 1').toHaveText('1'); - }); - - test('client:load', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - const counter = page.locator('#client-load'); - await expect(counter, 'component is visible').toBeVisible(); +const { test, createTests } = prepareTestFactory({ root: './fixtures/solid-component/' }); - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - const inc = counter.locator('.increment'); - await inc.click(); - - await expect(count, 'count incremented by 1').toHaveText('1'); - }); - - test('client:visible', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - // Make sure the component is on screen to trigger hydration - const counter = page.locator('#client-visible'); - await counter.scrollIntoViewIfNeeded(); - await expect(counter, 'component is visible').toBeVisible(); - - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - const inc = counter.locator('.increment'); - await inc.click(); - - await expect(count, 'count incremented by 1').toHaveText('1'); - }); - - test('client:media', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - const counter = page.locator('#client-media'); - await expect(counter, 'component is visible').toBeVisible(); - - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - const inc = counter.locator('.increment'); - await inc.click(); - await expect(count, 'component not hydrated yet').toHaveText('0'); - - // Reset the viewport to hydrate the component (max-width: 50rem) - await page.setViewportSize({ width: 414, height: 1124 }); - await inc.click(); - await expect(count, 'count incremented by 1').toHaveText('1'); +test.describe('Solid components in Astro files', () => { + createTests({ + pageUrl: '/', + pageSourceFilePath: './src/pages/index.astro', + componentFilePath: './src/components/SolidComponent.jsx', }); +}); - test('HMR', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - const counter = page.locator('#client-idle'); - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - // Edit the component's initial count prop - await astro.editFile('./src/pages/index.astro', (original) => - original.replace('id="client-idle" {...someProps}', 'id="client-idle" count={5}') - ); - - await expect(counter, 'component styles persisted').toHaveCSS('display', 'grid'); - await expect(count, 'count prop updated').toHaveText('5'); - - // Edit the imported CSS - await astro.editFile('./src/components/Counter.css', (original) => - original.replace('font-size: 2em;', 'font-size: 24px;') - ); - - await expect(count, 'imported CSS updated').toHaveCSS('font-size', '24px'); +test.describe('Solid components in Markdown files', () => { + createTests({ + pageUrl: '/markdown/', + pageSourceFilePath: './src/pages/markdown.md', + componentFilePath: './src/components/SolidComponent.jsx', }); }); diff --git a/packages/astro/e2e/svelte-component.test.js b/packages/astro/e2e/svelte-component.test.js index de5dc46b2..6ee9f1100 100644 --- a/packages/astro/e2e/svelte-component.test.js +++ b/packages/astro/e2e/svelte-component.test.js @@ -1,117 +1,21 @@ -import { test as base, expect } from '@playwright/test'; -import { loadFixture } from './test-utils.js'; +import { prepareTestFactory } from './shared-component-tests.js'; -const test = base.extend({ - astro: async ({}, use) => { - const fixture = await loadFixture({ root: './fixtures/svelte-component/' }); - await use(fixture); - }, -}); - -let devServer; - -test.beforeEach(async ({ astro }) => { - devServer = await astro.startDevServer(); -}); - -test.afterEach(async () => { - await devServer.stop(); -}); - -test.describe('Svelte components', () => { - test('server only', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - const counter = page.locator('#server-only'); - await expect(counter, 'component is visible').toBeVisible(); - - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - const inc = counter.locator('.increment'); - await inc.click(); - - await expect(count, 'component not hydrated').toHaveText('0'); - }); - - test('client:idle', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - const counter = page.locator('#client-idle'); - await expect(counter, 'component is visible').toBeVisible(); - - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - const inc = counter.locator('.increment'); - await inc.click(); - - await expect(count, 'count incremented by 1').toHaveText('1'); - }); - - test('client:load', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); +const { test, createTests } = prepareTestFactory({ root: './fixtures/svelte-component/' }); - const counter = page.locator('#client-load'); - await expect(counter, 'component is visible').toBeVisible(); - - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - const inc = counter.locator('.increment'); - await inc.click(); - - await expect(count, 'count incremented by 1').toHaveText('1'); - }); - - test('client:visible', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - // Make sure the component is on screen to trigger hydration - const counter = page.locator('#client-visible'); - await counter.scrollIntoViewIfNeeded(); - await expect(counter, 'component is visible').toBeVisible(); - - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - const inc = counter.locator('.increment'); - await inc.click(); - - await expect(count, 'count incremented by 1').toHaveText('1'); +test.describe('Svelte components in Astro files', () => { + createTests({ + pageUrl: '/', + pageSourceFilePath: './src/pages/index.astro', + componentFilePath: './src/components/SvelteComponent.svelte', + counterCssFilePath: './src/components/Counter.svelte', }); +}); - test('client:media', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - const counter = page.locator('#client-media'); - await expect(counter, 'component is visible').toBeVisible(); - - const count = counter.locator('pre'); - await expect(count, 'initial count is 0').toHaveText('0'); - - const inc = counter.locator('.increment'); - await inc.click(); - await expect(count, 'component not hydrated yet').toHaveText('0'); - - // Reset the viewport to hydrate the component (max-width: 50rem) - await page.setViewportSize({ width: 414, height: 1124 }); - await inc.click(); - await expect(count, 'count incremented by 1').toHaveText('1'); - }); - - test('HMR', async ({ page, astro }) => { - await page.goto(astro.resolveUrl('/')); - - // Edit the component's slot text - await astro.editFile('./src/pages/index.astro', (original) => - original.replace('Hello, client:idle!', 'Hello, updated client:idle!') - ); - - const counter = page.locator('#client-idle'); - const label = page.locator('#client-idle-message'); - - await expect(label, 'slot text updated').toHaveText('Hello, updated client:idle!'); - await expect(counter, 'component styles persisted').toHaveCSS('display', 'grid'); +test.describe('Svelte components in Markdown files', () => { + createTests({ + pageUrl: '/markdown/', + pageSourceFilePath: './src/pages/markdown.md', + componentFilePath: './src/components/SvelteComponent.svelte', + counterCssFilePath: './src/components/Counter.svelte', }); }); |