From 61cae32c8293a5090b439cfa485fe26da7facfb6 Mon Sep 17 00:00:00 2001 From: Ido Rosenthal Date: Sun, 7 Aug 2022 12:26:56 +0300 Subject: [PATCH 1/2] run out-of-memory tests multiple times with logs --- .../test/e2e/watched-project.spec.ts | 131 +++++++++--------- 1 file changed, 67 insertions(+), 64 deletions(-) diff --git a/packages/webpack-plugin/test/e2e/watched-project.spec.ts b/packages/webpack-plugin/test/e2e/watched-project.spec.ts index d7e99d193..52421c977 100644 --- a/packages/webpack-plugin/test/e2e/watched-project.spec.ts +++ b/packages/webpack-plugin/test/e2e/watched-project.spec.ts @@ -9,73 +9,76 @@ const project = 'watched-project'; const projectDir = dirname( require.resolve(`@stylable/webpack-plugin/test/e2e/projects/${project}/webpack.config`) ); - -describe(`(${project})`, () => { - const projectRunner = StylableProjectRunner.mochaSetup( - { - projectDir, - launchOptions: { - // headless: false +let i = 50; +while (--i > 0) { + describe(`(${project})`, () => { + const projectRunner = StylableProjectRunner.mochaSetup( + { + projectDir, + launchOptions: { + // headless: false + }, + watchMode: true, + useTempDir: true, + log: true, }, - watchMode: true, - useTempDir: true, - }, - before, - afterEach, - after - ); - it('renders css', async () => { - const { page } = await projectRunner.openInBrowser(); - const styleElements = await page.evaluate(browserFunctions.getStyleElementsMetadata, { - includeCSSContent: true, - }); + before, + afterEach, + after + ); + it('renders css', async () => { + const { page } = await projectRunner.openInBrowser(); + const styleElements = await page.evaluate(browserFunctions.getStyleElementsMetadata, { + includeCSSContent: true, + }); - expect(styleElements[0]).to.include({ - id: './src/index.st.css', - depth: '3', - }); + expect(styleElements[0]).to.include({ + id: './src/index.st.css', + depth: '3', + }); - expect(styleElements[0].css!.replace(/\s\s*/gm, ' ').trim()).to.match( - /\.index\d+__root \{ color: red; font-size: 3em; z-index: 1; \}/ - ); + expect(styleElements[0].css!.replace(/\s\s*/gm, ' ').trim()).to.match( + /\.index\d+__root \{ color: red; font-size: 3em; z-index: 1; \}/ + ); - await projectRunner.actAndWaitForRecompile( - 'invalidate dependency', - () => { - return writeFile( - join(projectRunner.testDir, 'src', 'mixin-b.st.css'), - '.b{ color: green; }' - ); - }, - async () => { - const { page } = await projectRunner.openInBrowser(); - const styleElements = await page.evaluate( - browserFunctions.getStyleElementsMetadata, - { - includeCSSContent: true, - } - ); - expect(styleElements[0].css!.replace(/\s\s*/gm, ' ').trim()).to.match( - /\.index\d+__root \{ color: green; font-size: 3em; z-index: 1; \}/ - ); - } - ); - }); + await projectRunner.actAndWaitForRecompile( + 'invalidate dependency', + () => { + return writeFile( + join(projectRunner.testDir, 'src', 'mixin-b.st.css'), + '.b{ color: green; }' + ); + }, + async () => { + const { page } = await projectRunner.openInBrowser(); + const styleElements = await page.evaluate( + browserFunctions.getStyleElementsMetadata, + { + includeCSSContent: true, + } + ); + expect(styleElements[0].css!.replace(/\s\s*/gm, ' ').trim()).to.match( + /\.index\d+__root \{ color: green; font-size: 3em; z-index: 1; \}/ + ); + } + ); + }); - it('allow stylable imports with missing files', async () => { - await projectRunner.actAndWaitForRecompile( - 'rename files with invalid dependencies', - () => { - return rename( - join(projectRunner.testDir, 'src', 'index.st.css'), - join(projectRunner.testDir, 'src', 'xxx.st.css') - ); - }, - () => { - // if we got here we finished to recompile with the missing file. - // when this test is broken the compiler had en error and exit the process. - expect('finish recompile'); - } - ); + it('allow stylable imports with missing files', async () => { + await projectRunner.actAndWaitForRecompile( + 'rename files with invalid dependencies', + () => { + return rename( + join(projectRunner.testDir, 'src', 'index.st.css'), + join(projectRunner.testDir, 'src', 'xxx.st.css') + ); + }, + () => { + // if we got here we finished to recompile with the missing file. + // when this test is broken the compiler had en error and exit the process. + expect('finish recompile'); + } + ); + }); }); -}); +} From a98ce8a526c3058292ef30c8cf736ade10af26fa Mon Sep 17 00:00:00 2001 From: Ido Rosenthal Date: Tue, 17 Jan 2023 18:23:59 +0200 Subject: [PATCH 2/2] clear cli test timeout to free process --- packages/e2e-test-kit/src/cli-test-kit.ts | 49 +++++++++++++++++------ 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/packages/e2e-test-kit/src/cli-test-kit.ts b/packages/e2e-test-kit/src/cli-test-kit.ts index b30aa0a46..2f0a4b452 100644 --- a/packages/e2e-test-kit/src/cli-test-kit.ts +++ b/packages/e2e-test-kit/src/cli-test-kit.ts @@ -1,6 +1,7 @@ import { fork, spawnSync, ChildProcess } from 'child_process'; import { on } from 'events'; import type { Readable } from 'stream'; +import { sleep } from 'promise-assist'; type ActionResponse = void | { sleep?: number }; @@ -41,16 +42,11 @@ export function createCliTester() { const found: { message: string; time: number }[] = []; const startTime = Date.now(); - return Promise.race([ - onTimeout(timeout, () => new Error(`${JSON.stringify(found, null, 3)}\n\n${output()}`)), + return timeoutPromise( runSteps(), - ]); - - function onTimeout(ms: number, rejectWith?: () => unknown) { - return new Promise<{ output(): string }>((resolve, reject) => - setTimeout(() => (rejectWith ? reject(rejectWith()) : resolve({ output })), ms) - ); - } + timeout, + () => `${JSON.stringify(found, null, 3)}\n\n${output()}` + ); async function runSteps() { for await (const line of readLines(process.stdout!)) { @@ -63,10 +59,10 @@ export function createCliTester() { }); if (step.action) { - const { sleep } = (await step.action()) || {}; + const { sleep: sleepMs } = (await step.action()) || {}; - if (typeof sleep === 'number') { - await onTimeout(sleep); + if (typeof sleepMs === 'number') { + await sleep(sleepMs); } } @@ -90,6 +86,35 @@ export function createCliTester() { }; } +export function timeoutPromise( + originalPromise: Promise, + ms: number, + timeoutMessage: string | (() => string) = `timed out after ${ms}ms` +): Promise { + return new Promise((resolve, reject) => { + const timerId = setTimeout( + () => + reject( + new Error( + typeof timeoutMessage === 'function' ? timeoutMessage() : timeoutMessage + ) + ), + ms + ); + + originalPromise.then( + (resolvedValue) => { + clearTimeout(timerId); + resolve(resolvedValue); + }, + (rejectReason) => { + clearTimeout(timerId); + reject(rejectReason); + } + ); + }); +} + async function* readLines(readable: Readable) { let buffer = ''; for await (const e of on(readable, 'data')) {