diff --git a/.eslintrc.js b/.eslintrc.js index e89bea66d..7b2779f08 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -32,5 +32,6 @@ module.exports = { rules: { 'no-debugger': 0, 'no-console': 0, + 'testing-library/no-debugging-utils': 0, }, }; diff --git a/.github/workflows/audit_and_lint.yml b/.github/workflows/audit_and_lint.yml index e350f04f0..722efa06f 100644 --- a/.github/workflows/audit_and_lint.yml +++ b/.github/workflows/audit_and_lint.yml @@ -76,7 +76,7 @@ jobs: if: always() && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/dev' || github.event_name == 'pull_request') - uses: github/codeql-action/upload-sarif@e0e5ded33cabb451ae0a9768fc7b0410bad9ad44 # pin@codeql-bundle-20210517 + uses: github/codeql-action/upload-sarif@807578363a7869ca324a79039e6db9c843e0e100 # pin@codeql-bundle-20210517 with: sarif_file: lint-results.sarif continue-on-error: true diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 9db8032bd..b320cfb33 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -17,10 +17,10 @@ jobs: uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # pin@v2 - name: Initialize CodeQL - uses: github/codeql-action/init@e0e5ded33cabb451ae0a9768fc7b0410bad9ad44 + uses: github/codeql-action/init@807578363a7869ca324a79039e6db9c843e0e100 with: queries: security-and-quality languages: javascript - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@e0e5ded33cabb451ae0a9768fc7b0410bad9ad44 + uses: github/codeql-action/analyze@807578363a7869ca324a79039e6db9c843e0e100 diff --git a/README.md b/README.md index c8aa6ad2d..8ef739f91 100644 --- a/README.md +++ b/README.md @@ -225,7 +225,7 @@ use `STABLE_MODE=true` (which will introduce delays only between main actions, 300ms by default) / `STABLE_MODE=` or `SLOW_MODE=true` (which will introduce delay between every action, 50ms by default) / `SLOW_MODE=`. -`SYNDEBUG=1` is very useful while debugging your tests. It enables following +`DEBUG=synpress:*` is very useful while debugging your tests. It enables following features: - improved logging diff --git a/helpers.js b/helpers.js index c4fc88746..93c0c9660 100644 --- a/helpers.js +++ b/helpers.js @@ -1,3 +1,4 @@ +const log = require('debug')('synpress:helpers'); const axios = require('axios'); const fs = require('fs').promises; const path = require('path'); @@ -10,6 +11,10 @@ let isTestnet = false; module.exports = { setNetwork: network => { + typeof network === 'object' + ? log(`Setting network to ${JSON.stringify(network)}`) + : log(`Setting network to ${network}`); + if (network === 'mainnet') { networkName = 'mainnet'; networkId = 1; @@ -38,7 +43,9 @@ module.exports = { // todo: handle a case when setNetwork() is triggered by changeNetwork() with a string of already added custom networks }, getNetwork: () => { - return { networkName, networkId, isTestnet }; + const networkData = { networkName, networkId, isTestnet }; + log(`Current network data: ${networkData}`); + return networkData; }, getSynpressPath: () => { if (process.env.SYNPRESS_LOCAL_TEST) { @@ -49,23 +56,29 @@ module.exports = { }, createDirIfNotExist: async path => { try { + log(`Checking if directory exists on path: ${path}`); await fs.access(path); + return true; } catch (e) { if (e.code === 'ENOENT') { + log(`Creating directory as it doesn't exist..`); await fs.mkdir(path); + return true; } else { throw new Error( - `[prepareMetamask] Unhandled error from fs.access() with following error:\n${e}`, + `[createDirIfNotExist] Unhandled error from fs.access() with following error:\n${e}`, ); } } }, checkDirOrFileExist: async path => { try { + log(`Checking if directory exists on path: ${path}`); await fs.access(path); return true; } catch (e) { if (e.code === 'ENOENT') { + log(`Directory or file doesn't exist`); return false; } else { throw new Error( @@ -75,6 +88,7 @@ module.exports = { } }, getMetamaskReleases: async version => { + log(`Trying to find metamask version ${version} in GitHub releases..`); let filename; let downloadUrl; let tagName; @@ -87,10 +101,16 @@ module.exports = { filename = response.data[0].assets[0].name; downloadUrl = response.data[0].assets[0].browser_download_url; tagName = response.data[0].tag_name; + log( + `Metamask version found! Filename: ${filename}; Download url: ${downloadUrl}; Tag name: ${tagName}`, + ); } else if (version) { filename = `metamask-chrome-${version}.zip`; downloadUrl = `https://github.com/MetaMask/metamask-extension/releases/download/v${version}/metamask-chrome-${version}.zip`; tagName = `metamask-chrome-${version}`; + log( + `Metamask version found! Filename: ${filename}; Download url: ${downloadUrl}; Tag name: ${tagName}`, + ); } return { filename, @@ -105,6 +125,9 @@ module.exports = { }, download: async (url, destination) => { try { + log( + `Trying to download and extract file from: ${url} to following path: ${destination}`, + ); await download(url, destination, { extract: true }); } catch (e) { throw new Error( @@ -130,6 +153,8 @@ module.exports = { ); if (!metamaskDirectoryExists && !metamaskManifestFileExists) { await module.exports.download(release.downloadUrl, metamaskDirectory); + } else { + log('Metamask is already downloaded'); } return metamaskDirectory; }, diff --git a/launcher.js b/launcher.js index 241620882..b991e54ee 100644 --- a/launcher.js +++ b/launcher.js @@ -1,6 +1,8 @@ +const log = require('debug')('synpress:launcher'); const cypress = require('cypress'); const helpers = require('./helpers'); const synpressConfigPath = `${helpers.getSynpressPath()}/synpress.config.js`; +log(`Detected synpress config path is: ${synpressConfigPath}`); process.env.CYPRESS_REMOTE_DEBUGGING_PORT = 9222; @@ -23,54 +25,90 @@ const launcher = { }, async run(arguments_) { if (arguments_.configFile) { + log(`Custom config file arg detected: ${arguments_.configFile}`); defaultArguments.push(`--config-file=${arguments_.configFile}`); } else { + log('Using default config file'); defaultArguments.push(`--config-file=${synpressConfigPath}`); } + log(`Tests will run on ${arguments_.browser} browser`); defaultArguments.push(`--browser=${arguments_.browser}`); + if (arguments_.component) { + log(`component arg enabled`); + defaultArguments.push('--component'); + } if (arguments_.config) { + log(`Custom config arg detected: ${defaultConfig},${arguments_.config}`); defaultArguments.push(`--config=${defaultConfig},${arguments_.config}`); } else { + log(`Using default config: ${defaultConfig}`); defaultArguments.push(`--config=${defaultConfig}`); } + if (arguments_.e2e) { + log(`e2e arg enabled`); + defaultArguments.push('--e2e'); + } if (arguments_.env) { + log(`Custom env arg detected: ${arguments_.env}`); defaultArguments.push(`--env=${arguments_.env}`); } if (arguments_.spec) { + log(`Custom spec arg detected: ${arguments_.spec}`); defaultArguments.push(`--spec=${arguments_.spec}`); } if (arguments_.noExit) { + log(`noExit arg enabled`); defaultArguments.push('--no-exit'); } + if (arguments_.port) { + log(`Custom port arg detected: ${arguments_.port}`); + defaultArguments.push(`--port=${arguments_.port}`); + } if (arguments_.project) { + log(`Custom project arg detected: ${arguments_.project}`); defaultArguments.push(`--project=${arguments_.project}`); } if (arguments_.quiet) { + log(`quiet arg enabled`); defaultArguments.push('--quiet'); } if (arguments_.reporter) { + log(`Custom reporter arg detected: ${arguments_.reporter}`); defaultArguments.push(`--reporter=${arguments_.reporter}`); } if (arguments_.reporterOptions) { + log(`Custom reporterOptions arg detected: ${arguments_.reporterOptions}`); defaultArguments.push(`--reporter-options=${arguments_.reporterOptions}`); } + if (arguments_.ciBuildId) { + log(`Custom ciBuildId arg detected: ${arguments_.ciBuildId}`); + defaultArguments.push(`--ci-build-id=${arguments_.ciBuildId}`); + } if (arguments_.record) { + log(`record arg enabled`); defaultArguments.push('--record'); } if (arguments_.key) { + log(`Custom key arg detected: ${arguments_.key}`); defaultArguments.push(`--key=${arguments_.key}`); } if (arguments_.parallel) { + log(`parallel arg enabled`); defaultArguments.push('--parallel'); } if (arguments_.group) { + log(`Custom group arg detected: ${arguments_.group}`); defaultArguments.push(`--group=${arguments_.group}`); } if (arguments_.tag) { + log(`Custom tag arg detected: ${arguments_.tag}`); defaultArguments.push(`--tag=${arguments_.tag}`); } const runOptions = await cypress.cli.parseRunArguments(defaultArguments); + log( + `Running synpress with following options: ${JSON.stringify(runOptions)}`, + ); const results = await cypress.run(runOptions); if (results.failures) { console.error('Failed to run Cypress'); diff --git a/package.json b/package.json index b6e34bc58..d2dfaea2d 100644 --- a/package.json +++ b/package.json @@ -63,6 +63,7 @@ "commander": "^9.4.1", "cypress": "^10.9.0", "cypress-wait-until": "^1.7.2", + "debug": "^4.3.4", "dotenv": "^16.0.3", "dotenv-parse-variables": "^2.0.0", "download": "^8.0.0", diff --git a/synpress.config.js b/synpress.config.js index ffd585084..7537730b6 100644 --- a/synpress.config.js +++ b/synpress.config.js @@ -1,8 +1,14 @@ +const log = require('debug')('synpress:config'); const path = require('path'); const packageJson = require('./package.json'); const { defineConfig } = require('cypress'); -const setupNodeEvents = require(`${getSynpressPath()}/plugins/index`); -const fixturesFolder = `${getSynpressPath()}/fixtures`; +const synpressPath = getSynpressPath(); +log(`Detected synpress root path is: ${synpressPath}`); +const pluginsPath = `${synpressPath}/plugins/index`; +log(`Detected synpress plugin path is: ${pluginsPath}`); +const setupNodeEvents = require(pluginsPath); +const fixturesFolder = `${synpressPath}/fixtures`; +log(`Detected synpress fixtures path is: ${fixturesFolder}`); const supportFile = 'tests/e2e/support.js'; module.exports = defineConfig({ diff --git a/synpress.js b/synpress.js index 5237f3786..4cf94e44a 100644 --- a/synpress.js +++ b/synpress.js @@ -1,23 +1,28 @@ #!/usr/bin/env node - +const log = require('debug')('synpress:cli'); const program = require('commander'); const { run, open } = require('./launcher'); const { version } = require('./package.json'); -if (process.env.SYNPRESS_LOCAL_TEST) { - require('dotenv').config(); -} else { - require('dotenv').config({ path: require('find-config')('.env') }); -} - -if (process.env.SYNDEBUG) { +if (process.env.DEBUG && process.env.DEBUG.includes('synpress')) { + log('SYNDEBUG mode is enabled'); process.env.PWDEBUG = 1; - // process.env.DEBUG = 'cypress:*'; if (!process.env.STABLE_MODE) { + log('Enabling stable mode'); process.env.STABLE_MODE = true; } } +if (process.env.SYNPRESS_LOCAL_TEST) { + log('Loading .env config file from root folder'); + require('dotenv').config(); +} else { + log( + 'Loading .env config file from first matching config file - root dir, ancestor or home dir', + ); + require('dotenv').config({ path: require('find-config')('.env') }); +} + if ( !process.env.SECRET_WORDS && !process.env.PRIVATE_KEY && @@ -45,15 +50,14 @@ if (process.env.RPC_URL || process.env.CHAIN_ID) { ); } - if (process.env.BLOCK_EXPLORER) { - if ( - !process.env.BLOCK_EXPLORER.startsWith('http://') && //DevSkim: ignore DS137138 - !process.env.BLOCK_EXPLORER.startsWith('https://') - ) { - throw new Error( - 'BLOCK_EXPLORER environment variable should start with "http://" or "https://"', //DevSkim: ignore DS137138 - ); - } + if ( + process.env.BLOCK_EXPLORER && + !process.env.BLOCK_EXPLORER.startsWith('http://') && //DevSkim: ignore DS137138 + !process.env.BLOCK_EXPLORER.startsWith('https://') + ) { + throw new Error( + 'BLOCK_EXPLORER environment variable should start with "http://" or "https://"', //DevSkim: ignore DS137138 + ); } } @@ -62,6 +66,7 @@ program.version(version, '-v, --version'); program .command('run') .requiredOption('-b, --browser ', 'run on specified browser', 'chrome') + .option('-cmp, --component', 'run component tests') .option( '-c, --config ', 'set configuration values, separate multiple values with a comma', @@ -70,12 +75,14 @@ program '-cf, --configFile ', 'specify a path to a JSON file where configuration values are set', ) + .option('--e2e', 'run e2e tests (already set as default)') .option( '-e, --env ', 'set environment variables, separate multiple values with comma', ) .option('-s, --spec ', 'run only provided spec files') .option('-ne, --noExit', 'keep runner open after tests finish') + .option('-pt, --port ', 'override default port') .option('-pr, --project ', 'run with specific project path') .option('-q, --quiet', 'only test runner output in console') .option('-r, --reporter ', 'specify mocha reporter') @@ -84,6 +91,7 @@ program 'specify mocha reporter options, separate multiple values with comma', ) // dashboard + .option('-cid, --ciBuildId', '[dashboard] add custom ci build id to the run') .option( '-r, --record', '[dashboard] record video of tests running after setting up your project to record', @@ -102,15 +110,19 @@ program .action(options => { run({ browser: options.browser, + component: options.component, config: options.config, configFile: options.configFile, + e2e: options.e2e, env: options.env, spec: options.spec, noExit: options.noExit, + port: options.port, project: options.project, quiet: options.quiet, reporter: options.reporter, reporterOptions: options.reporterOptions, + ciBuildId: options.ciBuildId, record: options.record, key: options.key, parallel: options.parallel,