0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2024-12-30 22:03:56 -05:00

Add component hydration in .md E2E tests, refactor (#3610)

Co-authored-by: Tony Sullivan <tony.f.sullivan@outlook.com>
Co-authored-by: Nate Moore <natemoo-re@users.noreply.github.com>
This commit is contained in:
hippotastic 2022-06-18 00:34:19 +02:00 committed by GitHub
parent 56937563c3
commit 6ab749be5c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 399 additions and 549 deletions

View file

@ -0,0 +1,5 @@
---
'astro': patch
---
Add component hydration in Markdown E2E tests

View file

@ -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>
}

View file

@ -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>

View file

@ -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" />

View file

@ -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>
}

View file

@ -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>

View file

@ -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" />

View file

@ -0,0 +1,5 @@
export default function SolidComponent({ id }) {
return (
<div id={id}>Framework client:only component</div>
);
}

View file

@ -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>

View file

@ -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" />

View file

@ -1,7 +1,6 @@
<script lang="ts">
export let id: string;
let count = 0;
export let count: number = 0;
function add() {
count += 1;

View file

@ -0,0 +1,5 @@
<script lang="ts">
export let id: string;
</script>
<div {id}>Framework client:only component</div>

View file

@ -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>

View file

@ -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" />

View file

@ -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);
},
});
const { test, createTests } = prepareTestFactory({ root: './fixtures/preact-component/' });
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 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('/'));
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 Astro files', () => {
createTests({
pageUrl: '/',
pageSourceFilePath: './src/pages/index.astro',
componentFilePath: './src/components/JSXComponent.jsx',
});
});
test.describe('Preact components in Markdown files', () => {
createTests({
pageUrl: '/markdown/',
pageSourceFilePath: './src/pages/markdown.md',
componentFilePath: './src/components/JSXComponent.jsx',
});
});

View file

@ -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);
},
});
const { test, createTests } = prepareTestFactory({ root: './fixtures/react-component/' });
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 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('/'));
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 Astro files', () => {
createTests({
pageUrl: '/',
pageSourceFilePath: './src/pages/index.astro',
componentFilePath: './src/components/JSXComponent.jsx',
});
});
test.describe('React components in Markdown files', () => {
createTests({
pageUrl: '/markdown/',
pageSourceFilePath: './src/pages/markdown.md',
componentFilePath: './src/components/JSXComponent.jsx',
});
});

View file

@ -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,
};
}

View file

@ -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);
},
});
const { test, createTests } = prepareTestFactory({ root: './fixtures/solid-component/' });
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 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('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 Astro files', () => {
createTests({
pageUrl: '/',
pageSourceFilePath: './src/pages/index.astro',
componentFilePath: './src/components/SolidComponent.jsx',
});
});
test.describe('Solid components in Markdown files', () => {
createTests({
pageUrl: '/markdown/',
pageSourceFilePath: './src/pages/markdown.md',
componentFilePath: './src/components/SolidComponent.jsx',
});
});

View file

@ -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);
},
});
const { test, createTests } = prepareTestFactory({ root: './fixtures/svelte-component/' });
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 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 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 Astro files', () => {
createTests({
pageUrl: '/',
pageSourceFilePath: './src/pages/index.astro',
componentFilePath: './src/components/SvelteComponent.svelte',
counterCssFilePath: './src/components/Counter.svelte',
});
});
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',
});
});