diff --git a/config/mocha.browser.opts b/config/mocha.browser.opts index 3d8eefc37a7..826bb3d5532 100644 --- a/config/mocha.browser.opts +++ b/config/mocha.browser.opts @@ -21,5 +21,5 @@ # karma runner supports. # This file is not converted to .mocharc.js format because karma-mocha doesn't work with it. ---timeout 20000 +--timeout 60000 --retry 3 diff --git a/packages/firestore/test/integration/api/aggregation.test.ts b/packages/firestore/test/integration/api/aggregation.test.ts index 657f7f3688d..24bd7b1192f 100644 --- a/packages/firestore/test/integration/api/aggregation.test.ts +++ b/packages/firestore/test/integration/api/aggregation.test.ts @@ -73,7 +73,7 @@ apiDescribe('Count queries', persistence => { where('author', '==', 'authorA') ).withConverter(throwingConverter); const snapshot = await getCountFromServer(query_); - expect(snapshot.data().count).to.equal(1); + expect(snapshot.data().count).to.equal(42); }); }); diff --git a/packages/firestore/test/integration/remote/stream.test.ts b/packages/firestore/test/integration/remote/stream.test.ts index 6726f92a772..a218c6207b4 100644 --- a/packages/firestore/test/integration/remote/stream.test.ts +++ b/packages/firestore/test/integration/remote/stream.test.ts @@ -291,7 +291,7 @@ it('token is not invalidated once the stream is healthy', () => { new FirestoreError(Code.UNAUTHENTICATED, '') ); await streamListener.awaitCallback('close'); - expect(credentials.observedStates).to.deep.equal(['getToken']); + expect(credentials.observedStates).to.deep.equal(['getTokenZZYZX']); }, credentials); }); diff --git a/scripts/ci-test/build_changed.ts b/scripts/ci-test/build_changed.ts index ac605145660..dc4b9fe4cd0 100644 --- a/scripts/ci-test/build_changed.ts +++ b/scripts/ci-test/build_changed.ts @@ -63,41 +63,36 @@ async function buildForTests( config: TestConfig, { buildAll = false }: Options ) { - try { - const testTasks = filterTasks(await getTestTasks(), config); - // print tasks for info - logTasks(testTasks); - if (testTasks.length === 0) { - console.log(chalk`{green No test tasks. Skipping all builds }`); - return; - } + const testTasks = filterTasks(await getTestTasks(), config); + // print tasks for info + logTasks(testTasks); + if (testTasks.length === 0) { + console.log(chalk`{green No test tasks. Skipping all builds }`); + return; + } - // build all and return - if (buildAll) { - await spawn('yarn', ['build'], { stdio: 'inherit', cwd: root }); - return; - } + // build all and return + if (buildAll) { + await spawn('yarn', ['build'], { stdio: 'inherit', cwd: root }); + return; + } - const lernaCmd = ['lerna', 'run']; - console.log(chalk`{blue Running build in:}`); - for (const task of testTasks) { - if (task.reason === TestReason.Changed) { - console.log(chalk`{yellow ${task.pkgName} (contains modified files)}`); - } else if (task.reason === TestReason.Dependent) { - console.log( - chalk`{yellow ${task.pkgName} (depends on modified files)}` - ); - } else { - console.log(chalk`{yellow ${task.pkgName} (running all tests)}`); - } - lernaCmd.push('--scope'); - lernaCmd.push(task.pkgName); + const lernaCmd = ['lerna', 'run']; + console.log(chalk`{blue Running build in:}`); + for (const task of testTasks) { + if (task.reason === TestReason.Changed) { + console.log(chalk`{yellow ${task.pkgName} (contains modified files)}`); + } else if (task.reason === TestReason.Dependent) { + console.log( + chalk`{yellow ${task.pkgName} (depends on modified files)}` + ); + } else { + console.log(chalk`{yellow ${task.pkgName} (running all tests)}`); } - - lernaCmd.push('--include-dependencies', 'build'); - await spawn('npx', lernaCmd, { stdio: 'inherit', cwd: root }); - } catch (e) { - console.error(chalk`{red ${e}}`); - process.exit(1); + lernaCmd.push('--scope'); + lernaCmd.push(task.pkgName); } + + lernaCmd.push('--include-dependencies', 'build'); + await spawn('npx', lernaCmd, { stdio: 'inherit', cwd: root }); } diff --git a/scripts/ci-test/test_changed.ts b/scripts/ci-test/test_changed.ts index 5d2f30865ed..d099ee25f7c 100644 --- a/scripts/ci-test/test_changed.ts +++ b/scripts/ci-test/test_changed.ts @@ -49,37 +49,31 @@ const config = testConfig[inputTestConfigName]!; runTests(config); async function runTests(config: TestConfig) { - try { - const testTasks = filterTasks(await getTestTasks(), config); + const testTasks = filterTasks(await getTestTasks(), config); - // print tasks for info - logTasks(testTasks); - if (testTasks.length === 0) { - chalk`{green No test tasks. Skipping all tests }`; - process.exit(0); - } + // print tasks for info + logTasks(testTasks); + if (testTasks.length === 0) { + chalk`{green No test tasks. Skipping all tests }`; + process.exit(0); + } - const lernaCmd = ['lerna', 'run', '--concurrency', '4']; - console.log(chalk`{blue Running tests in:}`); - for (const task of testTasks) { - if (task.reason === TestReason.Changed) { - console.log(chalk`{yellow ${task.pkgName} (contains modified files)}`); - } else if (task.reason === TestReason.Dependent) { - console.log( - chalk`{yellow ${task.pkgName} (depends on modified files)}` - ); - } else { - console.log(chalk`{yellow ${task.pkgName} (running all tests)}`); - } - lernaCmd.push('--scope'); - lernaCmd.push(task.pkgName); + const lernaCmd = ['lerna', 'run', '--concurrency', '4']; + console.log(chalk`{blue Running tests in:}`); + for (const task of testTasks) { + if (task.reason === TestReason.Changed) { + console.log(chalk`{yellow ${task.pkgName} (contains modified files)}`); + } else if (task.reason === TestReason.Dependent) { + console.log( + chalk`{yellow ${task.pkgName} (depends on modified files)}` + ); + } else { + console.log(chalk`{yellow ${task.pkgName} (running all tests)}`); } - - lernaCmd.push(testCommand); - await spawn('npx', lernaCmd, { stdio: 'inherit', cwd: root }); - process.exit(0); - } catch (e) { - console.error(chalk`{red ${e}}`); - process.exit(1); + lernaCmd.push('--scope'); + lernaCmd.push(task.pkgName); } + + lernaCmd.push(testCommand); + await spawn('npx', lernaCmd, { stdio: 'inherit', cwd: root }); } diff --git a/scripts/run_tests_in_ci.js b/scripts/run_tests_in_ci.js index a5ba6cd3289..42f1a562afc 100644 --- a/scripts/run_tests_in_ci.js +++ b/scripts/run_tests_in_ci.js @@ -17,8 +17,8 @@ const yargs = require('yargs'); const path = require('path'); -const { spawn } = require('child-process-promise'); -const { writeFileSync } = require('fs'); +const { spawn } = require('node:child_process'); +const fs = require('node:fs'); const LOGDIR = process.env.CI ? process.env.HOME : '/tmp'; // Maps the packages where we should not run `test:all` and instead isolate the cross-browser tests. @@ -30,16 +30,17 @@ const crossBrowserPackages = { 'packages/firestore-compat': 'test:browser' }; -function writeLogs(status, name, logText) { - const safeName = name.replace(/@/g, 'at_').replace(/\//g, '_'); - writeFileSync(path.join(LOGDIR, `${safeName}-ci-log.txt`), logText, { - encoding: 'utf8' +function getPathSafeName(name) { + return name.replace(/@/g, 'at_').replace(/\//g, '_'); +} + +async function printFile(path) { + const readStream = fs.createReadStream(path); + readStream.pipe(process.stdout); + await new Promise((resolve, reject) => { + readStream.once('end', resolve); + readStream.once('error', reject); }); - writeFileSync( - path.join(LOGDIR, `${safeName}-ci-summary.txt`), - `${status}: ${name}`, - { encoding: 'utf8' } - ); } const argv = yargs.options({ @@ -60,34 +61,43 @@ const argv = yargs.options({ let scriptName = argv.s; const dir = path.resolve(myPath); const { name } = require(`${dir}/package.json`); + const testOutputFile = path.join( + LOGDIR, + `${getPathSafeName(name)}-ci-log.txt` + ); - let stdout = ''; - let stderr = ''; - try { - if (process.env?.BROWSERS) { - for (const package in crossBrowserPackages) { - if (dir.endsWith(package)) { - scriptName = crossBrowserPackages[package]; - } + if (process.env?.BROWSERS) { + for (const package in crossBrowserPackages) { + if (dir.endsWith(package)) { + scriptName = crossBrowserPackages[package]; } } - const testProcess = spawn('yarn', ['--cwd', dir, scriptName]); + } + + const testOutputFileHandle = fs.openSync(testOutputFile, 'w'); + const testProcess = spawn('yarn', ['--cwd', dir, scriptName], { + stdio: ['inherit', testOutputFileHandle, testOutputFileHandle] + }); + + const exitCode = await new Promise((resolve, reject) => { + testProcess.once('close', resolve); + testProcess.once('error', reject); + }).finally(() => { + fs.closeSync(testOutputFileHandle); + }); - testProcess.childProcess.stdout.on('data', data => { - stdout += data.toString(); - }); - testProcess.childProcess.stderr.on('data', data => { - stderr += data.toString(); - }); + const resultStr = exitCode === 0 ? 'Success' : 'Failure'; + console.log(`${resultStr}: ${name}`); + await printFile(testOutputFile); - await testProcess; - console.log('Success: ' + name); - writeLogs('Success', name, stdout + '\n' + stderr); - } catch (e) { - console.error('Failure: ' + name); - console.log(stdout); - console.error(stderr); - writeLogs('Failure', name, stdout + '\n' + stderr); - process.exit(1); - } + fs.writeFileSync( + path.join(LOGDIR, `${getPathSafeName(name)}-ci-summary.txt`), + `${resultStr}: ${name}`, + { encoding: 'utf8' } + ); + + // NOTE: Set `process.exitCode` rather than calling `process.exit()` because + // the latter will exit forcefully even if stdout/stderr have not been fully + // flushed, leading to truncated output. + process.exitCode = exitCode; })();