centralizing test setup with a universal resetAllFiles hook (#3693)

This commit is contained in:
Tony Sullivan 2022-06-23 17:28:54 +00:00 committed by GitHub
parent 589b840f5a
commit c7cb5df450
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 168 additions and 315 deletions

View file

@ -1,13 +1,8 @@
import { test as base, expect } from '@playwright/test';
import { expect } from '@playwright/test';
import os from 'os';
import { loadFixture } from './test-utils.js';
import { testFactory } from './test-utils.js';
const test = base.extend({
astro: async ({}, use) => {
const fixture = await loadFixture({ root: './fixtures/astro-component/' });
await use(fixture);
},
});
const test = testFactory({ root: './fixtures/astro-component/' });
let devServer;

View file

@ -1,12 +1,7 @@
import { test as base, expect } from '@playwright/test';
import { loadFixture } from './test-utils.js';
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
const test = base.extend({
astro: async ({}, use) => {
const fixture = await loadFixture({ root: './fixtures/client-only/' });
await use(fixture);
},
});
const test = testFactory({ root: './fixtures/client-only/' });
let devServer;

View file

@ -1,44 +1,38 @@
<template>
<div :id="id" class="counter">
<h1><slot /></h1>
<button class="decrement" @click="subtract()">-</button>
<Result :value="count" />
<pre>{{count}}</pre>
<button class="increment" @click="add()">+</button>
</div>
<div :id="messageId" class="message">
<slot />
</div>
</template>
<script>
import { ref } from 'vue';
import Result from './Result.vue';
export default {
components: {
Result
},
props: {
id: {
type: String,
required: true
},
start: {
type: String,
required: true
},
stepSize: {
type: String,
default: "1"
count: {
type: Number,
default: 0
}
},
setup(props) {
const id = props.id;
const count = ref(parseInt(props.start))
const stepSize = ref(parseInt(props.stepSize))
const add = () => (count.value = count.value + stepSize.value);
const subtract = () => (count.value = count.value - stepSize.value);
const count = ref(props.count);
const messageId = `${id}-message`;
const add = () => (count.value = count.value + 1);
const subtract = () => (count.value = count.value - 1);
return {
count,
id,
messageId,
add,
subtract,
};
@ -47,11 +41,14 @@ export default {
</script>
<style>
.counter {
display: grid;
font-size: 2em;
grid-template-columns: repeat(3, minmax(0, 1fr));
margin-top: 2em;
place-items: center;
}
.counter {
display: grid;
font-size: 2em;
grid-template-columns: repeat(3, minmax(0, 1fr));
margin-top: 2em;
place-items: center;
}
.message {
text-align: center;
}
</style>

View file

@ -1,14 +1,13 @@
<template>
<pre>{{ value }}</pre>
<my-button>Click Me</my-button>
<div :id="id">Framework client:only component</div>
</template>
<script>
export default {
props: {
value: {
type: Number,
id: {
type: String,
required: true
}
}

View file

@ -1,33 +1,37 @@
---
import Counter from '../components/Counter.vue'
import Counter from '../components/Counter.vue';
import VueComponent from '../components/VueComponent.vue';
const someProps = {
count: 0,
};
---
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width"
/>
<title>Vue component</title>
<style>
:global(:root) {
font-family: system-ui;
padding: 1em;
}
</style>
</head>
<body>
<main>
<Counter id="server-only" start="0">No Client</Counter>
<Counter id="client-load" start="0" client:load>Hello, client:load!</Counter>
<!-- Test island deduplication, i.e. same UID as the component above. -->
<Counter id="client-load-dup" start="0" client:load>Hello, client:load!</Counter>
<!-- Test island deduplication account for non-render affecting props. -->
<Counter id="client-load-step" start="0" step-size="2" client:load>Hello, client:load!</Counter>
<Counter id="client-idle" start="0" client:idle>Hello, client:idle!</Counter>
<!-- Test that two client:visibles have unique uids -->
<Counter id="client-visible" start="0" client:visible>Hello, client:visible!</Counter>
<Counter id="client-media" start="0" client:media="(max-width: 50rem)">Hello, client:media!</Counter>
</main>
</body>
<html>
<head>
<!-- Head Stuff -->
</head>
<body>
<Counter id="server-only" {...someProps}>
<h1>Hello, server!</h1>
</Counter>
<Counter id="client-idle" {...someProps} client:idle>
<h1>Hello, client:idle!</h1>
</Counter>
<Counter id="client-load" {...someProps} client:load>
<h1>Hello, client:load!</h1>
</Counter>
<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>
<VueComponent id="client-only" client:only="vue" />
</body>
</html>

View file

@ -0,0 +1,31 @@
---
setup: |
import Counter from '../components/Counter.vue';
import VueComponent from '../components/VueComponent.vue';
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>
<VueComponent id="client-only" client:only="vue" />

View file

@ -1,12 +1,7 @@
import { test as base, expect } from '@playwright/test';
import { loadFixture } from './test-utils.js';
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
const test = base.extend({
astro: async ({}, use) => {
const fixture = await loadFixture({ root: './fixtures/lit-component/' });
await use(fixture);
},
});
const test = testFactory({ root: './fixtures/lit-component/' });
let devServer;

View file

@ -1,12 +1,7 @@
import { test as base, expect } from '@playwright/test';
import { loadFixture } from './test-utils.js';
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
const test = base.extend({
astro: async ({}, use) => {
const fixture = await loadFixture({ root: './fixtures/multiple-frameworks/' });
await use(fixture);
},
});
const test = testFactory({ root: './fixtures/multiple-frameworks/' });
let devServer;

View file

@ -1,12 +1,7 @@
import { test as base, expect } from '@playwright/test';
import { loadFixture } from './test-utils.js';
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
const test = base.extend({
astro: async ({}, use) => {
const fixture = await loadFixture({ root: './fixtures/nested-in-preact/' });
await use(fixture);
},
});
const test = testFactory({ root: './fixtures/nested-in-preact/' });
let devServer;

View file

@ -1,12 +1,7 @@
import { test as base, expect } from '@playwright/test';
import { loadFixture } from './test-utils.js';
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
const test = base.extend({
astro: async ({}, use) => {
const fixture = await loadFixture({ root: './fixtures/nested-in-react/' });
await use(fixture);
},
});
const test = testFactory({ root: './fixtures/nested-in-react/' });
let devServer;

View file

@ -1,12 +1,7 @@
import { test as base, expect } from '@playwright/test';
import { loadFixture } from './test-utils.js';
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
const test = base.extend({
astro: async ({}, use) => {
const fixture = await loadFixture({ root: './fixtures/nested-in-solid/' });
await use(fixture);
},
});
const test = testFactory({ root: './fixtures/nested-in-solid/' });
let devServer;

View file

@ -1,12 +1,7 @@
import { test as base, expect } from '@playwright/test';
import { loadFixture } from './test-utils.js';
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
const test = base.extend({
astro: async ({}, use) => {
const fixture = await loadFixture({ root: './fixtures/nested-in-svelte/' });
await use(fixture);
},
});
const test = testFactory({ root: './fixtures/nested-in-svelte/' });
let devServer;

View file

@ -1,12 +1,7 @@
import { test as base, expect } from '@playwright/test';
import { loadFixture } from './test-utils.js';
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
const test = base.extend({
astro: async ({}, use) => {
const fixture = await loadFixture({ root: './fixtures/nested-in-vue/' });
await use(fixture);
},
});
const test = testFactory({ root: './fixtures/nested-in-vue/' });
let devServer;

View file

@ -1,12 +1,7 @@
import { test as base, expect } from '@playwright/test';
import { loadFixture } from './test-utils.js';
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
const test = base.extend({
astro: async ({}, use) => {
const fixture = await loadFixture({ root: './fixtures/nested-styles/' });
await use(fixture);
},
});
const test = testFactory({ root: './fixtures/nested-styles/' });
let devServer;

View file

@ -1,12 +1,7 @@
import { test as base, expect } from '@playwright/test';
import { loadFixture } from './test-utils.js';
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
const test = base.extend({
astro: async ({}, use) => {
const fixture = await loadFixture({ root: './fixtures/pass-js/' });
await use(fixture);
},
});
const test = testFactory({ root: './fixtures/pass-js/' });
let devServer;

View file

@ -1,13 +1,8 @@
import { test as base, expect } from '@playwright/test';
import { loadFixture } from './test-utils.js';
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
export function prepareTestFactory({ root }) {
const test = base.extend({
astro: async ({}, use) => {
const fixture = await loadFixture({ root });
await use(fixture);
},
});
export function prepareTestFactory(opts) {
const test = testFactory(opts);
let devServer;

View file

@ -1,12 +1,7 @@
import { test as base, expect } from '@playwright/test';
import { loadFixture } from './test-utils.js';
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
const test = base.extend({
astro: async ({}, use) => {
const fixture = await loadFixture({ root: './fixtures/tailwindcss/' });
await use(fixture);
},
});
const test = testFactory({ root: './fixtures/tailwindcss/' });
let devServer;

View file

@ -1,3 +1,4 @@
import { test as testBase } from '@playwright/test';
import { loadFixture as baseLoadFixture } from '../test/test-utils.js';
export function loadFixture(inlineConfig) {
@ -11,3 +12,20 @@ export function loadFixture(inlineConfig) {
root: new URL(inlineConfig.root, import.meta.url).toString(),
});
}
export function testFactory(inlineConfig) {
let fixture;
const test = testBase.extend({
astro: async ({}, use) => {
fixture = await loadFixture(inlineConfig);
await use(fixture);
}
});
test.afterEach(() => {
fixture.resetAllFiles();
});
return test;
}

View file

@ -1,12 +1,7 @@
import { test as base, expect } from '@playwright/test';
import { loadFixture } from './test-utils.js';
import { expect } from '@playwright/test';
import { testFactory } from './test-utils.js';
const test = base.extend({
astro: async ({}, use) => {
const fixture = await loadFixture({ root: './fixtures/ts-resolution/' });
await use(fixture);
},
});
const test = testFactory({ root: './fixtures/ts-resolution/' });
function runTest(it) {
it('client:idle', async ({ page, astro }) => {

View file

@ -1,147 +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/vue-component/' });
await use(fixture);
},
});
const { test, createTests } = prepareTestFactory({ root: './fixtures/vue-component/' });
let devServer;
test.beforeEach(async ({ astro }) => {
devServer = await astro.startDevServer();
});
test.afterEach(async () => {
await devServer.stop();
});
test.describe('Vue 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('/'));
// Multiple counters on the page to verify islands aren't sharing state
const counter = page.locator('#client-load');
const counterDup = page.locator('#client-load-dup');
const counterStep = page.locator('#client-load-step');
await expect(counter).toBeVisible();
await expect(counterDup).toBeVisible();
await expect(counterStep).toBeVisible();
const count = counter.locator('pre');
const countDup = counterDup.locator('pre');
const countStep = counterStep.locator('pre');
const countInc = counter.locator('.increment');
const countDupInc = counterDup.locator('.increment');
const countStepInc = counterStep.locator('.increment');
// Should only increment the first counter
await countInc.click();
await expect(count, 'intial count is 1').toHaveText('1');
await expect(countDup, 'initial count is 0').toHaveText('0');
await expect(countStep, 'initial count is 0').toHaveText('0');
// Should only increment the second counter
await countDupInc.click();
await expect(count, "count didn't change").toHaveText('1');
await expect(countDup, 'count incremented by 1').toHaveText('1');
await expect(countStep, "count didn't change").toHaveText('0');
// Should only increment the third counter
// Expecting an increase of 4 becasuse the component's
// step is set to 2
await countStepInc.click();
await countStepInc.click();
await expect(count, "count didn't change").toHaveText('1');
await expect(countDup, "count didn't change").toHaveText('1');
await expect(countStep, 'count incremented by 4').toHaveText('4');
});
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).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:visible!', 'Hello, updated client:visible!')
);
const counter = page.locator('#client-visible');
const label = counter.locator('h1');
await expect(label, 'slotted text updated').toHaveText('Hello, updated client:visible!');
await expect(counter, 'component styles persisted').toHaveCSS('display', 'grid');
test.describe('Vue components in Astro files', () => {
createTests({
pageUrl: '/',
pageSourceFilePath: './src/pages/index.astro',
componentFilePath: './src/components/VueComponent.vue',
counterCssFilePath: './src/components/Counter.vue',
});
});
test.describe('Vue components in Markdown files', () => {
createTests({
pageUrl: '/markdown/',
pageSourceFilePath: './src/pages/markdown.md',
componentFilePath: './src/components/VueComponent.vue',
counterCssFilePath: './src/components/Counter.vue',
});
});