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