Skip to content

Commit ace42b6

Browse files
committed
test(solid): share production island hydration fixtures
1 parent b00ebb1 commit ace42b6

1 file changed

Lines changed: 60 additions & 39 deletions

File tree

‎packages/solid/test/integration/island-hydration.test.ts‎

Lines changed: 60 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
22
import { dirname, join } from 'node:path';
3-
import { chromium } from 'playwright';
4-
import { preview } from 'vite';
3+
import { chromium, type Browser } from 'playwright';
4+
import { preview, type PreviewServer } from 'vite';
55
import solid from 'vite-plugin-solid';
6-
import { describe, expect, it } from 'vite-plus/test';
6+
import { afterAll, beforeAll, describe, expect, it } from 'vite-plus/test';
77
import { collectBrowserDiagnostics } from '../../../../test/browser-helpers.ts';
88
import { buildIslandApp } from '../../../../test/island-css-build.ts';
99
import { openIslandPage, type IslandPageVisit } from '../../../../test/island-page-browser.ts';
@@ -69,12 +69,7 @@ export default function Page() {
6969
}`,
7070
};
7171

72-
async function visitFixture(
73-
production: boolean,
74-
): Promise<{ visit: IslandPageVisit; close(): Promise<void> }> {
75-
if (production) {
76-
return visitProductionFixture();
77-
}
72+
async function visitFixture(): Promise<{ visit: IslandPageVisit; close(): Promise<void> }> {
7873
const root = mkdtempSync(join(import.meta.dirname, '__tmp_island_hydration_'));
7974
for (const [file, content] of Object.entries(files)) {
8075
mkdirSync(dirname(join(root, file)), { recursive: true });
@@ -98,32 +93,20 @@ async function visitFixture(
9893
}
9994
}
10095

101-
async function visitProductionFixture(): Promise<{
96+
async function visitProductionFixture(
97+
browser: Browser,
98+
base: string,
99+
): Promise<{
102100
visit: IslandPageVisit;
103101
close(): Promise<void>;
104102
}> {
105-
const build = buildIslandApp({
106-
packageDir: join(import.meta.dirname, '../..'),
107-
pluginName: 'voidSolid',
108-
files,
109-
});
110-
const server = await preview({
111-
root: build.root,
112-
configFile: false,
113-
logLevel: 'silent',
114-
build: { outDir: 'dist/client' },
115-
preview: { host: '127.0.0.1', port: 0 },
116-
});
117-
const browser = await chromium.launch();
118-
const close = async () => {
119-
await browser.close();
120-
await server.close();
121-
build.cleanup();
122-
};
103+
const context = await browser.newContext();
104+
const close = () => context.close();
123105
try {
124-
const page = await browser.newPage();
106+
const page = await context.newPage();
107+
page.setDefaultTimeout(10_000);
125108
const diagnostics = collectBrowserDiagnostics(page);
126-
const response = await page.goto(server.resolvedUrls!.local[0]);
109+
const response = await page.goto(base);
127110
const visit = { page, diagnostics, html: await response!.text(), close };
128111
return { visit, close };
129112
} catch (error) {
@@ -164,24 +147,62 @@ async function expectReused(visit: IslandPageVisit, name: string): Promise<void>
164147
}
165148

166149
describe.each(['dev', 'production'])('%s island hydration', (mode) => {
150+
let productionBuild: ReturnType<typeof buildIslandApp> | undefined;
151+
let productionServer: PreviewServer | undefined;
152+
let productionBrowser: Browser | undefined;
153+
154+
beforeAll(async () => {
155+
if (mode === 'production') {
156+
productionBuild = buildIslandApp({
157+
packageDir: join(import.meta.dirname, '../..'),
158+
pluginName: 'voidSolid',
159+
files,
160+
});
161+
productionServer = await preview({
162+
root: productionBuild.root,
163+
configFile: false,
164+
logLevel: 'silent',
165+
build: { outDir: 'dist/client' },
166+
preview: { host: '127.0.0.1', port: 0 },
167+
});
168+
productionBrowser = await chromium.launch();
169+
}
170+
});
171+
172+
afterAll(async () => {
173+
await productionBrowser?.close();
174+
await productionServer?.close();
175+
productionBuild?.cleanup();
176+
});
177+
178+
function newFixture() {
179+
return mode === 'production'
180+
? visitProductionFixture(productionBrowser!, productionServer!.resolvedUrls!.local[0])
181+
: visitFixture();
182+
}
183+
167184
it('reuses SSR DOM and preserves input in repeated islands and an island layout', async () => {
168-
const fixture = await visitFixture(mode === 'production');
185+
const fixture = await newFixture();
169186
try {
170187
for (const name of ['layout', 'first', 'second']) {
171188
await expectReused(fixture.visit, name);
172189
}
173190
const { page } = fixture.visit;
174191
await page.locator('[data-counter="first"] button').click();
175-
expect(await page.locator('[data-counter="first"] button').textContent()).toBe('1');
176-
expect(await page.locator('[data-counter="second"] button').textContent()).toBe('10');
192+
await expect
193+
.poll(() => page.locator('[data-counter="first"] button').textContent())
194+
.toBe('1');
195+
await expect
196+
.poll(() => page.locator('[data-counter="second"] button').textContent())
197+
.toBe('10');
177198
expect(fixture.visit.diagnostics()).not.toContain('pageerror');
178199
} finally {
179200
await fixture.close();
180201
}
181202
});
182203

183204
it('hydrates visible islands in reverse order after another island handles an event', async () => {
184-
const fixture = await visitFixture(mode === 'production');
205+
const fixture = await newFixture();
185206
try {
186207
const { page } = fixture.visit;
187208
await page.waitForSelector('[data-counter="first"]');
@@ -201,9 +222,9 @@ describe.each(['dev', 'production'])('%s island hydration', (mode) => {
201222
await page.locator(`[data-counter="${name}"]`).scrollIntoViewIfNeeded();
202223
await expectReused(fixture.visit, name);
203224
await page.locator(`[data-counter="${name}"] button`).click();
204-
expect(await page.locator(`[data-counter="${name}"] button`).textContent()).toBe(
205-
String(initial + 1),
206-
);
225+
await expect
226+
.poll(() => page.locator(`[data-counter="${name}"] button`).textContent())
227+
.toBe(String(initial + 1));
207228
}
208229
expect(fixture.visit.diagnostics()).not.toContain('pageerror');
209230
} finally {
@@ -212,13 +233,13 @@ describe.each(['dev', 'production'])('%s island hydration', (mode) => {
212233
});
213234

214235
it('hydrates an async resource inside Suspense without replacing the resolved SSR DOM', async () => {
215-
const fixture = await visitFixture(mode === 'production');
236+
const fixture = await newFixture();
216237
try {
217238
expect(fixture.visit.html).toContain('data-counter="async"');
218239
await expectReused(fixture.visit, 'async');
219240
const button = fixture.visit.page.locator('[data-counter="async"] button');
220241
await button.click();
221-
expect(await button.textContent()).toBe('51');
242+
await expect.poll(() => button.textContent()).toBe('51');
222243
expect(fixture.visit.diagnostics()).not.toContain('pageerror');
223244
} finally {
224245
await fixture.close();

0 commit comments

Comments
 (0)