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:
parent
56937563c3
commit
6ab749be5c
19 changed files with 399 additions and 549 deletions
5
.changeset/hungry-ravens-cheat.md
Normal file
5
.changeset/hungry-ravens-cheat.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Add component hydration in Markdown E2E tests
|
|
@ -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>
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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" />
|
|
@ -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>
|
||||
}
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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" />
|
|
@ -0,0 +1,5 @@
|
|||
export default function SolidComponent({ id }) {
|
||||
return (
|
||||
<div id={id}>Framework client:only component</div>
|
||||
);
|
||||
}
|
|
@ -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>
|
||||
|
|
|
@ -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" />
|
|
@ -1,7 +1,6 @@
|
|||
<script lang="ts">
|
||||
export let id: string;
|
||||
|
||||
let count = 0;
|
||||
export let count: number = 0;
|
||||
|
||||
function add() {
|
||||
count += 1;
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
<script lang="ts">
|
||||
export let id: string;
|
||||
</script>
|
||||
|
||||
<div {id}>Framework client:only component</div>
|
|
@ -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>
|
||||
|
|
|
@ -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" />
|
|
@ -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',
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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',
|
||||
});
|
||||
});
|
||||
|
|
160
packages/astro/e2e/shared-component-tests.js
Normal file
160
packages/astro/e2e/shared-component-tests.js
Normal 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,
|
||||
};
|
||||
}
|
|
@ -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',
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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',
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue