How to use api.run method in ava

Best JavaScript code snippet using ava

watcher.js

Source:watcher.js Github

copy

Full Screen

1'use strict';2const path = require('path');3const EventEmitter = require('events');4const PassThrough = require('stream').PassThrough;5const Promise = require('bluebird');6const defaultIgnore = require('ignore-by-default').directories();7const lolex = require('lolex');8const proxyquire = require('proxyquire');9const sinon = require('sinon');10const test = require('tap').test;11const AvaFiles = require('../lib/ava-files');12const setImmediate = require('../lib/globals').setImmediate;13// Helper to make using beforeEach less arduous14function makeGroup(test) {15	return (desc, fn) => {16		test(desc, t => {17			const beforeEach = fn => {18				t.beforeEach(done => {19					fn();20					done();21				});22			};23			const pending = [];24			const test = (name, fn) => {25				pending.push(t.test(name, fn));26			};27			fn(beforeEach, test, makeGroup(test));28			return Promise.all(pending);29		});30	};31}32const group = makeGroup(test);33group('chokidar', (beforeEach, test, group) => {34	let chokidar;35	let debug;36	let logger;37	let api;38	let avaFiles;39	let Subject;40	let runStatus;41	let resetRunStatus;42	let clock;43	let chokidarEmitter;44	let stdin;45	let files;46	function proxyWatcher(opts) {47		return proxyquire.noCallThru().load('../lib/watcher', opts ||48			{49				chokidar,50				debug(name) {51					return function () {52						const args = [name];53						args.push.apply(args, arguments);54						debug.apply(null, args);55					};56				},57				'./ava-files': avaFiles58			});59	}60	beforeEach(() => {61		chokidar = {62			watch: sinon.stub()63		};64		debug = sinon.spy();65		logger = {66			start: sinon.spy(),67			finish: sinon.spy(),68			section: sinon.spy(),69			clear: sinon.stub().returns(true),70			reset: sinon.spy()71		};72		api = {73			on() {},74			run: sinon.stub()75		};76		resetRunStatus = () => {77			runStatus = {78				failCount: 0,79				rejectionCount: 0,80				exceptionCount: 081			};82			return runStatus;83		};84		if (clock) {85			clock.uninstall();86		}87		clock = lolex.install(0, ['setImmediate', 'setTimeout', 'clearTimeout']);88		chokidarEmitter = new EventEmitter();89		chokidar.watch.returns(chokidarEmitter);90		logger.clear.returns(true);91		avaFiles = AvaFiles;92		api.run.returns(new Promise(() => {}));93		files = [94			'test.js',95			'test-*.js',96			'test'97		];98		resetRunStatus();99		stdin = new PassThrough();100		stdin.pause();101		Subject = proxyWatcher();102	});103	const start = sources => new Subject(logger, api, files, sources || []);104	const emitChokidar = (event, path) => {105		chokidarEmitter.emit('all', event, path);106	};107	const add = path => {108		emitChokidar('add', path || 'source.js');109	};110	const change = path => {111		emitChokidar('change', path || 'source.js');112	};113	const unlink = path => {114		emitChokidar('unlink', path || 'source.js');115	};116	const delay = () => new Promise(resolve => {117		setImmediate(resolve);118	});119	// Advance the clock to get past the debounce timeout, then wait for a promise120	// to be resolved to get past the `busy.then()` delay121	const debounce = times => {122		times = times >= 0 ? times : 1;123		clock.next();124		return delay().then(() => {125			if (times > 1) {126				return debounce(times - 1);127			}128		});129	};130	test('watches for default source file changes, as well as test files', t => {131		t.plan(2);132		start();133		t.ok(chokidar.watch.calledOnce);134		t.strictDeepEqual(chokidar.watch.firstCall.args, [135			['package.json', '**/*.js'].concat(files),136			{137				ignored: defaultIgnore.map(dir => `${dir}/**/*`),138				ignoreInitial: true139			}140		]);141	});142	test('watched source files are configurable', t => {143		t.plan(2);144		start(['foo.js', '!bar.js', 'baz.js', '!qux.js']);145		t.ok(chokidar.watch.calledOnce);146		t.strictDeepEqual(chokidar.watch.firstCall.args, [147			['foo.js', 'baz.js'].concat(files),148			{149				ignored: defaultIgnore.map(dir => `${dir}/**/*`).concat('bar.js', 'qux.js'),150				ignoreInitial: true151			}152		]);153	});154	test('configured sources can override default ignore patterns', t => {155		t.plan(2);156		start(['node_modules/foo/*.js']);157		t.ok(chokidar.watch.calledOnce);158		t.strictDeepEqual(chokidar.watch.firstCall.args, [159			['node_modules/foo/*.js'].concat(files),160			{161				ignored: defaultIgnore.map(dir => `${dir}/**/*`).concat('!node_modules/foo/*.js'),162				ignoreInitial: true163			}164		]);165	});166	test('starts running the initial tests', t => {167		t.plan(8);168		let done;169		api.run.returns(new Promise(resolve => {170			done = () => {171				resolve(runStatus);172			};173		}));174		start();175		t.ok(logger.clear.notCalled);176		t.ok(logger.reset.notCalled);177		t.ok(logger.start.notCalled);178		t.ok(api.run.calledOnce);179		t.strictDeepEqual(api.run.firstCall.args, [files, {runOnlyExclusive: false}]);180		// Finish is only called after the run promise fulfils181		t.ok(logger.finish.notCalled);182		done();183		return delay().then(() => {184			t.ok(logger.finish.calledOnce);185			t.is(logger.finish.firstCall.args[0], runStatus);186		});187	});188	[189		{190			label: 'is added',191			fire: add,192			event: 'add'193		},194		{195			label: 'changes',196			fire: change,197			event: 'change'198		},199		{200			label: 'is removed',201			fire: unlink,202			event: 'unlink'203		}204	].forEach(variant => {205		test(`logs a debug message when a file is ${variant.label}`, t => {206			t.plan(2);207			start();208			variant.fire('file.js');209			t.ok(debug.calledOnce);210			t.strictDeepEqual(debug.firstCall.args, ['ava:watcher', 'Detected %s of %s', variant.event, 'file.js']);211		});212	});213	[214		{215			label: 'is added',216			fire: add217		},218		{219			label: 'changes',220			fire: change221		},222		{223			label: 'is removed',224			fire: unlink225		}226	].forEach(variant => {227		test(`reruns initial tests when a source file ${variant.label}`, t => {228			t.plan(12);229			api.run.returns(Promise.resolve(runStatus));230			start();231			let done;232			api.run.returns(new Promise(resolve => {233				done = () => {234					resolve(runStatus);235				};236			}));237			variant.fire();238			return debounce().then(() => {239				t.ok(logger.clear.calledOnce);240				t.ok(logger.reset.calledOnce);241				t.ok(logger.start.calledOnce);242				t.ok(api.run.calledTwice);243				// Clear is called before reset244				t.ok(logger.clear.firstCall.calledBefore(logger.reset.firstCall));245				// Reset is called before the second run246				t.ok(logger.reset.firstCall.calledBefore(api.run.secondCall));247				// Reset is called before start248				t.ok(logger.reset.firstCall.calledBefore(logger.start.firstCall));249				// No explicit files are provided250				t.strictDeepEqual(api.run.secondCall.args, [files, {runOnlyExclusive: false}]);251				// Finish is only called after the run promise fulfils252				t.ok(logger.finish.calledOnce);253				t.is(logger.finish.firstCall.args[0], runStatus);254				resetRunStatus();255				done();256				return delay();257			}).then(() => {258				t.ok(logger.finish.calledTwice);259				t.is(logger.finish.secondCall.args[0], runStatus);260			});261		});262	});263	[264		{265			label: 'failures',266			prop: 'failCount'267		},268		{269			label: 'rejections',270			prop: 'rejectionCount'271		},272		{273			label: 'exceptions',274			prop: 'exceptionCount'275		}276	].forEach(variant => {277		test(`does not clear logger if the previous run had ${variant.label}`, t => {278			t.plan(2);279			runStatus[variant.prop] = 1;280			api.run.returns(Promise.resolve(runStatus));281			start();282			api.run.returns(Promise.resolve(resetRunStatus()));283			change();284			return debounce().then(() => {285				t.ok(logger.clear.notCalled);286				change();287				return debounce();288			}).then(() => {289				t.ok(logger.clear.calledOnce);290			});291		});292	});293	test('sections the logger if it was not cleared', t => {294		t.plan(5);295		api.run.returns(Promise.resolve({failCount: 1}));296		start();297		api.run.returns(Promise.resolve({failCount: 0}));298		change();299		return debounce().then(() => {300			t.ok(logger.clear.notCalled);301			t.ok(logger.reset.calledTwice);302			t.ok(logger.section.calledOnce);303			t.ok(logger.reset.firstCall.calledBefore(logger.section.firstCall));304			t.ok(logger.reset.secondCall.calledAfter(logger.section.firstCall));305		});306	});307	test('sections the logger if it could not be cleared', t => {308		t.plan(5);309		logger.clear.returns(false);310		api.run.returns(Promise.resolve(runStatus));311		start();312		change();313		return debounce().then(() => {314			t.ok(logger.clear.calledOnce);315			t.ok(logger.reset.calledTwice);316			t.ok(logger.section.calledOnce);317			t.ok(logger.reset.firstCall.calledBefore(logger.section.firstCall));318			t.ok(logger.reset.secondCall.calledAfter(logger.section.firstCall));319		});320	});321	test('does not section the logger if it was cleared', t => {322		t.plan(3);323		api.run.returns(Promise.resolve(runStatus));324		start();325		change();326		return debounce().then(() => {327			t.ok(logger.clear.calledOnce);328			t.ok(logger.section.notCalled);329			t.ok(logger.reset.calledOnce);330		});331	});332	test('debounces by 10ms', t => {333		t.plan(1);334		api.run.returns(Promise.resolve(runStatus));335		start();336		change();337		const before = clock.now;338		return debounce().then(() => {339			t.is(clock.now - before, 10);340		});341	});342	test('debounces again if changes occur in the interval', t => {343		t.plan(2);344		api.run.returns(Promise.resolve(runStatus));345		start();346		change();347		change();348		const before = clock.now;349		return debounce(2).then(() => {350			t.is(clock.now - before, 2 * 10);351			change();352			return debounce();353		}).then(() => {354			t.is(clock.now - before, 3 * 10);355		});356	});357	test('only reruns tests once the initial run has finished', t => {358		t.plan(2);359		let done;360		api.run.returns(new Promise(resolve => {361			done = () => {362				resolve({});363			};364		}));365		start();366		change();367		clock.next();368		return delay().then(() => {369			t.ok(api.run.calledOnce);370			done();371			return delay();372		}).then(() => {373			t.ok(api.run.calledTwice);374		});375	});376	test('only reruns tests once the previous run has finished', t => {377		t.plan(3);378		api.run.returns(Promise.resolve(runStatus));379		start();380		let done;381		api.run.returns(new Promise(resolve => {382			done = () => {383				resolve({});384			};385		}));386		change();387		return debounce().then(() => {388			t.ok(api.run.calledTwice);389			change();390			clock.next();391			return delay();392		}).then(() => {393			t.ok(api.run.calledTwice);394			done();395			return delay();396		}).then(() => {397			t.ok(api.run.calledThrice);398		});399	});400	[401		{402			label: 'is added',403			fire: add404		},405		{406			label: 'changes',407			fire: change408		}409	].forEach(variant => {410		test(`(re)runs a test file when it ${variant.label}`, t => {411			t.plan(6);412			api.run.returns(Promise.resolve(runStatus));413			start();414			let done;415			api.run.returns(new Promise(resolve => {416				done = () => {417					resolve(runStatus);418				};419			}));420			variant.fire('test.js');421			return debounce().then(() => {422				t.ok(api.run.calledTwice);423				// The `test.js` file is provided424				t.strictDeepEqual(api.run.secondCall.args, [['test.js'], {runOnlyExclusive: false}]);425				// Finish is only called after the run promise fulfills426				t.ok(logger.finish.calledOnce);427				t.is(logger.finish.firstCall.args[0], runStatus);428				resetRunStatus();429				done();430				return delay();431			}).then(() => {432				t.ok(logger.finish.calledTwice);433				t.is(logger.finish.secondCall.args[0], runStatus);434			});435		});436	});437	test('(re)runs several test files when they are added or changed', t => {438		t.plan(2);439		api.run.returns(Promise.resolve(runStatus));440		start();441		add('test-one.js');442		change('test-two.js');443		return debounce(2).then(() => {444			t.ok(api.run.calledTwice);445			// The test files are provided446			t.strictDeepEqual(api.run.secondCall.args, [['test-one.js', 'test-two.js'], {runOnlyExclusive: false}]);447		});448	});449	test('reruns initial tests if both source and test files are added or changed', t => {450		t.plan(2);451		api.run.returns(Promise.resolve(runStatus));452		start();453		add('test.js');454		unlink('source.js');455		return debounce(2).then(() => {456			t.ok(api.run.calledTwice);457			// No explicit files are provided458			t.strictDeepEqual(api.run.secondCall.args, [files, {runOnlyExclusive: false}]);459		});460	});461	test('does nothing if tests are deleted', t => {462		t.plan(1);463		api.run.returns(Promise.resolve(runStatus));464		start();465		unlink('test.js');466		return debounce().then(() => {467			t.ok(api.run.calledOnce);468		});469	});470	test('determines whether changed files are tests based on the initial files patterns', t => {471		t.plan(2);472		files = ['foo-{bar,baz}.js'];473		api.run.returns(Promise.resolve(runStatus));474		start();475		add('foo-bar.js');476		add('foo-baz.js');477		return debounce(2).then(() => {478			t.ok(api.run.calledTwice);479			t.strictDeepEqual(api.run.secondCall.args, [['foo-bar.js', 'foo-baz.js'], {runOnlyExclusive: false}]);480		});481	});482	test('initial exclude patterns override whether something is a test file', t => {483		t.plan(2);484		avaFiles = function (options) {485			const ret = new AvaFiles(options);486			// Note: There is no way for users to actually set exclude patterns yet.487			// This test just validates that internal updates to the default excludes pattern will be obeyed.488			ret.excludePatterns = ['!*bar*'];489			return ret;490		};491		Subject = proxyWatcher();492		files = ['foo-{bar,baz}.js'];493		api.run.returns(Promise.resolve(runStatus));494		start();495		add('foo-bar.js');496		add('foo-baz.js');497		return debounce(2).then(() => {498			t.ok(api.run.calledTwice);499			// `foo-bar.js` is excluded from being a test file, thus the initial tests500			// are run501			t.strictDeepEqual(api.run.secondCall.args, [files, {runOnlyExclusive: false}]);502		});503	});504	test('test files must end in .js', t => {505		t.plan(2);506		files = ['foo.bar'];507		api.run.returns(Promise.resolve(runStatus));508		start();509		add('foo.bar');510		return debounce(2).then(() => {511			t.ok(api.run.calledTwice);512			// `foo.bar` cannot be a test file, thus the initial tests are run513			t.strictDeepEqual(api.run.secondCall.args, [files, {runOnlyExclusive: false}]);514		});515	});516	test('test files must not start with an underscore', t => {517		t.plan(2);518		api.files = ['_foo.bar'];519		api.run.returns(Promise.resolve(runStatus));520		start();521		add('_foo.bar');522		return debounce(2).then(() => {523			t.ok(api.run.calledTwice);524			// `_foo.bar` cannot be a test file, thus the initial tests are run525			t.strictDeepEqual(api.run.secondCall.args, [files, {runOnlyExclusive: false}]);526		});527	});528	test('files patterns may match directories', t => {529		t.plan(2);530		files = ['dir', 'another-dir/*/deeper'];531		api.run.returns(Promise.resolve(runStatus));532		start();533		add(path.join('dir', 'test.js'));534		add(path.join('dir', 'nested', 'test.js'));535		add(path.join('another-dir', 'nested', 'deeper', 'test.js'));536		return debounce(3).then(() => {537			t.ok(api.run.calledTwice);538			t.strictDeepEqual(api.run.secondCall.args, [539				[540					path.join('dir', 'test.js'),541					path.join('dir', 'nested', 'test.js'),542					path.join('another-dir', 'nested', 'deeper', 'test.js')543				],544				{runOnlyExclusive: false}545			]);546		});547	});548	test('exclude patterns override directory matches', t => {549		t.plan(2);550		avaFiles = function (options) {551			const ret = new AvaFiles(options);552			// Note: There is no way for users to actually set exclude patterns yet.553			// This test just validates that internal updates to the default excludes pattern will be obeyed.554			ret.excludePatterns = ['!**/exclude/**'];555			return ret;556		};557		Subject = proxyWatcher();558		files = ['dir'];559		api.run.returns(Promise.resolve(runStatus));560		start();561		add(path.join('dir', 'exclude', 'foo.js'));562		return debounce(2).then(() => {563			t.ok(api.run.calledTwice);564			// `dir/exclude/foo.js` is excluded from being a test file, thus the initial565			// tests are run566			t.strictDeepEqual(api.run.secondCall.args, [files, {runOnlyExclusive: false}]);567		});568	});569	['r', 'rs'].forEach(input => {570		test(`reruns initial tests when "${input}" is entered on stdin`, t => {571			t.plan(4);572			api.run.returns(Promise.resolve(runStatus));573			start().observeStdin(stdin);574			stdin.write(`${input}\n`);575			return delay().then(() => {576				t.ok(api.run.calledTwice);577				t.strictDeepEqual(api.run.secondCall.args, [files, {runOnlyExclusive: false}]);578				stdin.write(`\t${input}  \n`);579				return delay();580			}).then(() => {581				t.ok(api.run.calledThrice);582				t.strictDeepEqual(api.run.thirdCall.args, [files, {runOnlyExclusive: false}]);583			});584		});585		test(`entering "${input}" on stdin prevents the logger from being cleared`, t => {586			t.plan(2);587			api.run.returns(Promise.resolve({failCount: 0}));588			start().observeStdin(stdin);589			stdin.write(`${input}\n`);590			return delay().then(() => {591				t.ok(api.run.calledTwice);592				t.ok(logger.clear.notCalled);593			});594		});595		test(`entering "${input}" on stdin cancels any debouncing`, t => {596			t.plan(7);597			api.run.returns(Promise.resolve(runStatus));598			start().observeStdin(stdin);599			let before = clock.now;600			let done;601			api.run.returns(new Promise(resolve => {602				done = () => {603					resolve({});604				};605			}));606			add();607			stdin.write(`${input}\n`);608			return delay().then(() => {609				// Processing "rs" caused a new run610				t.ok(api.run.calledTwice);611				// Try to advance the clock. This is *after* input was processed. The612				// debounce timeout should have been canceled, so the clock can't have613				// advanced.614				clock.next();615				t.is(before, clock.now);616				add();617				// Advance clock *before* input is received. Note that the previous run618				// hasn't finished yet.619				clock.next();620				stdin.write(`${input}\n`);621				return delay();622			}).then(() => {623				// No new runs yet624				t.ok(api.run.calledTwice);625				// Though the clock has advanced626				t.is(clock.now - before, 10);627				before = clock.now;628				const previous = done;629				api.run.returns(new Promise(resolve => {630					done = () => {631						resolve({});632					};633				}));634				// Finish the previous run635				previous();636				return delay();637			}).then(() => {638				// There's only one new run639				t.ok(api.run.calledThrice);640				stdin.write(`${input}\n`);641				return delay();642			}).then(() => {643				add();644				// Finish the previous run. This should cause a new run due to the645				// input.646				done();647				return delay();648			}).then(() => {649				// Again there's only one new run650				t.is(api.run.callCount, 4);651				// Try to advance the clock. This is *after* input was processed. The652				// debounce timeout should have been canceled, so the clock can't have653				// advanced.654				clock.next();655				t.is(before, clock.now);656			});657		});658	});659	test('does nothing if anything other than "rs" is entered on stdin', t => {660		t.plan(1);661		api.run.returns(Promise.resolve(runStatus));662		start().observeStdin(stdin);663		stdin.write('foo\n');664		return debounce().then(() => {665			t.ok(api.run.calledOnce);666		});667	});668	test('ignores unexpected events from chokidar', t => {669		t.plan(1);670		api.run.returns(Promise.resolve(runStatus));671		start();672		emitChokidar('foo');673		return debounce().then(() => {674			t.ok(api.run.calledOnce);675		});676	});677	test('initial run rejects', t => {678		t.plan(1);679		const expected = new Error();680		api.run.returns(Promise.reject(expected));681		start();682		return delay().then(() => {683			// The error is rethrown asynchronously, using setImmediate. The clock has684			// faked setTimeout, so if we call clock.next() it'll invoke and rethrow685			// the error, which can then be caught here.686			try {687				clock.next();688			} catch (err) {689				t.is(err, expected);690			}691		});692	});693	test('subsequent run rejects', t => {694		t.plan(1);695		api.run.returns(Promise.resolve(runStatus));696		start();697		const expected = new Error();698		api.run.returns(Promise.reject(expected));699		add();700		return debounce().then(() => {701			// The error is rethrown asynchronously, using setImmediate. The clock has702			// faked setTimeout, so if we call clock.next() it'll invoke and rethrow703			// the error, which can then be caught here.704			try {705				clock.next();706			} catch (err) {707				t.is(err, expected);708			}709		});710	});711	group('tracks test dependencies', (beforeEach, test) => {712		let apiEmitter;713		let runStatus;714		let runStatusEmitter;715		beforeEach(() => {716			apiEmitter = new EventEmitter();717			api.on = (event, fn) => {718				apiEmitter.on(event, fn);719			};720			runStatusEmitter = new EventEmitter();721			runStatus = {722				on(event, fn) {723					runStatusEmitter.on(event, fn);724				}725			};726		});727		const emitDependencies = (file, dependencies) => {728			runStatusEmitter.emit('dependencies', file, dependencies);729		};730		const seed = sources => {731			let done;732			api.run.returns(new Promise(resolve => {733				done = () => {734					resolve({});735				};736			}));737			const watcher = start(sources);738			const files = [path.join('test', '1.js'), path.join('test', '2.js')];739			const absFiles = files.map(relFile => path.resolve(relFile));740			apiEmitter.emit('test-run', runStatus, absFiles);741			emitDependencies(files[0], [path.resolve('dep-1.js'), path.resolve('dep-3.js')]);742			emitDependencies(files[1], [path.resolve('dep-2.js'), path.resolve('dep-3.js')]);743			done();744			api.run.returns(new Promise(() => {}));745			return watcher;746		};747		test('runs specific tests that depend on changed sources', t => {748			t.plan(2);749			seed();750			change('dep-1.js');751			return debounce().then(() => {752				t.ok(api.run.calledTwice);753				t.strictDeepEqual(api.run.secondCall.args, [[path.join('test', '1.js')], {runOnlyExclusive: false}]);754			});755		});756		test('reruns all tests if a source cannot be mapped to a particular test', t => {757			t.plan(2);758			seed();759			change('cannot-be-mapped.js');760			return debounce().then(() => {761				t.ok(api.run.calledTwice);762				t.strictDeepEqual(api.run.secondCall.args, [files, {runOnlyExclusive: false}]);763			});764		});765		test('runs changed tests and tests that depend on changed sources', t => {766			t.plan(2);767			seed();768			change('dep-1.js');769			change(path.join('test', '2.js'));770			return debounce(2).then(() => {771				t.ok(api.run.calledTwice);772				t.strictDeepEqual(api.run.secondCall.args, [773					[path.join('test', '2.js'), path.join('test', '1.js')],774					{runOnlyExclusive: false}775				]);776			});777		});778		test('avoids duplication when both a test and a source dependency change', t => {779			t.plan(2);780			seed();781			change(path.join('test', '1.js'));782			change('dep-1.js');783			return debounce(2).then(() => {784				t.ok(api.run.calledTwice);785				t.strictDeepEqual(api.run.secondCall.args, [[path.join('test', '1.js')], {runOnlyExclusive: false}]);786			});787		});788		test('stops tracking unlinked tests', t => {789			t.plan(2);790			seed();791			unlink(path.join('test', '1.js'));792			change('dep-3.js');793			return debounce(2).then(() => {794				t.ok(api.run.calledTwice);795				t.strictDeepEqual(api.run.secondCall.args, [[path.join('test', '2.js')], {runOnlyExclusive: false}]);796			});797		});798		test('updates test dependencies', t => {799			t.plan(2);800			seed();801			emitDependencies(path.join('test', '1.js'), [path.resolve('dep-4.js')]);802			change('dep-4.js');803			return debounce().then(() => {804				t.ok(api.run.calledTwice);805				t.strictDeepEqual(api.run.secondCall.args, [[path.join('test', '1.js')], {runOnlyExclusive: false}]);806			});807		});808		[809			{810				desc: 'only tracks source dependencies',811				sources: ['dep-1.js']812			},813			{814				desc: 'exclusion patterns affect tracked source dependencies',815				sources: ['!dep-2.js']816			}817		].forEach(variant => {818			test(variant.desc, t => {819				t.plan(2);820				seed(variant.sources);821				// `dep-2.js` isn't treated as a source and therefore it's not tracked as822				// a dependency for `test/2.js`. Pretend Chokidar detected a change to823				// verify (normally Chokidar would also be ignoring this file but hey).824				change('dep-2.js');825				return debounce().then(() => {826					t.ok(api.run.calledTwice);827					// Expect all tests to be rerun since `dep-2.js` is not a tracked828					// dependency829					t.strictDeepEqual(api.run.secondCall.args, [files, {runOnlyExclusive: false}]);830				});831			});832		});833		test('uses default source patterns', t => {834			t.plan(4);835			seed();836			emitDependencies(path.join('test', '1.js'), [path.resolve('package.json'), path.resolve('index.js'), path.resolve('lib/util.js')]);837			emitDependencies(path.join('test', '2.js'), [path.resolve('foo.bar')]);838			change('package.json');839			change('index.js');840			change(path.join('lib', 'util.js'));841			api.run.returns(Promise.resolve(runStatus));842			return debounce(3).then(() => {843				t.ok(api.run.calledTwice);844				t.strictDeepEqual(api.run.secondCall.args, [[path.join('test', '1.js')], {runOnlyExclusive: false}]);845				change('foo.bar');846				return debounce();847			}).then(() => {848				t.ok(api.run.calledThrice);849				// Expect all tests to be rerun since `foo.bar` is not a tracked850				// dependency851				t.strictDeepEqual(api.run.thirdCall.args, [files, {runOnlyExclusive: false}]);852			});853		});854		test('uses default exclusion patterns', t => {855			t.plan(2);856			// Ensure each directory is treated as containing sources857			seed(['**/*']);858			// Synthesize an excluded file for each directory that's ignored by859			// default. Apply deeper nesting for each file.860			const excludedFiles = defaultIgnore.map((dir, index) => {861				let relPath = dir;862				for (let i = index; i >= 0; i--) {863					relPath = path.join(relPath, String(i));864				}865				return `${relPath}.js`;866			});867			// Ensure `test/1.js` also depends on the excluded files868			emitDependencies(869				path.join('test', '1.js'),870				excludedFiles.map(relPath => path.resolve(relPath)).concat('dep-1.js')871			);872			// Modify all excluded files873			excludedFiles.forEach(change);874			return debounce(excludedFiles.length).then(() => {875				t.ok(api.run.calledTwice);876				// Since the excluded files are not tracked as a dependency, all tests877				// are expected to be rerun878				t.strictDeepEqual(api.run.secondCall.args, [files, {runOnlyExclusive: false}]);879			});880		});881		test('allows default exclusion patterns to be overriden', t => {882			t.plan(2);883			seed(['node_modules/foo/*.js']);884			const dep = path.join('node_modules', 'foo', 'index.js');885			emitDependencies(path.join('test', '1.js'), [path.resolve(dep)]);886			change(dep);887			return debounce(1).then(() => {888				t.ok(api.run.calledTwice);889				t.strictDeepEqual(api.run.secondCall.args, [[path.join('test', '1.js')], {runOnlyExclusive: false}]);890			});891		});892		test('ignores dependencies outside of the current working directory', t => {893			t.plan(4);894			seed(['**/*.js', '..foo.js']);895			emitDependencies(path.join('test', '1.js'), [path.resolve('../outside.js')]);896			emitDependencies(path.join('test', '2.js'), [path.resolve('..foo.js')]);897			// Pretend Chokidar detected a change to verify (normally Chokidar would898			// also be ignoring this file but hey)899			change(path.join('..', 'outside.js'));900			api.run.returns(Promise.resolve({failCount: 0}));901			return debounce().then(() => {902				t.ok(api.run.calledTwice);903				// If `../outside.js` was tracked as a dependency of test/1.js this would904				// have caused `test/1.js` to be rerun. Instead expect all tests to be905				// rerun. This is somewhat artifical: normally changes to `../outside.js`906				// wouldn't even be picked up. However this lets us test dependency907				// tracking without directly inspecting the internal state of the908				// watcher.909				t.strictDeepEqual(api.run.secondCall.args, [files, {runOnlyExclusive: false}]);910				change('..foo.js');911				return debounce();912			}).then(() => {913				t.ok(api.run.calledThrice);914				t.strictDeepEqual(api.run.thirdCall.args, [[path.join('test', '2.js')], {runOnlyExclusive: false}]);915			});916		});917		test('logs a debug message when a dependent test is found', t => {918			t.plan(2);919			seed();920			change('dep-1.js');921			return debounce().then(() => {922				t.ok(debug.calledTwice);923				t.strictDeepEqual(debug.secondCall.args, ['ava:watcher', '%s is a dependency of %s', 'dep-1.js', path.join('test', '1.js')]);924			});925		});926		test('logs a debug message when sources remain without dependent tests', t => {927			t.plan(2);928			seed();929			change('cannot-be-mapped.js');930			return debounce().then(() => {931				t.ok(debug.calledTwice);932				t.strictDeepEqual(debug.secondCall.args, ['ava:watcher', 'Sources remain that cannot be traced to specific tests. Rerunning all tests']);933			});934		});935	});936	group('.only is sticky', (beforeEach, test) => {937		let apiEmitter;938		beforeEach(() => {939			apiEmitter = new EventEmitter();940			api.on = (event, fn) => {941				apiEmitter.on(event, fn);942			};943		});944		const emitStats = (file, hasExclusive) => {945			apiEmitter.emit('stats', {946				file,947				hasExclusive948			});949		};950		const t1 = path.join('test', '1.js');951		const t2 = path.join('test', '2.js');952		const t3 = path.join('test', '3.js');953		const t4 = path.join('test', '4.js');954		const seed = () => {955			let done;956			api.run.returns(new Promise(resolve => {957				done = () => {958					resolve({});959				};960			}));961			const watcher = start();962			emitStats(t1, true);963			emitStats(t2, true);964			emitStats(t3, false);965			emitStats(t4, false);966			done();967			api.run.returns(new Promise(() => {}));968			return watcher;969		};970		test('changed test files (none of which previously contained .only) are run in exclusive mode', t => {971			t.plan(2);972			seed();973			change(t3);974			change(t4);975			return debounce(2).then(() => {976				t.ok(api.run.calledTwice);977				t.strictDeepEqual(api.run.secondCall.args, [[t1, t2, t3, t4], {runOnlyExclusive: true}]);978			});979		});980		test('changed test files (comprising some, but not all, files that previously contained .only) are run in exclusive mode', t => {981			t.plan(2);982			seed();983			change(t1);984			change(t4);985			return debounce(2).then(() => {986				t.ok(api.run.calledTwice);987				t.strictDeepEqual(api.run.secondCall.args, [[t1, t2, t4], {runOnlyExclusive: true}]);988			});989		});990		test('changed test files (comprising all files that previously contained .only) are run in regular mode', t => {991			t.plan(2);992			seed();993			change(t1);994			change(t2);995			return debounce(2).then(() => {996				t.ok(api.run.calledTwice);997				t.strictDeepEqual(api.run.secondCall.args, [[t1, t2], {runOnlyExclusive: false}]);998			});999		});1000		test('once no test files contain .only, further changed test files are run in regular mode', t => {1001			t.plan(2);1002			seed();1003			emitStats(t1, false);1004			emitStats(t2, false);1005			change(t3);1006			change(t4);1007			return debounce(2).then(() => {1008				t.ok(api.run.calledTwice);1009				t.strictDeepEqual(api.run.secondCall.args, [[t3, t4], {runOnlyExclusive: false}]);1010			});1011		});1012		test('once test files containing .only are removed, further changed test files are run in regular mode', t => {1013			t.plan(2);1014			seed();1015			unlink(t1);1016			unlink(t2);1017			change(t3);1018			change(t4);1019			return debounce(4).then(() => {1020				t.ok(api.run.calledTwice);1021				t.strictDeepEqual(api.run.secondCall.args, [[t3, t4], {runOnlyExclusive: false}]);1022			});1023		});1024	});1025	group('tracks previous failures', (beforeEach, test) => {1026		let apiEmitter;1027		let runStatus;1028		let runStatusEmitter;1029		beforeEach(() => {1030			apiEmitter = new EventEmitter();1031			api.on = (event, fn) => {1032				apiEmitter.on(event, fn);1033			};1034			runStatusEmitter = new EventEmitter();1035			runStatus = {1036				on(event, fn) {1037					runStatusEmitter.on(event, fn);1038				}1039			};1040		});1041		const seed = seedFailures => {1042			let done;1043			api.run.returns(new Promise(resolve => {1044				done = () => {1045					resolve(runStatus);1046				};1047			}));1048			const watcher = start();1049			const files = [path.join('test', '1.js'), path.join('test', '2.js')];1050			apiEmitter.emit('test-run', runStatus, files.map(relFile => {1051				return path.resolve(relFile);1052			}));1053			if (seedFailures) {1054				seedFailures(files);1055			}1056			done();1057			api.run.returns(new Promise(() => {}));1058			return watcher;1059		};1060		const rerun = function (file) {1061			runStatus = {on: runStatus.on};1062			let done;1063			api.run.returns(new Promise(resolve => {1064				done = () => {1065					resolve(runStatus);1066				};1067			}));1068			change(file);1069			return debounce().then(() => {1070				apiEmitter.emit('test-run', runStatus, [path.resolve(file)]);1071				done();1072				api.run.returns(new Promise(() => {}));1073			});1074		};1075		test('sets runStatus.previousFailCount to 0 if there were no previous failures', t => {1076			t.plan(1);1077			seed(files => {1078				runStatusEmitter.emit('error', {file: files[0]});1079			});1080			return debounce().then(() => {1081				t.is(runStatus.previousFailCount, 0);1082			});1083		});1084		test('sets runStatus.previousFailCount if there were prevous failures', t => {1085			t.plan(1);1086			let other;1087			seed(files => {1088				runStatusEmitter.emit('test', {1089					file: files[0],1090					error: {}1091				});1092				runStatusEmitter.emit('error', {1093					file: files[0]1094				});1095				other = files[1];1096			});1097			return rerun(other).then(() => {1098				t.is(runStatus.previousFailCount, 2);1099			});1100		});1101		test('tracks failures from multiple files', t => {1102			t.plan(1);1103			let first;1104			seed(files => {1105				runStatusEmitter.emit('test', {1106					file: files[0],1107					error: {}1108				});1109				runStatusEmitter.emit('error', {file: files[1]});1110				first = files[0];1111			});1112			return rerun(first).then(() => {1113				t.is(runStatus.previousFailCount, 1);1114			});1115		});1116		test('previous failures don\'t count when that file is rerun', t => {1117			t.plan(1);1118			let same;1119			seed(files => {1120				runStatusEmitter.emit('test', {1121					file: files[0],1122					error: {}1123				});1124				runStatusEmitter.emit('error', {file: files[0]});1125				same = files[0];1126			});1127			return rerun(same).then(() => {1128				t.is(runStatus.previousFailCount, 0);1129			});1130		});1131		test('previous failures don\'t count when that file is deleted', t => {1132			t.plan(1);1133			let same;1134			let other;1135			seed(files => {1136				runStatusEmitter.emit('test', {1137					file: files[0],1138					error: {}1139				});1140				runStatusEmitter.emit('error', {file: files[0]});1141				same = files[0];1142				other = files[1];1143			});1144			unlink(same);1145			return debounce().then(() => rerun(other)).then(() => {1146				t.is(runStatus.previousFailCount, 0);1147			});1148		});1149	});...

