Best JavaScript code snippet using ava
watcher.js
Source:watcher.js
1'use strict';2const nodePath = require('path');3const debug = require('debug')('ava:watcher');4const chokidar = require('chokidar');5const diff = require('lodash/difference');6const flatten = require('lodash/flatten');7const chalk = require('./chalk').get();8const {applyTestFileFilter, classify, getChokidarIgnorePatterns} = require('./globs');9const {levels: providerLevels} = require('./provider-manager');10function rethrowAsync(error) {11 // Don't swallow exceptions. Note that any12 // expected error should already have been logged13 setImmediate(() => {14 throw error;15 });16}17const MIN_DEBOUNCE_DELAY = 10;18const INITIAL_DEBOUNCE_DELAY = 100;19const END_MESSAGE = chalk.gray('Type `r` and press enter to rerun tests\nType `u` and press enter to update snapshots\n');20class Debouncer {21 constructor(watcher) {22 this.watcher = watcher;23 this.timer = null;24 this.repeat = false;25 }26 debounce(delay) {27 if (this.timer) {28 this.again = true;29 return;30 }31 delay = delay ? Math.max(delay, MIN_DEBOUNCE_DELAY) : INITIAL_DEBOUNCE_DELAY;32 const timer = setTimeout(async () => {33 await this.watcher.busy;34 // Do nothing if debouncing was canceled while waiting for the busy35 // promise to fulfil36 if (this.timer !== timer) {37 return;38 }39 if (this.again) {40 this.timer = null;41 this.again = false;42 this.debounce(delay / 2);43 } else {44 this.watcher.runAfterChanges();45 this.timer = null;46 this.again = false;47 }48 }, delay);49 this.timer = timer;50 }51 cancel() {52 if (this.timer) {53 clearTimeout(this.timer);54 this.timer = null;55 this.again = false;56 }57 }58}59class TestDependency {60 constructor(file, dependencies) {61 this.file = file;62 this.dependencies = dependencies;63 }64 contains(dependency) {65 return this.dependencies.includes(dependency);66 }67}68class Watcher {69 constructor({api, filter = [], globs, projectDir, providers, reporter}) {70 this.debouncer = new Debouncer(this);71 this.clearLogOnNextRun = true;72 this.runVector = 0;73 this.previousFiles = [];74 this.globs = {cwd: projectDir, ...globs};75 const patternFilters = filter.map(({pattern}) => pattern);76 this.providers = providers.filter(({level}) => level >= providerLevels.pathRewrites);77 this.run = (specificFiles = [], updateSnapshots = false) => {78 const clearLogOnNextRun = this.clearLogOnNextRun && this.runVector > 0;79 if (this.runVector > 0) {80 this.clearLogOnNextRun = true;81 }82 this.runVector++;83 let runOnlyExclusive = false;84 if (specificFiles.length > 0) {85 const exclusiveFiles = specificFiles.filter(file => this.filesWithExclusiveTests.includes(file));86 runOnlyExclusive = exclusiveFiles.length !== this.filesWithExclusiveTests.length;87 if (runOnlyExclusive) {88 // The test files that previously contained exclusive tests are always89 // run, together with the remaining specific files.90 const remainingFiles = diff(specificFiles, exclusiveFiles);91 specificFiles = this.filesWithExclusiveTests.concat(remainingFiles);92 }93 if (filter.length > 0) {94 specificFiles = applyTestFileFilter({cwd: projectDir, filter: patternFilters, testFiles: specificFiles});95 }96 this.pruneFailures(specificFiles);97 }98 this.touchedFiles.clear();99 this.previousFiles = specificFiles;100 this.busy = api.run({101 files: specificFiles,102 filter,103 runtimeOptions: {104 clearLogOnNextRun,105 previousFailures: this.sumPreviousFailures(this.runVector),106 runOnlyExclusive,107 runVector: this.runVector,108 updateSnapshots: updateSnapshots === true109 }110 })111 .then(runStatus => { // eslint-disable-line promise/prefer-await-to-then112 reporter.endRun();113 reporter.lineWriter.writeLine(END_MESSAGE);114 if (this.clearLogOnNextRun && (115 runStatus.stats.failedHooks > 0 ||116 runStatus.stats.failedTests > 0 ||117 runStatus.stats.failedWorkers > 0 ||118 runStatus.stats.internalErrors > 0 ||119 runStatus.stats.timeouts > 0 ||120 runStatus.stats.uncaughtExceptions > 0 ||121 runStatus.stats.unhandledRejections > 0122 )) {123 this.clearLogOnNextRun = false;124 }125 })126 .catch(rethrowAsync);127 };128 this.testDependencies = [];129 this.trackTestDependencies(api);130 this.touchedFiles = new Set();131 this.trackTouchedFiles(api);132 this.filesWithExclusiveTests = [];133 this.trackExclusivity(api);134 this.filesWithFailures = [];135 this.trackFailures(api);136 this.dirtyStates = {};137 this.watchFiles();138 this.rerunAll();139 }140 watchFiles() {141 chokidar.watch(['**/*'], {142 cwd: this.globs.cwd,143 ignored: getChokidarIgnorePatterns(this.globs),144 ignoreInitial: true145 }).on('all', (event, path) => {146 if (event === 'add' || event === 'change' || event === 'unlink') {147 debug('Detected %s of %s', event, path);148 this.dirtyStates[nodePath.join(this.globs.cwd, path)] = event;149 this.debouncer.debounce();150 }151 });152 }153 trackTestDependencies(api) {154 api.on('run', plan => {155 plan.status.on('stateChange', evt => {156 if (evt.type !== 'dependencies') {157 return;158 }159 const dependencies = evt.dependencies.filter(filePath => {160 const {isIgnoredByWatcher} = classify(filePath, this.globs);161 return !isIgnoredByWatcher;162 });163 this.updateTestDependencies(evt.testFile, dependencies);164 });165 });166 }167 updateTestDependencies(file, dependencies) {168 // Ensure the rewritten test file path is included in the dependencies,169 // since changes to non-rewritten paths are ignored.170 for (const {main} of this.providers) {171 const rewritten = main.resolveTestFile(file);172 if (!dependencies.includes(rewritten)) {173 dependencies = [rewritten, ...dependencies];174 }175 }176 if (dependencies.length === 0) {177 this.testDependencies = this.testDependencies.filter(dep => dep.file !== file);178 return;179 }180 const isUpdate = this.testDependencies.some(dep => {181 if (dep.file !== file) {182 return false;183 }184 dep.dependencies = dependencies;185 return true;186 });187 if (!isUpdate) {188 this.testDependencies.push(new TestDependency(file, dependencies));189 }190 }191 trackTouchedFiles(api) {192 api.on('run', plan => {193 plan.status.on('stateChange', evt => {194 if (evt.type !== 'touched-files') {195 return;196 }197 for (const file of evt.files) {198 this.touchedFiles.add(file);199 }200 });201 });202 }203 trackExclusivity(api) {204 api.on('run', plan => {205 plan.status.on('stateChange', evt => {206 if (evt.type !== 'worker-finished') {207 return;208 }209 const fileStats = plan.status.stats.byFile.get(evt.testFile);210 const ranExclusiveTests = fileStats.selectedTests > 0 && fileStats.declaredTests > fileStats.selectedTests;211 this.updateExclusivity(evt.testFile, ranExclusiveTests);212 });213 });214 }215 updateExclusivity(file, hasExclusiveTests) {216 const index = this.filesWithExclusiveTests.indexOf(file);217 if (hasExclusiveTests && index === -1) {218 this.filesWithExclusiveTests.push(file);219 } else if (!hasExclusiveTests && index !== -1) {220 this.filesWithExclusiveTests.splice(index, 1);221 }222 }223 trackFailures(api) {224 api.on('run', plan => {225 this.pruneFailures(plan.files);226 const currentVector = this.runVector;227 plan.status.on('stateChange', evt => {228 if (!evt.testFile) {229 return;230 }231 switch (evt.type) {232 case 'hook-failed':233 case 'internal-error':234 case 'test-failed':235 case 'uncaught-exception':236 case 'unhandled-rejection':237 case 'worker-failed':238 this.countFailure(evt.testFile, currentVector);239 break;240 default:241 break;242 }243 });244 });245 }246 pruneFailures(files) {247 const toPrune = new Set(files);248 this.filesWithFailures = this.filesWithFailures.filter(state => !toPrune.has(state.file));249 }250 countFailure(file, vector) {251 const isUpdate = this.filesWithFailures.some(state => {252 if (state.file !== file) {253 return false;254 }255 state.count++;256 return true;257 });258 if (!isUpdate) {259 this.filesWithFailures.push({260 file,261 vector,262 count: 1263 });264 }265 }266 sumPreviousFailures(beforeVector) {267 let total = 0;268 for (const state of this.filesWithFailures) {269 if (state.vector < beforeVector) {270 total += state.count;271 }272 }273 return total;274 }275 cleanUnlinkedTests(unlinkedTests) {276 for (const testFile of unlinkedTests) {277 this.updateTestDependencies(testFile, []);278 this.updateExclusivity(testFile, false);279 this.pruneFailures([testFile]);280 }281 }282 observeStdin(stdin) {283 stdin.resume();284 stdin.setEncoding('utf8');285 stdin.on('data', async data => {286 data = data.trim().toLowerCase();287 if (data !== 'r' && data !== 'rs' && data !== 'u') {288 return;289 }290 // Cancel the debouncer, it might rerun specific tests whereas *all* tests291 // need to be rerun292 this.debouncer.cancel();293 await this.busy;294 // Cancel the debouncer again, it might have restarted while waiting for295 // the busy promise to fulfil296 this.debouncer.cancel();297 this.clearLogOnNextRun = false;298 if (data === 'u') {299 this.updatePreviousSnapshots();300 } else {301 this.rerunAll();302 }303 });304 }305 rerunAll() {306 this.dirtyStates = {};307 this.run();308 }309 updatePreviousSnapshots() {310 this.dirtyStates = {};311 this.run(this.previousFiles, true);312 }313 runAfterChanges() {314 const {dirtyStates} = this;315 this.dirtyStates = {};316 let dirtyPaths = Object.keys(dirtyStates).filter(path => {317 if (this.touchedFiles.has(path)) {318 debug('Ignoring known touched file %s', path);319 this.touchedFiles.delete(path);320 return false;321 }322 return true;323 });324 for (const {main} of this.providers) {325 dirtyPaths = dirtyPaths.filter(path => {326 if (main.ignoreChange(path)) {327 debug('Ignoring changed file %s', path);328 return false;329 }330 return true;331 });332 }333 const dirtyHelpersAndSources = [];334 const dirtyTests = [];335 for (const filePath of dirtyPaths) {336 const {isIgnoredByWatcher, isTest} = classify(filePath, this.globs);337 if (!isIgnoredByWatcher) {338 if (isTest) {339 dirtyTests.push(filePath);340 } else {341 dirtyHelpersAndSources.push(filePath);342 }343 }344 }345 const addedOrChangedTests = dirtyTests.filter(path => dirtyStates[path] !== 'unlink');346 const unlinkedTests = diff(dirtyTests, addedOrChangedTests);347 this.cleanUnlinkedTests(unlinkedTests);348 // No need to rerun tests if the only change is that tests were deleted349 if (unlinkedTests.length === dirtyPaths.length) {350 return;351 }352 if (dirtyHelpersAndSources.length === 0) {353 // Run any new or changed tests354 this.run(addedOrChangedTests);355 return;356 }357 // Try to find tests that depend on the changed source files358 const testsByHelpersOrSource = dirtyHelpersAndSources.map(path => {359 return this.testDependencies.filter(dep => dep.contains(path)).map(dep => {360 debug('%s is a dependency of %s', path, dep.file);361 return dep.file;362 });363 }, this).filter(tests => tests.length > 0);364 // Rerun all tests if source files were changed that could not be traced to365 // specific tests366 if (testsByHelpersOrSource.length !== dirtyHelpersAndSources.length) {367 debug('Files remain that cannot be traced to specific tests: %O', dirtyHelpersAndSources);368 debug('Rerunning all tests');369 this.run();370 return;371 }372 // Run all affected tests373 this.run([...new Set(addedOrChangedTests.concat(flatten(testsByHelpersOrSource)))]);374 }375}...
globs.js
Source:globs.js
...177 const options = {178 ...globs.normalizeGlobs({extensions: ['js'], providers: []}),179 cwd: fixture()180 };181 function isIgnoredByWatcher(file) {182 t.true(globs.classify(fixture(file), options).isIgnoredByWatcher, `${file} should be ignored`);183 }184 function notIgnored(file) {185 t.false(globs.classify(fixture(file), options).isIgnoredByWatcher, `${file} should not be ignored`);186 }187 notIgnored('foo-bar.js');188 notIgnored('foo.js');189 notIgnored('foo/blah.js');190 notIgnored('bar/foo.js');191 notIgnored('_foo-bar.js');192 notIgnored('foo/_foo-bar.js');193 notIgnored('fixtures/foo.js');194 notIgnored('helpers/foo.js');195 notIgnored('snapshots/foo.js.snap');196 isIgnoredByWatcher('snapshots/foo.js.snap.md');197 notIgnored('foo-bar.json');198 notIgnored('foo-bar.coffee');199 notIgnored('bar.js');200 notIgnored('bar/bar.js');201 isIgnoredByWatcher('node_modules/foo.js');202 t.end();203});204test('isIgnoredByWatcher with patterns', t => {205 const options = {206 ...globs.normalizeGlobs({207 files: ['**/foo*'],208 ignoredByWatcher: ['**/bar*'],209 extensions: ['js'],210 providers: []211 }),212 cwd: fixture()213 };214 t.true(globs.classify(fixture('node_modules/foo/foo.js'), options).isIgnoredByWatcher);215 t.true(globs.classify(fixture('bar.js'), options).isIgnoredByWatcher);...
Using AI Code Generation
1const test = require('ava')2const isIgnoredByWatcher = require('ava/lib/watcher').isIgnoredByWatcher3test('isIgnoredByWatcher', t => {4 t.true(isIgnoredByWatcher('test.js'))5 t.true(isIgnoredByWatcher('test-foo.js'))6 t.true(isIgnoredByWatcher('test/foo.js'))7 t.true(isIgnoredByWatcher('test/foo/bar.js'))8 t.true(isIgnoredByWatcher('test/foo/bar/test.js'))9 t.true(isIgnoredByWatcher('test/foo/bar/test-foo.js'))10 t.true(isIgnoredByWatcher('test/foo/bar/test-foo/bar.js'))11 t.true(isIgnoredByWatcher('test/foo/bar/test-foo/bar/test.js'))12 t.true(isIgnoredByWatcher('test/foo/bar/test-foo/bar/test-foo.js'))13 t.true(isIgnoredByWatcher('test/foo/bar/test-foo/bar/test-foo/bar.js'))14 t.true(isIgnoredByWatcher('test/foo/bar/test-foo/bar/test-foo/bar/test.js'))15 t.true(isIgnoredByWatcher('test/foo/bar/test-foo/bar/test-foo/bar/test-foo.js'))16 t.true(isIgnoredByWatcher('test/foo/bar/test-foo/bar/test-foo/bar/test-foo/bar.js'))17 t.true(isIgnoredByWatcher('test/foo/bar/test-foo/bar/test-foo/bar/test-foo/bar/test.js'))18 t.true(isIgnoredByWatcher('test/foo/bar/test-foo/bar/test-foo/bar/test-foo/bar/test-foo.js'))19 t.true(isIgnoredByWatcher('test/foo/bar/test-foo/bar/test-foo/bar/test-foo/bar/test-foo/bar.js'))20 t.true(isIgnoredByWatcher('test/foo/bar/test-foo/bar/test-foo/bar/test-foo/bar/test-foo/bar/test.js'))21 t.true(isIgnoredByWatcher('test/foo/bar/test-foo/bar/test-foo/bar/test-foo/bar/test-foo/bar/test-foo.js'))22 t.true(isIgnoredByWatcher('test/foo/bar/test-foo/bar/test-foo/bar/test-foo/bar/test-foo/bar/test-foo/bar.js'))23 t.true(isIgnoredByWatcher('test/foo/bar/test-foo/bar/test-foo/bar/test-foo/bar/test-foo/bar/test-foo/bar/test.js'))
Using AI Code Generation
1import test from 'ava';2import {isIgnoredByWatcher} from 'ava/lib/watcher';3test('check if file is ignored by watcher', t => {4 const isIgnored = isIgnoredByWatcher('test.js');5 t.true(isIgnored);6});7import test from 'ava';8import {isIgnoredByWatcher} from 'ava/lib/watcher';9test('check if file is ignored by watcher', t => {10 const isIgnored = isIgnoredByWatcher('test2.js');11 t.false(isIgnored);12});13{14 "scripts": {15 },16 "ava": {17 }18}19import test from 'ava';20import {isIgnoredByWatcher} from 'ava/lib/watcher';21test('check if file is ignored by watcher', t => {22 const isIgnored = isIgnoredByWatcher('test.js');23 t.true(isIgnored);24});25import test from 'ava';26import {isIgnoredByWatcher} from 'ava/lib/watcher';27test('check if file is ignored by watcher', t => {28 const isIgnored = isIgnoredByWatcher('test2.js');29 t.false(isIgnored);30});
Using AI Code Generation
1const test = require('ava')2const path = require('path')3const isIgnoredByWatcher = require('ava/lib/watcher').isIgnoredByWatcher4const cwd = process.cwd()5const ignoredPath = path.join(cwd, 'ignored.txt')6const notIgnoredPath = path.join(cwd, 'not-ignored.txt')7test('ignored path', t => {8 t.true(isIgnoredByWatcher(ignoredPath))9})10test('not ignored path', t => {11 t.false(isIgnoredByWatcher(notIgnoredPath))12})13const test = require('ava')14const path = require('path')15const isIgnoredByWatcher = require('ava/lib/watcher').isIgnoredByWatcher16const cwd = process.cwd()17const ignoredPath = path.join(cwd, 'ignored.txt')18const notIgnoredPath = path.join(cwd, 'not-ignored.txt')19test('ignored path', t => {20 t.true(isIgnoredByWatcher(ignoredPath))21})22test('not ignored path', t => {23 t.false(isIgnoredByWatcher(notIgnoredPath))24})25const test = require('ava')26const path = require('path')27const isIgnoredByWatcher = require('ava/lib/watcher').isIgnoredByWatcher28const cwd = process.cwd()29const ignoredPath = path.join(cwd, 'ignored.txt')30const notIgnoredPath = path.join(cwd, 'not-ignored.txt')31test('ignored path', t => {32 t.true(isIgnoredByWatcher(ignoredPath))33})34test('not ignored path', t => {35 t.false(isIgnoredByWatcher(notIgnoredPath))36})37{38 "ava": {
Using AI Code Generation
1var avaFiles = require('ava-files');2var path = require('path');3var files = avaFiles({4 cwd: process.cwd(),5 resolveTestsFrom: process.cwd()6});7var filePath = path.join(process.cwd(), 'test.js');8console.log(files.isIgnoredByWatcher(filePath));9var avaFiles = require('ava-files');10var path = require('path');11var files = avaFiles({12 cwd: process.cwd(),13 resolveTestsFrom: process.cwd()14});15var filePath = path.join(process.cwd(), 'test.js');16console.log(files.isIgnoredByWatcher(filePath));17var avaFiles = require('ava-files');18var path = require('path');19var files = avaFiles({20 cwd: process.cwd(),21 resolveTestsFrom: process.cwd()22});23var filePath = path.join(process.cwd(), 'test.js');24console.log(files.isIgnoredByWatcher(filePath));25var avaFiles = require('ava-files');26var path = require('path');27var files = avaFiles({28 cwd: process.cwd(),29 resolveTestsFrom: process.cwd()30});31var filePath = path.join(process.cwd(), 'test.js');32console.log(files.isIgnoredByWatcher(filePath));33var avaFiles = require('ava-files');34var path = require('path');35var files = avaFiles({36 cwd: process.cwd(),37 resolveTestsFrom: process.cwd()38});39var filePath = path.join(process.cwd(), 'test.js');40console.log(files.isIgnoredByWatcher(filePath));41var avaFiles = require('ava-files');42var path = require('path');43var files = avaFiles({44 cwd: process.cwd(),45 resolveTestsFrom: process.cwd()46});47var filePath = path.join(process.cwd(), 'test.js');48console.log(files.isIgnoredByWatcher(filePath));
Using AI Code Generation
1const test = require('ava');2const watcher = require('chokidar');3const path = require('path');4test('chokidar', t => {5 const watcher = chokidar.watch(path.resolve(__dirname, 'test.js'));6 watcher.on('ready', () => {7 console.log(watcher.isIgnored(path.resolve(__dirname, 'test.js')));8 });9});
Using AI Code Generation
1import test from 'ava';2import path from 'path';3import watcher from 'chokidar';4const ignored = watcher().getWatched();5test('Test if file is being watched', t => {6 const testFilePath = path.resolve('./test.js');7 t.false(watcher.isIgnored(testFilePath));8});9test('Test if file is being ignored', t => {10 const testFilePath = path.resolve('./test.js');11 t.true(watcher.isIgnored(testFilePath));12});13import test from 'ava';14import path from 'path';15import watcher from 'chokidar';16const ignored = watcher().getWatched();17test('Test if file is being watched', t => {18 const testFilePath = path.resolve('./test.js');19 t.false(watcher.isIgnored(testFilePath));20});21test('Test if file is being ignored', t => {22 const testFilePath = path.resolve('./test.js');23 t.true(watcher.isIgnored(testFilePath));24});25import test from 'ava';26import path from 'path';27import watcher from 'chokidar';28const ignored = watcher().getWatched();29test('Test if file is being watched', t => {30 const testFilePath = path.resolve('./test.js');31 t.false(watcher.isIgnored(testFilePath));32});33test('Test if file is being ignored', t => {34 const testFilePath = path.resolve('./test.js');35 t.true(watcher.isIgnored(testFilePath));36});
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!