From aca8b111c3a3e3d3133edfb2ffaa8acf38bed60c Mon Sep 17 00:00:00 2001 From: Raghu Simha Date: Tue, 12 May 2020 18:19:26 -0400 Subject: [PATCH] =?UTF-8?q?=F0=9F=8F=97Allow=20`gulp`=20tasks=20to=20progr?= =?UTF-8?q?ammatically=20build=20the=20runtime=20(#28326)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../babel-config/pre-closure-config.js | 8 +- build-system/common/utils.js | 27 +-- build-system/compile/compile.js | 2 +- build-system/compile/helpers.js | 8 +- build-system/compile/single-pass.js | 6 +- build-system/pr-check/visual-diff-tests.js | 6 +- build-system/tasks/build.js | 31 ++- build-system/tasks/css.js | 7 +- build-system/tasks/dist.js | 43 ++-- build-system/tasks/e2e/index.js | 10 +- build-system/tasks/firebase.js | 31 +-- build-system/tasks/helpers.js | 79 +++---- build-system/tasks/integration.js | 12 +- .../tasks/performance/compile-scripts.js | 4 +- build-system/tasks/vendor-configs.js | 2 +- build-system/tasks/visual-diff/index.js | 9 +- contributing/TESTING.md | 196 +++++++++--------- 17 files changed, 253 insertions(+), 228 deletions(-) diff --git a/build-system/babel-config/pre-closure-config.js b/build-system/babel-config/pre-closure-config.js index d41509945a1d..d013a8d40555 100644 --- a/build-system/babel-config/pre-closure-config.js +++ b/build-system/babel-config/pre-closure-config.js @@ -25,6 +25,10 @@ const {getExperimentConstant, getReplacePlugin} = require('./helpers'); */ function getPreClosureConfig() { const isCheckTypes = argv._.includes('check-types'); + const testTasks = ['e2e', 'integration', 'visual-diff']; + const isTestTask = testTasks.some((task) => argv._.includes(task)); + const isFortesting = argv.fortesting || isTestTask; + // For experiment, remove FixedLayer import from v0.js, otherwise remove // from amp-viewer-integration const fixedLayerImport = @@ -89,13 +93,13 @@ function getPreClosureConfig() { !isCheckTypes ? './build-system/babel-plugins/babel-plugin-transform-json-configuration' : null, - !(argv.fortesting || isCheckTypes) + !(isFortesting || isCheckTypes) ? [ './build-system/babel-plugins/babel-plugin-amp-mode-transformer', {isEsmBuild: !!argv.esm}, ] : null, - !(argv.fortesting || isCheckTypes) + !(isFortesting || isCheckTypes) ? './build-system/babel-plugins/babel-plugin-is_dev-constant-transformer' : null, ].filter(Boolean); diff --git a/build-system/common/utils.js b/build-system/common/utils.js index 3c945f860f52..416ddc21eaaa 100644 --- a/build-system/common/utils.js +++ b/build-system/common/utils.js @@ -19,6 +19,9 @@ const fs = require('fs-extra'); const globby = require('globby'); const log = require('fancy-log'); const path = require('path'); +const {clean} = require('../tasks/clean'); +const {doBuild} = require('../tasks/build'); +const {doDist} = require('../tasks/dist'); const {execOrDie} = require('./exec'); const {gitDiffNameOnlyMaster} = require('./git'); const {green, cyan, yellow} = require('ansi-colors'); @@ -27,24 +30,16 @@ const {isTravisBuild} = require('./travis'); const ROOT_DIR = path.resolve(__dirname, '../../'); /** - * Cleans and builds binaries with --fortesting flag and - * overriden config. - * - * @param {boolean} minified + * Performs a clean build of the AMP runtime in testing mode. + * Used by `gulp e2e|integration|visual_diff`. */ -// TODO(gh/amphtml/28312): Directly call dist() or build() -// instead of spwaning a new process. -function buildRuntime(minified = true) { - execOrDie('gulp clean'); - - let command = minified ? `gulp dist --fortesting` : `gulp build --fortesting`; - if (argv.core_runtime_only) { - command += ` --core_runtime_only`; - } else if (argv.extensions) { - command += ` --extensions=${argv.extensions}`; +async function buildRuntime() { + await clean(); + if (argv.compiled) { + await doDist({fortesting: true}); + } else { + await doBuild({fortesting: true}); } - - execOrDie(command); } /** diff --git a/build-system/compile/compile.js b/build-system/compile/compile.js index 8318a8ef3a23..f0239a9ae003 100644 --- a/build-system/compile/compile.js +++ b/build-system/compile/compile.js @@ -396,7 +396,7 @@ function compile( ) .pipe(postClosureBabel()) .pipe(sanitize()) - .pipe(writeSourcemaps()) + .pipe(writeSourcemaps(options)) .pipe(gulp.dest('.')) .on('end', resolve); } diff --git a/build-system/compile/helpers.js b/build-system/compile/helpers.js index 21150113dc59..a0b0b9a09c22 100644 --- a/build-system/compile/helpers.js +++ b/build-system/compile/helpers.js @@ -21,7 +21,7 @@ const {VERSION: internalRuntimeVersion} = require('./internal-version'); const argv = minimist(process.argv.slice(2)); -function getSourceMapBase() { +function getSourceMapBase(options) { if (argv.sourcemap_url) { // Custom sourcemap URLs have placeholder {version} that should be // replaced with the actual version. Also, ensure trailing slash exists. @@ -29,15 +29,15 @@ function getSourceMapBase() { .replace(/\{version\}/g, internalRuntimeVersion) .replace(/([^/])$/, '$1/'); } - if (argv.fortesting) { + if (options.fortesting) { return 'http://localhost:8000/'; } return `https://raw.githubusercontent.com/ampproject/amphtml/${internalRuntimeVersion}/`; } -function writeSourcemaps() { +function writeSourcemaps(options) { return sourcemaps.write('.', { - sourceRoot: getSourceMapBase(), + sourceRoot: getSourceMapBase(options), includeContent: !!argv.full_sourcemaps, }); } diff --git a/build-system/compile/single-pass.js b/build-system/compile/single-pass.js index 43579fd53be6..5f205e1feac6 100644 --- a/build-system/compile/single-pass.js +++ b/build-system/compile/single-pass.js @@ -527,7 +527,7 @@ exports.singlePassCompile = async function (entryModule, options, timeInfo) { externs: options.externs, hideWarningsFor: options.hideWarningsFor, }) - .then(compile) + .then((flagsArray) => compile(flagsArray, options)) .then(wrapMainBinaries) .then(intermediateBundleConcat) .then(eliminateIntermediateBundles) @@ -690,7 +690,7 @@ function cleanupWeakModuleFiles() { return del([weakModuleJsFile, weakModuleMapFile]); } -function compile(flagsArray) { +function compile(flagsArray, options) { log('Minifying single-pass JS with', colors.cyan('closure-compiler') + '...'); // TODO(@cramforce): Run the post processing step return new Promise(function (resolve, reject) { @@ -703,7 +703,7 @@ function compile(flagsArray) { .on('error', (err) => handleSinglePassCompilerError(err)) .pipe(gulpIf(!argv.pseudo_names, checkForUnknownDeps())) .on('error', reject) - .pipe(writeSourcemaps()) + .pipe(writeSourcemaps(options)) .pipe( gulpIf( /(\/amp-|\/_base)/, diff --git a/build-system/pr-check/visual-diff-tests.js b/build-system/pr-check/visual-diff-tests.js index c801393793c3..ac9e7ddd2329 100644 --- a/build-system/pr-check/visual-diff-tests.js +++ b/build-system/pr-check/visual-diff-tests.js @@ -44,7 +44,7 @@ function main() { downloadDistOutput(FILENAME); timedExecOrDie('gulp update-packages'); process.env['PERCY_TOKEN'] = atob(process.env.PERCY_TOKEN_ENCODED); - timedExecOrDie('gulp visual-diff --nobuild --master'); + timedExecOrDie('gulp visual-diff --compiled --nobuild --master'); } else { printChangeSummary(FILENAME); const buildTargets = determineBuildTargets(FILENAME); @@ -56,9 +56,9 @@ function main() { ) { downloadDistOutput(FILENAME); timedExecOrDie('gulp update-packages'); - timedExecOrDie('gulp visual-diff --nobuild'); + timedExecOrDie('gulp visual-diff --compiled --nobuild'); } else { - timedExecOrDie('gulp visual-diff --nobuild --empty'); + timedExecOrDie('gulp visual-diff --empty'); console.log( `${FILELOGPREFIX} Skipping`, colors.cyan('Visual Diff Tests'), diff --git a/build-system/tasks/build.js b/build-system/tasks/build.js index d8ff1089bc90..7cf5e6ece7af 100644 --- a/build-system/tasks/build.js +++ b/build-system/tasks/build.js @@ -62,30 +62,44 @@ async function watch() { * Perform the prerequisite steps before starting the unminified build. * Used by `gulp` and `gulp build`. * - * @param {boolean} watch + * @param {!Object} options */ -async function runPreBuildSteps(watch) { - await compileCss(watch); +async function runPreBuildSteps(options) { + await compileCss(options); await compileJison(); - await bootstrapThirdPartyFrames(watch); + await bootstrapThirdPartyFrames(options); } /** * Unminified build. Entry point for `gulp build`. */ async function build() { + await doBuild(); +} + +/** + * Performs an unminified build with the given extra args. + * + * @param {Object=} extraArgs + */ +async function doBuild(extraArgs = {}) { maybeUpdatePackages(); const handlerProcess = createCtrlcHandler('build'); process.env.NODE_ENV = 'development'; + const options = { + fortesting: extraArgs.fortesting || argv.fortesting, + minify: false, + watch: argv.watch, + }; printNobuildHelp(); printConfigHelp('gulp build'); parseExtensionFlags(); - await runPreBuildSteps(argv.watch); + await runPreBuildSteps(options); if (argv.core_runtime_only) { - await compileCoreRuntime(argv.watch, /* minify */ false); + await compileCoreRuntime(options); } else { - await compileAllJs(/* minify */ false); - await buildExtensions({watch: argv.watch}); + await compileAllJs(options); + await buildExtensions(options); } if (!argv.watch) { exitCtrlcHandler(handlerProcess); @@ -94,6 +108,7 @@ async function build() { module.exports = { build, + doBuild, runPreBuildSteps, watch, }; diff --git a/build-system/tasks/css.js b/build-system/tasks/css.js index 8e12b5884e07..8cb7cfd969d3 100644 --- a/build-system/tasks/css.js +++ b/build-system/tasks/css.js @@ -76,11 +76,12 @@ const cssEntryPoints = [ /** * Compile all the css and drop in the build folder - * @param {boolean} watch + * + * @param {Object=} options * @return {!Promise} */ -function compileCss(watch) { - if (watch) { +function compileCss(options = {}) { + if (options.watch) { const watchFunc = () => { compileCss(); }; diff --git a/build-system/tasks/dist.js b/build-system/tasks/dist.js index 3a1dbebdfee3..939e3ed46c1c 100644 --- a/build-system/tasks/dist.js +++ b/build-system/tasks/dist.js @@ -74,14 +74,16 @@ const hostname = argv.hostname || 'cdn.ampproject.org'; /** * Prints a useful help message prior to the gulp dist task + * + * @param {!Object} options */ -function printDistHelp() { +function printDistHelp(options) { if (argv.sanitize_vars_for_diff && !argv.pseudo_names) { throw new Error('--sanitize_vars_for_diff requires --pseudo_names'); } let cmd = 'gulp dist'; - if (argv.fortesting) { + if (options.fortesting) { cmd = cmd + ' --fortesting'; } if (argv.single_pass) { @@ -103,42 +105,54 @@ function printDistHelp() { * Perform the prerequisite steps before starting the minified build. * Used by `gulp` and `gulp dist`. * - * @param {boolean} watch + * @param {!Object} options */ -async function runPreDistSteps(watch) { +async function runPreDistSteps(options) { cleanupBuildDir(); await prebuild(); - await compileCss(watch); + await compileCss(options); await compileJison(); await copyCss(); await copyParsers(); - await bootstrapThirdPartyFrames(watch, /* minify */ true); + await bootstrapThirdPartyFrames(options); await startNailgunServer(distNailgunPort, /* detached */ false); displayLifecycleDebugging(); } /** - * Dist Build - * @return {!Promise} + * Minified build. Entry point for `gulp dist`. */ async function dist() { + await doDist(); +} + +/** + * Performs a minified build with the given extra args. + * + * @param {Object=} extraArgs + */ +async function doDist(extraArgs = {}) { maybeUpdatePackages(); const handlerProcess = createCtrlcHandler('dist'); process.env.NODE_ENV = 'production'; + const options = { + fortesting: extraArgs.fortesting || argv.fortesting, + minify: true, + watch: argv.watch, + }; printNobuildHelp(); - printDistHelp(); - - await runPreDistSteps(argv.watch); + printDistHelp(options); + await runPreDistSteps(options); // Steps that use closure compiler. Small ones before large (parallel) ones. if (argv.core_runtime_only) { - await compileCoreRuntime(argv.watch, /* minify */ true); + await compileCoreRuntime(options); } else { await buildExperiments(); await buildLoginDone('0.1'); await buildWebPushPublisherFiles(); - await compileAllJs(/* minify */ true); - await buildExtensions({minify: true, watch: argv.watch}); + await compileAllJs(options); + await buildExtensions(options); } if (!argv.watch) { await stopNailgunServer(distNailgunPort); @@ -435,6 +449,7 @@ function preBuildLoginDoneVersion(version) { module.exports = { dist, + doDist, runPreDistSteps, }; diff --git a/build-system/tasks/e2e/index.js b/build-system/tasks/e2e/index.js index 94c15868914d..80dc6430d0f3 100644 --- a/build-system/tasks/e2e/index.js +++ b/build-system/tasks/e2e/index.js @@ -39,11 +39,11 @@ const PORT = 8000; const SLOW_TEST_THRESHOLD_MS = 2500; const TEST_RETRIES = isTravisBuild() ? 2 : 0; -async function launchWebServer_(minified) { +async function launchWebServer_() { await startServer( {host: HOST, port: PORT}, {quiet: !argv.debug}, - {compiled: minified} + {compiled: argv.compiled} ); } @@ -84,11 +84,11 @@ async function e2e() { // build runtime if (!argv.nobuild) { - buildRuntime(/* minified */ !!argv.compiled); + await buildRuntime(); } // start up web server - await launchWebServer_(/* minified */ argv.compiled); + await launchWebServer_(); // run tests if (!argv.watch) { @@ -154,7 +154,7 @@ e2e.flags = { 'nobuild': ' Skips building the runtime via `gulp (build|dist) --fortesting`', 'extensions': ' Builds only the listed extensions.', - 'compiled': ' Runs the tests using minified js', + 'compiled': ' Runs tests against minified JS', 'files': ' Run tests found in a specific path (ex: **/test-e2e/*.js)', 'testnames': ' Lists the name of each test being run', 'watch': ' Watches for changes in files, runs corresponding test(s)', diff --git a/build-system/tasks/firebase.js b/build-system/tasks/firebase.js index e9b35052135f..970564b3616a 100644 --- a/build-system/tasks/firebase.js +++ b/build-system/tasks/firebase.js @@ -18,10 +18,9 @@ const colors = require('ansi-colors'); const fs = require('fs-extra'); const log = require('fancy-log'); const path = require('path'); -const {applyAmpConfig} = require('./helpers'); -const {build} = require('./build'); const {clean} = require('./clean'); -const {dist} = require('./dist'); +const {doBuild} = require('./build'); +const {doDist} = require('./dist'); async function walk(dest) { const filelist = []; @@ -51,10 +50,10 @@ async function copyAndReplaceUrls(src, dest) { async function firebase() { if (!argv.nobuild) { await clean(); - if (argv.min) { - await dist(); + if (argv.compiled) { + await doDist({fortesting: argv.fortesting}); } else { - await build(); + await doBuild({fortesting: argv.fortesting}); } } await fs.mkdirp('firebase'); @@ -78,16 +77,6 @@ async function firebase() { fs.copy('dist.3p/current', 'firebase/dist.3p/current', {overwrite: true}), ]); - if (argv.fortesting) { - await Promise.all([ - applyAmpConfig( - 'firebase/dist.3p/current/integration.js', - /* localDev */ true - ), - applyAmpConfig('firebase/dist/amp.js', /* localDev */ true), - ]); - } - await Promise.all([ fs.copyFile('firebase/dist/ww.max.js', 'firebase/dist/ww.js', { overwrite: true, @@ -101,7 +90,7 @@ async function replaceUrls(filePath) { /https:\/\/cdn\.ampproject\.org\/v0\.js/g, '/dist/amp.js' ); - if (argv.min) { + if (argv.compiled) { result = result.replace( /https:\/\/cdn\.ampproject\.org\/v0\/(.+?).js/g, '/dist/v0/$1.js' @@ -121,9 +110,9 @@ module.exports = { firebase.description = 'Generates firebase folder for deployment'; firebase.flags = { - 'file': 'File to deploy to firebase as index.html', - 'min': 'Source from minified files', - 'nobuild': 'Skips the gulp build|dist step.', + 'file': ' File to deploy to firebase as index.html', + 'compiled': ' Deploy from minified files', + 'nobuild': ' Skips the gulp build|dist step.', 'fortesting': - 'Expects an env var AMP_TESTING_HOST and writes this to AMP_CONFIG', + ' Expects an env var AMP_TESTING_HOST and writes this to AMP_CONFIG', }; diff --git a/build-system/tasks/helpers.js b/build-system/tasks/helpers.js index e4d66bdc4848..3eba955eaa41 100644 --- a/build-system/tasks/helpers.js +++ b/build-system/tasks/helpers.js @@ -123,22 +123,22 @@ function doBuildJs(jsBundles, name, extraOptions) { /** * Generates frames.html - * @param {boolean} watch - * @param {boolean} minify - * @return {!Promise} + * + * @param {!Object} options */ -async function bootstrapThirdPartyFrames(watch, minify) { +async function bootstrapThirdPartyFrames(options) { const startTime = Date.now(); const promises = []; + const {watch, minify} = options; thirdPartyFrames.forEach((frameObject) => { promises.push( - thirdPartyBootstrap(frameObject.max, frameObject.min, minify) + thirdPartyBootstrap(frameObject.max, frameObject.min, options) ); }); if (watch) { thirdPartyFrames.forEach((frameObject) => { const watchFunc = () => { - thirdPartyBootstrap(frameObject.max, frameObject.min, minify); + thirdPartyBootstrap(frameObject.max, frameObject.min, options); }; gulpWatch(frameObject.max, debounce(watchFunc, watchDebounceDelay)); }); @@ -153,46 +153,45 @@ async function bootstrapThirdPartyFrames(watch, minify) { /** * Compile and optionally minify the core runtime. - * @param {boolean} watch - * @param {boolean} minify - * @return {!Promise} + * + * @param {!Object} options */ -async function compileCoreRuntime(watch, minify) { - await doBuildJs(jsBundles, 'amp.js', {watch, minify}); +async function compileCoreRuntime(options) { + await doBuildJs(jsBundles, 'amp.js', options); } /** * Compile and optionally minify the stylesheets and the scripts for the runtime * and drop them in the dist folder * - * @param {boolean} minify + * @param {!Object} options * @return {!Promise} */ -async function compileAllJs(minify) { +async function compileAllJs(options) { + const {minify} = options; if (minify) { log('Minifying multi-pass JS with', cyan('closure-compiler') + '...'); } else { log('Compiling JS with', cyan('browserify') + '...'); } const startTime = Date.now(); - const {watch} = argv; await Promise.all([ - minify ? Promise.resolve() : doBuildJs(jsBundles, 'polyfills.js', {watch}), - doBuildJs(jsBundles, 'alp.max.js', {watch, minify}), - doBuildJs(jsBundles, 'examiner.max.js', {watch, minify}), - doBuildJs(jsBundles, 'ww.max.js', {watch, minify}), - doBuildJs(jsBundles, 'integration.js', {watch, minify}), - doBuildJs(jsBundles, 'ampcontext-lib.js', {watch, minify}), - doBuildJs(jsBundles, 'iframe-transport-client-lib.js', {watch, minify}), - doBuildJs(jsBundles, 'recaptcha.js', {watch, minify}), - doBuildJs(jsBundles, 'amp-viewer-host.max.js', {watch, minify}), - doBuildJs(jsBundles, 'video-iframe-integration.js', {watch, minify}), - doBuildJs(jsBundles, 'amp-story-player.js', {watch, minify}), - doBuildJs(jsBundles, 'amp-inabox-host.js', {watch, minify}), - doBuildJs(jsBundles, 'amp-shadow.js', {watch, minify}), - doBuildJs(jsBundles, 'amp-inabox.js', {watch, minify}), + minify ? Promise.resolve() : doBuildJs(jsBundles, 'polyfills.js', options), + doBuildJs(jsBundles, 'alp.max.js', options), + doBuildJs(jsBundles, 'examiner.max.js', options), + doBuildJs(jsBundles, 'ww.max.js', options), + doBuildJs(jsBundles, 'integration.js', options), + doBuildJs(jsBundles, 'ampcontext-lib.js', options), + doBuildJs(jsBundles, 'iframe-transport-client-lib.js', options), + doBuildJs(jsBundles, 'recaptcha.js', options), + doBuildJs(jsBundles, 'amp-viewer-host.max.js', options), + doBuildJs(jsBundles, 'video-iframe-integration.js', options), + doBuildJs(jsBundles, 'amp-story-player.js', options), + doBuildJs(jsBundles, 'amp-inabox-host.js', options), + doBuildJs(jsBundles, 'amp-shadow.js', options), + doBuildJs(jsBundles, 'amp-inabox.js', options), ]); - await compileCoreRuntime(watch, minify); + await compileCoreRuntime(options); endBuildStep( minify ? 'Minified' : 'Compiled', 'all runtime JS files', @@ -299,7 +298,8 @@ async function compileMinifiedJs(srcDir, srcFilename, destDir, options) { if (!argv.noconfig && MINIFIED_TARGETS.includes(minifiedName)) { await applyAmpConfig( maybeToEsmName(`${destDir}/${minifiedName}`), - /* localDev */ !!argv.fortesting + /* localDev */ options.fortesting, + /* fortesting */ options.fortesting ); } @@ -310,7 +310,8 @@ async function compileMinifiedJs(srcDir, srcFilename, destDir, options) { altMainBundles.map(({name}) => applyAmpConfig( maybeToEsmName(`dist/${name}.js`), - /* localDev */ !!argv.fortesting + /* localDev */ options.fortesting, + /* fortesting */ options.fortesting ) ) ); @@ -445,7 +446,8 @@ function compileUnminifiedJs(srcDir, srcFilename, destDir, options) { if (UNMINIFIED_TARGETS.includes(destFilename)) { return applyAmpConfig( `${destDir}/${destFilename}`, - /* localDev */ true + /* localDev */ true, + /* fortesting */ options.fortesting ); } }); @@ -561,11 +563,13 @@ function printNobuildHelp() { * Writes AMP_CONFIG to a runtime file. Optionally enables localDev mode and * fortesting mode. Called by "gulp build" and "gulp dist" while building * various runtime files. + * * @param {string} targetFile File to which the config is to be written. * @param {boolean} localDev Whether or not to enable local development. + * @param {boolean} fortesting Whether or not to enable testing mode. * @return {!Promise} */ -async function applyAmpConfig(targetFile, localDev) { +async function applyAmpConfig(targetFile, localDev, fortesting) { const config = argv.config === 'canary' ? 'canary' : 'prod'; const baseConfigFile = 'build-system/global-configs/' + config + '-config.json'; @@ -578,7 +582,7 @@ async function applyAmpConfig(targetFile, localDev) { /* opt_localDev */ localDev, /* opt_localBranch */ true, /* opt_branch */ false, - /* opt_fortesting */ !!argv.fortesting + /* opt_fortesting */ fortesting ); }); } @@ -603,10 +607,11 @@ function concatFilesToString(files) { * * @param {string} input * @param {string} outputName - * @param {boolean} minify + * @param {!Object} options * @return {!Promise} */ -function thirdPartyBootstrap(input, outputName, minify) { +function thirdPartyBootstrap(input, outputName, options) { + const {minify, fortesting} = options; if (!minify) { return toPromise(gulp.src(input).pipe(gulp.dest('dist.3p/current'))); } @@ -615,7 +620,7 @@ function thirdPartyBootstrap(input, outputName, minify) { // actual frame host for the JS inside the frame. // But during testing we need a relative reference because the // version is not available on the absolute path. - const integrationJs = argv.fortesting + const integrationJs = fortesting ? './f.js' : `https://${hostname3p}/${internalRuntimeVersion}/f.js`; // Convert default relative URL to absolute min URL. diff --git a/build-system/tasks/integration.js b/build-system/tasks/integration.js index 60976152d1ed..cb6c51a3dffd 100644 --- a/build-system/tasks/integration.js +++ b/build-system/tasks/integration.js @@ -24,7 +24,7 @@ const { RuntimeTestRunner, RuntimeTestConfig, } = require('./runtime-test/runtime-test-base'); -const {execOrDie} = require('../common/exec'); +const {buildRuntime} = require('../common/utils'); class Runner extends RuntimeTestRunner { constructor(config) { @@ -36,12 +36,7 @@ class Runner extends RuntimeTestRunner { if (argv.nobuild) { return; } - execOrDie('gulp clean'); - if (argv.compiled) { - execOrDie(`gulp dist --fortesting --config ${argv.config}`); - } else { - execOrDie(`gulp build --config ${argv.config}`); - } + await buildRuntime(); } } @@ -68,8 +63,7 @@ integration.description = 'Runs integration tests'; integration.flags = { 'chrome_canary': ' Runs tests on Chrome Canary', 'chrome_flags': ' Uses the given flags to launch Chrome', - 'compiled': - ' Changes integration tests to use production JS binaries for execution', + 'compiled': ' Runs tests against minified JS', 'single_pass': ' Run tests in Single Pass mode', 'config': ' Sets the runtime\'s AMP_CONFIG to one of "prod" (default) or "canary"', diff --git a/build-system/tasks/performance/compile-scripts.js b/build-system/tasks/performance/compile-scripts.js index 87f1debde72f..0cd8bc02af6f 100644 --- a/build-system/tasks/performance/compile-scripts.js +++ b/build-system/tasks/performance/compile-scripts.js @@ -15,7 +15,7 @@ */ const argv = require('minimist')(process.argv.slice(2)); -const {dist} = require('../dist'); +const {doDist} = require('../dist'); const {EXPERIMENT, urlToCachePath} = require('./helpers'); const {setExtensionsToBuildFromDocuments} = require('../extension-helpers.js'); @@ -28,7 +28,7 @@ async function compileScripts(urls) { if (!argv.nobuild) { const examples = urls.map((url) => urlToCachePath(url, EXPERIMENT)); setExtensionsToBuildFromDocuments(examples); - await dist(); + await doDist(); } } diff --git a/build-system/tasks/vendor-configs.js b/build-system/tasks/vendor-configs.js index 179ebc8f37a4..ad06b7db5cc3 100644 --- a/build-system/tasks/vendor-configs.js +++ b/build-system/tasks/vendor-configs.js @@ -40,7 +40,7 @@ async function vendorConfigs(opt_options) { const destPath = 'dist/v0/analytics-vendors/'; // ignore test json if not fortesting - if (!argv.fortesting) { + if (!(argv.fortesting || options.fortesting)) { srcPath.push('!extensions/amp-analytics/0.1/vendors/_fake_.json'); } diff --git a/build-system/tasks/visual-diff/index.js b/build-system/tasks/visual-diff/index.js index 8378f9ddda67..68969d0e12d1 100644 --- a/build-system/tasks/visual-diff/index.js +++ b/build-system/tasks/visual-diff/index.js @@ -157,7 +157,7 @@ async function launchWebServer() { await startServer( {host: HOST, port: PORT}, {quiet: !argv.webserver_debug}, - {compiled: true} + {compiled: argv.compiled} ); } @@ -683,7 +683,7 @@ async function createEmptyBuild() { */ async function visualDiff() { const handlerProcess = createCtrlcHandler('visual-diff'); - ensureOrBuildAmpRuntimeInTestMode_(); + await ensureOrBuildAmpRuntimeInTestMode_(); installPercy_(); setupCleanup_(); maybeOverridePercyEnvironmentVariables(); @@ -753,14 +753,14 @@ async function ensureOrBuildAmpRuntimeInTestMode_() { log( 'fatal', 'The AMP runtime was not built in test mode. Run', - colors.cyan('gulp dist --fortesting'), + colors.cyan('gulp build|dist --fortesting'), 'or remove the', colors.cyan('--nobuild'), 'option from this command' ); } } else { - buildRuntime(); + await buildRuntime(); } } @@ -825,4 +825,5 @@ visualDiff.flags = { ' Disables Percy integration (for testing local changes only)', 'nobuild': ' Skip build', 'noyarn': ' Skip calling yarn to install dependencies', + 'compiled': ' Runs tests against minified JS', }; diff --git a/contributing/TESTING.md b/contributing/TESTING.md index 04a65f5ddce8..928695489748 100644 --- a/contributing/TESTING.md +++ b/contributing/TESTING.md @@ -44,97 +44,101 @@ Before running these commands, make sure you have Node.js, yarn, and Gulp instal **Pro tip:** To see a full listing of `gulp` commands and their flags, run `gulp help`. -| Command | Description | -| --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| **`gulp`** | Starts the dev server, lazily builds JS files and extensions when requested, and watches them for changes. **Use this for development.** | -| `gulp --extensions=amp-foo,amp-bar` | Same as `gulp`. Pre-builds the listed extensions, and lazily builds other files when requested. | -| `gulp --extensions_from=examples/foo.amp.html` | Same as `gulp`. Pre-builds the extensions in the given example file, and lazily builds other files when requested. | -| `gulp --compiled` | Same as `gulp`. Compiles and serves minified binaries. Can be used with `--extensions` and `--extensions_from`. | -| `gulp --version_override=` | Runs "watch" and "serve". Overrides the version written to the AMP_CONFIG. | -| `gulp dist` | Builds minified AMP binaries and applies AMP_CONFIG to runtime files. | -| `gulp dist --watch` | Builds minified AMP binaries and watches them for changes. | -| `gulp dist --noconfig` | Builds minified AMP binaries without applying AMP_CONFIG to runtime files. | -| `gulp dist --extensions=amp-foo,amp-bar` | Builds minified AMP binaries, with only the listed extensions. | -| `gulp dist --extensions_from=examples/foo.amp.html` | Builds minified AMP binaries, with only extensions from the listed examples. | -| `gulp dist --noextensions` | Builds minified AMP binaries without building any extensions. | -| `gulp dist --core_runtime_only` | Builds minified AMP binaries for just the core runtime. | -| `gulp dist --fortesting` | Builds minified AMP binaries for local testing. (Allows use cases like ads, tweets, etc. to work with minified sources. Overrides `TESTING_HOST` if specified. Uses the production `AMP_CONFIG` by default.) | -| `gulp dist --fortesting --config=` | Builds minified AMP binaries for local testing, with the specified `AMP_CONFIG`. `config` can be `prod` or `canary`. (Defaults to `prod`.) | -| `gulp dist --version_override=` | Builds minified AMP binaries and overrides the version written to the AMP_CONFIG. | -| `gulp lint` | Validates JS files against the ESLint linter. | -| `gulp lint --watch` | Watches for changes in files, and validates against the ESLint linter. | -| `gulp lint --fix` | Fixes simple lint warnings/errors automatically. | -| `gulp lint --files=` | Lints just the files provided. Can be used with `--fix`. | -| `gulp lint --local_changes` | Lints just the files changed in the local branch. Can be used with `--fix`. | -| `gulp prettify` | Validates non-JS files using Prettier. | -| `gulp prettify --fix` | Fixes simple formatting errors automatically. | -| `gulp prettify --files=` | Checks just the files provided. Can be used with `--fix`. | -| `gulp prettify --local_changes` | Checks just the files changed in the local branch. Can be used with `--fix`. | -| `gulp build` | Builds unminified AMP binaries. | -| `gulp build --watch` | Builds unminified AMP binaries and watches them for changes. | -| `gulp build --extensions=amp-foo,amp-bar` | Builds unminified AMP binaries, with only the listed extensions. | -| `gulp build --extensions_from=examples/foo.amp.html` | Builds unminified AMP binaries, with only the extensions needed to load the listed examples. | -| `gulp build --noextensions` | Builds unminified AMP binaries with no extensions. | -| `gulp build --core_runtime_only` | Builds unminified AMP binaries for just the core runtime. | -| `gulp build --fortesting` | Builds unminified AMP binaries and sets the `test` field in `AMP_CONFIG` to `true`. | -| `gulp build --version_override=` | Builds unminified AMP binaries with the specified version. | -| `gulp check-links --files=` | Reports dead links in `.md` files. | -| `gulp check-links --local_changes` | Reports dead links in `.md` files changed in the local branch. | -| `gulp clean` | Removes build output. | -| `gulp css` | Recompiles css to the build directory and builds the embedded css into js files for the AMP library. | -| `gulp compile-jison` | Compiles jison parsers for extensions to build directory. | -| `gulp pr-check` | Runs all the Travis CI checks locally. | -| `gulp pr-check --nobuild` | Runs all the Travis CI checks locally, but skips the `gulp build` step. | -| `gulp pr-check --files=` | Runs all the Travis CI checks locally, and restricts tests to the files provided. | -| `gulp unit` | Runs the unit tests in Chrome (doesn't require the AMP library to be built). | -| `gulp unit --local_changes` | Runs the unit tests directly affected by the files changed in the local branch in Chrome. | -| `gulp integration` | Runs the integration tests in Chrome after building the runtime with the `prod` version of `AMP_CONFIG`. | -| `gulp integration --config=` | Same as above, but `config` can be `prod` or `canary`. (Defaults to `prod`.) | -| `gulp [unit\|integration] --verbose` | Runs tests in Chrome with logging enabled. | -| `gulp [unit\|integration] --nobuild` | Runs tests without re-build. | -| `gulp [unit\|integration] --coverage` | Runs code coverage tests. After running, the report will be available at test/coverage/index.html | -| `gulp [unit\|integration] --watch` | Watches for changes in files, runs corresponding test(s) in Chrome. | -| `gulp [unit\|integration] --watch --verbose` | Same as `watch`, with logging enabled. | -| `gulp [unit\|integration] --saucelabs` | Runs tests on saucelabs browsers (requires [setup](#testing-on-sauce-labs)). | -| `gulp [unit\|integration] --safari` | Runs tests in Safari. | -| `gulp [unit\|integration] --firefox` | Runs tests in Firefox. | -| `gulp [unit\|integration] --edge` | Runs tests in Edge. | -| `gulp [unit\|integration] --ie` | Runs tests in Internet Explorer. | -| `gulp [unit\|integration] --files=` | Runs specific test files. | -| `gulp [unit\|integration] --testnames` | Lists the name of each test being run, and prints a summary at the end. | -| `gulp serve` | Serves content from the repository root at http://localhost:8000/. Examples live in http://localhost:8000/examples/. Serves unminified binaries by default. | -| `gulp serve --compiled` | Same as `serve`, but serves minified binaries. | -| `gulp serve --cdn` | Same as `serve`, but serves CDN binaries. | -| `gulp serve --rtv ` | Same as `serve`, but serves binaries with the given 15 digit RTV. | -| `gulp serve --new_server` | Same as `serve`, but uses new Typescript based transforms. _Still under active development._ | -| `gulp serve --new_server --esm` | Same as `serve`, but serves esm (module) binaries. Requires the new Typescript based transforms. _Still under active development._ | -| `gulp serve --quiet` | Same as `serve`, with logging silenced. | -| `gulp serve --port ` | Same as `serve`, but uses a port number other than the default of 8000. | -| `gulp serve --inspect` | Same as `serve`, but runs the server in `node --inspect` mode | -| `gulp check-types` | Verifies that there are no errors associated with Closure typing. Run automatically upon push. | -| `gulp dep-check` | Runs a dependency check on each module. Run automatically upon push. | -| `gulp presubmit` | Run validation against files to check for forbidden and required terms. Run automatically upon push. | -| `gulp validator` | Builds and tests the AMP validator. Run automatically upon push. | -| `gulp ava` | Run node tests for tasks and offline/node code using [ava](https://github.com/avajs/ava). | -| `gulp todos:find-closed` | Find `TODO`s in code for issues that have been closed. | -| `gulp visual-diff` | Runs all visual diff tests on a headless instance of local Chrome after building the runtime with the `prod` version of `AMP_CONFIG`. Requires `PERCY_TOKEN` to be set as an environment variable or passed to the task with `--percy_token`. | -| `gulp visual-diff --config=` | Same as above, but `config` can be `prod` or `canary`. (Defaults to `prod`.) | -| `gulp visual-diff --nobuild` | Same as above, but without re-build. | -| `gulp visual-diff --chrome_debug --webserver_debug` | Same as above, with additional logging. Debug flags can be used independently. | -| `gulp visual-diff --grep=` | Same as above, but executes only those tests whose name matches the regular expression pattern. | -| `gulp firebase` | Generates a folder `firebase` and copies over all files from `examples` and `test/manual` for firebase deployment. | -| `gulp firebase --file path/to/file` | Same as above, but copies over the file specified as `firebase/index.html`. | -| `gulp firebase --min` | Same as `gulp firebase`, but uses minified files of the form `/dist/v0/amp-component-name.js` instead of unminified files of the form `/dist/v0/amp-component-name.max.js`. | -| `gulp firebase --nobuild` | Same as `gulp firebase`, but skips the `gulp build` step. | -| `gulp e2e` | Runs all end-to-end tests on Chrome after building the runtime with the `prod` version of `AMP_CONFIG`.. | -| `gulp e2e --config=` | Same as above, but `config` can be `prod` or `canary`. (Defaults to `prod`.) | -| `gulp e2e --files=` | Runs end-to-end tests from the specified files on the latest Chrome browser. | -| `gulp e2e --nobuild` | Runs all end-to-end tests without building the runtime. | -| `gulp e2e --testnames` | Lists the name of each test being run, and prints a summary at the end. | -| `gulp e2e --engine=ENGINE` | Runs end-to-end tests with the given Web Driver engine. Allowed values are `puppeteer` and `selenium`. | -| `gulp e2e --headless` | Runs end-to-end tests in a headless browser instance. | -| `gulp e2e --watch` | Watches for changes in test files, runs tests. | -| `gulp check-sourcemaps` | Checks sourcemaps generated during minified compilation for correctness. | +| Command | Description | +| --------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **`gulp`** | Starts the dev server, lazily builds JS files and extensions when requested, and watches them for changes. **Use this for development.** | +| `gulp --extensions=amp-foo,amp-bar` | Same as `gulp`. Pre-builds the listed extensions, and lazily builds other files when requested. | +| `gulp --extensions_from=examples/foo.amp.html` | Same as `gulp`. Pre-builds the extensions in the given example file, and lazily builds other files when requested. | +| `gulp --compiled` | Same as `gulp`. Compiles and serves minified binaries. Can be used with `--extensions` and `--extensions_from`. | +| `gulp --version_override=` | Runs "watch" and "serve". Overrides the version written to the AMP_CONFIG. | +| `gulp dist` | Builds minified AMP binaries and applies AMP_CONFIG to runtime files. | +| `gulp dist --watch` | Builds minified AMP binaries and watches them for changes. | +| `gulp dist --noconfig` | Builds minified AMP binaries without applying AMP_CONFIG to runtime files. | +| `gulp dist --extensions=amp-foo,amp-bar` | Builds minified AMP binaries, with only the listed extensions. | +| `gulp dist --extensions_from=examples/foo.amp.html` | Builds minified AMP binaries, with only extensions from the listed examples. | +| `gulp dist --noextensions` | Builds minified AMP binaries without building any extensions. | +| `gulp dist --core_runtime_only` | Builds minified AMP binaries for just the core runtime. | +| `gulp dist --fortesting` | Builds minified AMP binaries for local testing. (Allows use cases like ads, tweets, etc. to work with minified sources. Overrides `TESTING_HOST` if specified. Uses the production `AMP_CONFIG` by default.) | +| `gulp dist --fortesting --config=` | Builds minified AMP binaries for local testing, with the specified `AMP_CONFIG`. `config` can be `prod` or `canary`. (Defaults to `prod`.) | +| `gulp dist --version_override=` | Builds minified AMP binaries and overrides the version written to the AMP_CONFIG. | +| `gulp lint` | Validates JS files against the ESLint linter. | +| `gulp lint --watch` | Watches for changes in files, and validates against the ESLint linter. | +| `gulp lint --fix` | Fixes simple lint warnings/errors automatically. | +| `gulp lint --files=` | Lints just the files provided. Can be used with `--fix`. | +| `gulp lint --local_changes` | Lints just the files changed in the local branch. Can be used with `--fix`. | +| `gulp prettify` | Validates non-JS files using Prettier. | +| `gulp prettify --fix` | Fixes simple formatting errors automatically. | +| `gulp prettify --files=` | Checks just the files provided. Can be used with `--fix`. | +| `gulp prettify --local_changes` | Checks just the files changed in the local branch. Can be used with `--fix`. | +| `gulp build` | Builds unminified AMP binaries. | +| `gulp build --watch` | Builds unminified AMP binaries and watches them for changes. | +| `gulp build --extensions=amp-foo,amp-bar` | Builds unminified AMP binaries, with only the listed extensions. | +| `gulp build --extensions_from=examples/foo.amp.html` | Builds unminified AMP binaries, with only the extensions needed to load the listed examples. | +| `gulp build --noextensions` | Builds unminified AMP binaries with no extensions. | +| `gulp build --core_runtime_only` | Builds unminified AMP binaries for just the core runtime. | +| `gulp build --fortesting` | Builds unminified AMP binaries and sets the `test` field in `AMP_CONFIG` to `true`. | +| `gulp build --version_override=` | Builds unminified AMP binaries with the specified version. | +| `gulp check-links --files=` | Reports dead links in `.md` files. | +| `gulp check-links --local_changes` | Reports dead links in `.md` files changed in the local branch. | +| `gulp clean` | Removes build output. | +| `gulp css` | Recompiles css to the build directory and builds the embedded css into js files for the AMP library. | +| `gulp compile-jison` | Compiles jison parsers for extensions to build directory. | +| `gulp pr-check` | Runs all the Travis CI checks locally. | +| `gulp pr-check --nobuild` | Runs all the Travis CI checks locally, but skips the `gulp build` step. | +| `gulp pr-check --files=` | Runs all the Travis CI checks locally, and restricts tests to the files provided. | +| `gulp unit` | Runs the unit tests in Chrome (doesn't require the AMP library to be built). | +| `gulp unit --local_changes` | Runs the unit tests directly affected by the files changed in the local branch in Chrome. | +| `gulp integration` | Runs the integration tests in Chrome after building the unminified runtime with the `prod` version of `AMP_CONFIG`. | +| `gulp integration --compiled` | Same as above, but builds the minified runtime. | +| `gulp integration --config=` | Same as above, but `config` can be `prod` or `canary`. (Defaults to `prod`.) | +| `gulp integration --nobuild` | Same as above, but skips building the runtime. | +| `gulp [unit\|integration] --verbose` | Runs tests in Chrome with logging enabled. | +| `gulp [unit\|integration] --nobuild` | Runs tests without re-build. | +| `gulp [unit\|integration] --coverage` | Runs code coverage tests. After running, the report will be available at test/coverage/index.html | +| `gulp [unit\|integration] --watch` | Watches for changes in files, runs corresponding test(s) in Chrome. | +| `gulp [unit\|integration] --watch --verbose` | Same as `watch`, with logging enabled. | +| `gulp [unit\|integration] --saucelabs` | Runs tests on saucelabs browsers (requires [setup](#testing-on-sauce-labs)). | +| `gulp [unit\|integration] --safari` | Runs tests in Safari. | +| `gulp [unit\|integration] --firefox` | Runs tests in Firefox. | +| `gulp [unit\|integration] --edge` | Runs tests in Edge. | +| `gulp [unit\|integration] --ie` | Runs tests in Internet Explorer. | +| `gulp [unit\|integration] --files=` | Runs specific test files. | +| `gulp [unit\|integration] --testnames` | Lists the name of each test being run, and prints a summary at the end. | +| `gulp serve` | Serves content from the repository root at http://localhost:8000/. Examples live in http://localhost:8000/examples/. Serves unminified binaries by default. | +| `gulp serve --compiled` | Same as `serve`, but serves minified binaries. | +| `gulp serve --cdn` | Same as `serve`, but serves CDN binaries. | +| `gulp serve --rtv ` | Same as `serve`, but serves binaries with the given 15 digit RTV. | +| `gulp serve --new_server` | Same as `serve`, but uses new Typescript based transforms. _Still under active development._ | +| `gulp serve --new_server --esm` | Same as `serve`, but serves esm (module) binaries. Requires the new Typescript based transforms. _Still under active development._ | +| `gulp serve --quiet` | Same as `serve`, with logging silenced. | +| `gulp serve --port ` | Same as `serve`, but uses a port number other than the default of 8000. | +| `gulp serve --inspect` | Same as `serve`, but runs the server in `node --inspect` mode | +| `gulp check-types` | Verifies that there are no errors associated with Closure typing. Run automatically upon push. | +| `gulp dep-check` | Runs a dependency check on each module. Run automatically upon push. | +| `gulp presubmit` | Run validation against files to check for forbidden and required terms. Run automatically upon push. | +| `gulp validator` | Builds and tests the AMP validator. Run automatically upon push. | +| `gulp ava` | Run node tests for tasks and offline/node code using [ava](https://github.com/avajs/ava). | +| `gulp todos:find-closed` | Find `TODO`s in code for issues that have been closed. | +| `gulp visual-diff` | Runs all visual diff tests on a headless instance of local Chrome after building the unminified runtime with the `prod` version of `AMP_CONFIG`. Requires `PERCY_TOKEN` to be set as an environment variable or passed to the task with `--percy_token`. | +| `gulp visual-diff --compiled` | Same as above, but builds the minified runtime. | +| `gulp visual-diff --config=` | Same as above, but `config` can be `prod` or `canary`. (Defaults to `prod`.) | +| `gulp visual-diff --nobuild` | Same as above, but skips building the runtime. | +| `gulp visual-diff --chrome_debug --webserver_debug` | Same as above, with additional logging. Debug flags can be used independently. | +| `gulp visual-diff --grep=` | Same as above, but executes only those tests whose name matches the regular expression pattern. | +| `gulp firebase` | Generates a folder `firebase` and copies over all files from `examples` and `test/manual` for firebase deployment. | +| `gulp firebase --file path/to/file` | Same as above, but copies over the file specified as `firebase/index.html`. | +| `gulp firebase --compiled` | Same as `gulp firebase`, but uses minified files of the form `/dist/v0/amp-component-name.js` instead of unminified files of the form `/dist/v0/amp-component-name.max.js`. | +| `gulp firebase --nobuild` | Same as `gulp firebase`, but skips building the runtime. | +| `gulp e2e` | Runs all end-to-end tests on Chrome after building the unminified runtime with the `prod` version of `AMP_CONFIG`.. | +| `gulp e2e --compiled` | Same as above, but builds the minified runtime. . | +| `gulp e2e --config=` | Same as above, but `config` can be `prod` or `canary`. (Defaults to `prod`.) | +| `gulp e2e --nobuild` | Same as above, but skips building the runtime. | +| `gulp e2e --files=` | Runs end-to-end tests from the specified files on the latest Chrome browser. | +| `gulp e2e --testnames` | Lists the name of each test being run, and prints a summary at the end. | +| `gulp e2e --engine=ENGINE` | Runs end-to-end tests with the given Web Driver engine. Allowed values are `puppeteer` and `selenium`. | +| `gulp e2e --headless` | Runs end-to-end tests in a headless browser instance. | +| `gulp e2e --watch` | Watches for changes in test files, runs tests. | +| `gulp check-sourcemaps` | Checks sourcemaps generated during minified compilation for correctness. | ## Manual testing @@ -286,19 +290,21 @@ export PERCY_TOKEN="" Once the environment variable is set up, you can run the AMP visual diff tests. -First, build the AMP runtime: +First, build the AMP runtime in minified or unminified mode: ```sh -gulp dist --fortesting +gulp build --fortesting # unminified mode +gulp dist --fortesting # minified mode ``` Next, run the `gulp` task that invokes the visual diff tests: ```sh -gulp visual-diff --nobuild +gulp visual-diff --nobuild # unminified mode +gulp visual-diff --compiled --nobuild # minified mode ``` -Note that if you drop the `--nobuild` flag, `gulp visual-diff` will run `gulp dist --fortesting` on each execution. +Note that if you drop the `--nobuild` flag, `gulp visual-diff` will run `gulp dist|build --fortesting` on each execution. The build will use the Percy credentials set via environment variables in the previous step, and run the tests on your local install of Chrome in headless mode. You can see the results at `https://percy.io//`.