Full Screen

Full Screen

webhook.js

Source:webhook.js Github

copy

Full Screen

...19      userId: userId20    });21    if (!user) {22      let text = `Configure user settings at ${env.getBuiltin().appUrl}`;23      return api.run("this.post_text_only_message", {24        text: text,25        channel: channel26      })27    }28    const raw_full_command = parsed_body.event.text;29    const raw_command = raw_full_command.substr(raw_full_command.indexOf(">") + 2); // get rid of botusername30    const help_text = "I don't understand the command. \n\nPlease either 'list-ec2-instances' or 'resize-ec2-instance \"instance-id\" approver: @name'";31    // return api.run("slack.post_chat_message", {text: "abcd", channel: channel});32    if (!raw_command) {33      console.log("didn't see raw command");34      return api.run("this.post_text_only_message", {35        text: help_text,36        channel: channel37      });38    }39    if (raw_command.length < 1) {40      console.log("didn't see raw command length");41      return api.run("this.post_text_only_message", {42        text: help_text,43        channel: channel44      });45    }46    const list_cmd = new RegExp(/list-ec2-instances/).exec(raw_command) != null;47    const resize_cmd = new RegExp(/resize-ec2-instance/).exec(raw_command) != null;48    if (!(list_cmd || resize_cmd)) {49      console.log("didn't see raw command we understood");50      console.log(resize_cmd);51      console.log(raw_command);52      return api.run("this.post_text_only_message", {53        text: help_text,54        channel: channel55      });56    }57    if (list_cmd) {58      const parameters = api.run("this.create_parameters_for_list_instances", {59        channel: channel,60        user: user61      })[0];62      return api.run("this.post_chat_message", parameters);63    }64    if (resize_cmd) {65      const command_array = raw_command.split(/ +/).filter(s => {66        return s && s.length > 067      });68      if (command_array.length != 4) {69        console.log("didn't see resize command we understood");70        console.log(command_array);71        console.log(raw_command);72        return api.run("this.post_text_only_message", {73          text: help_text + " [saw " + raw_command + "]",74          channel: channel75        });76      }77      const instanceId = command_array[1].trim();78      const approvalUser = command_array[3].trim();79      if (!instanceId || !/^i-[0-9]/.exec(instanceId) || !approvalUser) {80        console.log("didn't see resize command we understood");81        console.log(command_array);82        console.log(raw_command);83        return api.run("this.post_text_only_message", {84          text: help_text + " [saw " + raw_command + "]",85          channel: channel86        });87      }88      const stashKey = instanceId + "-" + user.slack.userId;89      const stashValue = {};90      stashValue.approvalUser = approvalUser;91      stashValue.channel = channel;92      stash.put(stashKey, JSON.stringify(stashValue));93      const parameters = api.run("this.create_parameters_for_resize_instances", {94        channel: channel,95        user: user,96        instanceId: instanceId97      })[0];98      return api.run("this.post_chat_message", parameters);99    }100  });101  return {102    status_code: 200103  };...

