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 os from 'os';
import { loadFixture } from './test-utils.js'; import { testFactory } from './test-utils.js';
const test = base.extend({ const test = testFactory({ root: './fixtures/astro-component/' });
astro: async ({}, use) => {
const fixture = await loadFixture({ root: './fixtures/astro-component/' });
await use(fixture);
},
});
let devServer; let devServer;

View file

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

View file

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

View file

@ -1,14 +1,13 @@
<template> <template>
<pre>{{ value }}</pre> <div :id="id">Framework client:only component</div>
<my-button>Click Me</my-button>
</template> </template>
<script> <script>
export default { export default {
props: { props: {
value: { id: {
type: Number, type: String,
required: true 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">
<html>
<head> <head>
<meta charset="utf-8" /> <!-- Head Stuff -->
<meta
name="viewport"
content="width=device-width"
/>
<title>Vue component</title>
<style>
:global(:root) {
font-family: system-ui;
padding: 1em;
}
</style>
</head> </head>
<body> <body>
<main> <Counter id="server-only" {...someProps}>
<Counter id="server-only" start="0">No Client</Counter> <h1>Hello, server!</h1>
<Counter id="client-load" start="0" client:load>Hello, client:load!</Counter> </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> <Counter id="client-idle" {...someProps} client:idle>
<!-- Test island deduplication account for non-render affecting props. --> <h1>Hello, client:idle!</h1>
<Counter id="client-load-step" start="0" step-size="2" client:load>Hello, client:load!</Counter> </Counter>
<Counter id="client-idle" start="0" client:idle>Hello, client:idle!</Counter>
<!-- Test that two client:visibles have unique uids --> <Counter id="client-load" {...someProps} client:load>
<Counter id="client-visible" start="0" client:visible>Hello, client:visible!</Counter> <h1>Hello, client:load!</h1>
<Counter id="client-media" start="0" client:media="(max-width: 50rem)">Hello, client:media!</Counter> </Counter>
</main>
<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> </body>
</html> </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 { expect } from '@playwright/test';
import { loadFixture } from './test-utils.js'; import { testFactory } from './test-utils.js';
const test = base.extend({ const test = testFactory({ root: './fixtures/lit-component/' });
astro: async ({}, use) => {
const fixture = await loadFixture({ root: './fixtures/lit-component/' });
await use(fixture);
},
});
let devServer; let devServer;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,3 +1,4 @@
import { test as testBase } from '@playwright/test';
import { loadFixture as baseLoadFixture } from '../test/test-utils.js'; import { loadFixture as baseLoadFixture } from '../test/test-utils.js';
export function loadFixture(inlineConfig) { export function loadFixture(inlineConfig) {
@ -11,3 +12,20 @@ export function loadFixture(inlineConfig) {
root: new URL(inlineConfig.root, import.meta.url).toString(), 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 { expect } from '@playwright/test';
import { loadFixture } from './test-utils.js'; import { testFactory } from './test-utils.js';
const test = base.extend({ const test = testFactory({ root: './fixtures/ts-resolution/' });
astro: async ({}, use) => {
const fixture = await loadFixture({ root: './fixtures/ts-resolution/' });
await use(fixture);
},
});
function runTest(it) { function runTest(it) {
it('client:idle', async ({ page, astro }) => { it('client:idle', async ({ page, astro }) => {

View file

@ -1,147 +1,21 @@
import { test as base, expect } from '@playwright/test'; import { prepareTestFactory } from './shared-component-tests.js';
import { loadFixture } from './test-utils.js';
const test = base.extend({ const { test, createTests } = prepareTestFactory({ root: './fixtures/vue-component/' });
astro: async ({}, use) => {
const fixture = await loadFixture({ root: './fixtures/vue-component/' });
await use(fixture);
},
});
let devServer; test.describe('Vue components in Astro files', () => {
createTests({
test.beforeEach(async ({ astro }) => { pageUrl: '/',
devServer = await astro.startDevServer(); pageSourceFilePath: './src/pages/index.astro',
}); componentFilePath: './src/components/VueComponent.vue',
counterCssFilePath: './src/components/Counter.vue',
test.afterEach(async () => { });
await devServer.stop(); });
});
test.describe('Vue components in Markdown files', () => {
test.describe('Vue components', () => { createTests({
test('server only', async ({ page, astro }) => { pageUrl: '/markdown/',
await page.goto(astro.resolveUrl('/')); pageSourceFilePath: './src/pages/markdown.md',
componentFilePath: './src/components/VueComponent.vue',
const counter = page.locator('#server-only'); counterCssFilePath: './src/components/Counter.vue',
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');
}); });
}); });