Full Screen

Full Screen

index.js

Source:index.js Github

copy

Full Screen

1import * as _commands from './commands';2import validator from './validate';3export const name = 'beanstalk';4export const description = 'Deploy Meteor app to AWS Elastic Beanstalk';5export const commands = _commands;6export const validate = {7  app(config, utils) {8    if (config.app && config.app.type === 'aws-beanstalk') {9      return validator(config, utils);10    }11    return [];12  }13};14export function prepareConfig(config) {15  if (!config.app || config.app.type !== 'aws-beanstalk') {16    return config;17  }18  const defaultBuildOptions = {19    serverOnly: true20  };21  config.app.buildOptions = config.app.buildOptions || defaultBuildOptions;22  // This will change 0 to 1. The validator will warn when the number is 023  // To have 0 instances, `mup stop` should be used24  config.app.minInstances = config.app.minInstances || 1;25  config.app.maxInstances = config.app.maxInstances || config.app.minInstances;26  config.app.instanceType = config.app.instanceType || 't2.micro';27  return config;28}29function isBeanstalkApp(api) {30  const config = api.getConfig();31  if (config.app && config.app.type === 'aws-beanstalk') {32    return true;33  }34  return false;35}36export const hooks = {37  'post.setup': (api) => {38    if (isBeanstalkApp(api)) {39      return api.runCommand('beanstalk.setup');40    }41  },42  'post.deploy': (api) => {43    if (isBeanstalkApp(api)) {44      return api.runCommand('beanstalk.deploy');45    }46  },47  'post.logs': (api) => {48    if (isBeanstalkApp(api)) {49      return api.runCommand('beanstalk.logs');50    }51  },52  'post.start': (api) => {53    if (isBeanstalkApp(api)) {54      return api.runCommand('beanstalk.start');55    }56  },57  'post.stop': (api) => {58    if (isBeanstalkApp(api)) {59      return api.runCommand('beanstalk.stop');60    }61  },62  'post.restart': (api) => {63    if (isBeanstalkApp(api)) {64      return api.runCommand('beanstalk.restart');65    }66  },67  'post.reconfig': (api) => {68    if (isBeanstalkApp(api)) {69      return api.runCommand('beanstalk.reconfig');70    }71  },72  'post.status': (api) => {73    if (isBeanstalkApp(api)) {74      return api.runCommand('beanstalk.status');75    }76  }...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1const test = require('ava');2var api = require('ava-api');3api.run({4}).then(function (result) {5    console.log(result);6});7module.exports = {8        ['@babel/preset-env', { targets: { node: 'current' } }]9};10{11  "scripts": {12  },13  "dependencies": {14  }15}16import test from 'ava';17test('foo', t => {18    t.pass();19});20test('bar', async t => {21    const bar = Promise.resolve('bar');22    t.is(await bar, 'bar');23});24import test from 'ava';25test('foo', t => {26    t.pass();27});28test('bar', async t => {29    const bar = Promise.resolve('bar');30    t.is(await bar, 'bar');31});32import test from 'ava';33test('foo', t => {34    t.pass();35});36test('bar', async t => {37    const bar = Promise.resolve('bar');38    t.is(await bar, 'bar');39});40import test from 'ava';41test('foo', t => {42    t.pass();43});44test('bar', async t => {45    const bar = Promise.resolve('bar');46    t.is(await bar, 'bar');47});48import test from 'ava

Full Screen

Using AI Code Generation

copy

Full Screen

1import test from 'ava';2import api from 'ava-api';3import { resolve } from 'path';4import { readFileSync } from 'fs';5test('api.run', async t => {6  const { stdout } = await api.run(['test.js'], { cwd: resolve(__dirname, 'fixtures') });7  t.true(stdout.includes('1 test passed'));8});9import test from '../../..';10test('api.run', t => {11  t.pass();12});13import test from 'ava';14import api from 'ava-api';15import { resolve } from 'path';16import { readFileSync } from 'fs';17test('api.run', async t => {18  const { stdout } = await api.run(['test.js'], { cwd: resolve(__dirname, 'fixtures') });19  t.true(stdout.includes('1 test passed'));20});21import test from '../../..';22test('api.run', t => {23  t.pass();24});25import test from 'ava';26import api from 'ava-api';27import { resolve } from 'path';28import { readFileSync } from 'fs';29test('api.run', async t => {30  const { stdout } = await api.run(['test.js'], { cwd: resolve(__dirname, 'fixtures') });31  t.true(stdout.includes('1 test passed'));32});33import test from '../../..';34test('api.run', t => {35  t.pass();36});37import test from 'ava';38import api from 'ava-api';39import { resolve } from 'path';40import { readFileSync } from 'fs';41test('api.run', async t => {42  const { stdout } = await api.run(['test.js'], { cwd: resolve(__dirname, 'fixtures') });43  t.true(stdout.includes('1 test passed'));44});45import test from '../../..';46test('api.run', t => {47  t.pass();48});49import test from 'ava';

Full Screen

Using AI Code Generation

copy

Full Screen

1var module = function() {2    var that = {};3    that.thing1 = function() {4    };5    that.thing2 = function() {6    };7    return that;8}9module.exports = module;10var module = function() {11    var that = {};12    that.thing1 = function() {13    };14    that.thing2 = function() {15    };16    return that;17}18module.exports = module;

Full Screen

Using AI Code Generation

copy

Full Screen

1import test from 'ava';2import api from 'ava-api';3test('test', async t => {4    t.is(await api.run('example.js'), 'foo');5});6export default 'foo';7api.run(filepath, [options])8import api from 'ava-api';9api.run('test.js', {10}).then(result => {11    console.log(result);12});13api.run('test.js', {14}).then(result => {15    console.log(result);16});

Full Screen

Using AI Code Generation

copy

Full Screen

1var api = require('api');2var run = api.run;3var test = api.test;4test.assert(response.status === 200, 'response status is 200');5test.assert(response.status === 200, 'response status is 200');6test.assert(response.status === 200, 'response status is 200')7test.assert(response.status === 200, 'response status is 200')8  .assert(response.json().headers['User-Agent'] === 'PostmanRuntime/7.11.0', 'user agent is correct');9test.assert(response.status === 200, 'response status is 200')10  .assert(response.json().headers['User-Agent'] === 'PostmanRuntime/7.11.0', 'user agent is correct')11  .assert(response.json().headers['Accept'] === '*/*', 'Accept is correct');12test.assert(response.status === 200, 'response status is 200')13  .assert(response.json().headers['User-Agent'] === 'PostmanRuntime/7.11.0', 'user agent is correct')14  .assert(response.json().headers['Accept'] === '*/*', 'Accept is correct')15  .assert(response.json().headers['Accept-Encoding'] ===

Full Screen

Using AI Code Generation

copy

Full Screen

1var api = require('api');2var api = new api();3api.run('API Name', 'API Method', 'API Method Arguments', function(err, response){4    if(err){5        console.log(err);6    }else{7        console.log(response);8    }9});10var request = require('request');11var api = function(){12    this.run = function(apiName, apiMethod, args, callback){13        request({14            headers: {15            },16        }, function (error, response, body) {17            if(error){18                callback(error, null);19            }else{20                callback(null, body);21            }22        });23    }24}25module.exports = api;

Full Screen

Automation Testing Tutorials

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.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run ava automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful