From 5f15a022152cc724eaeb93994089c6661ac339e1 Mon Sep 17 00:00:00 2001 From: Tomas Romero Date: Sat, 1 Aug 2015 13:47:27 -0300 Subject: [PATCH 1/3] Run tests manually from outside of the app --- methods.js | 7 ++++ packages/latte/latte.js | 75 +++++++++++++++------------------------ packages/latte/package.js | 2 +- 3 files changed, 37 insertions(+), 47 deletions(-) create mode 100644 methods.js diff --git a/methods.js b/methods.js new file mode 100644 index 0000000..94546b6 --- /dev/null +++ b/methods.js @@ -0,0 +1,7 @@ +Meteor.methods({ + test: function (input) { + T.needToBoot = false + T.run(input) + } +}) + diff --git a/packages/latte/latte.js b/packages/latte/latte.js index e624587..fe0ad58 100644 --- a/packages/latte/latte.js +++ b/packages/latte/latte.js @@ -1,13 +1,13 @@ var figures = Npm.require('figures') T = { // eslint-disable-line - analize: function () { // this lets us analyze suite's structure to act accordingly later (allowing, for example, iit blocks to work) - T.analyzing = true - T.suites.forEach(exec) - T.analyzing = false - }, - run: function () { + run: function (onlySuites) { if (!process.env.RUN_TESTS) { return } + if (onlySuites) { T.onlySuites = onlySuites } + T.preProcess = false + T.describeBlocks.forEach(exec) + T.analyzing = false + T.needToBoot = false var testingDB = new global.MongoInternals.RemoteCollectionDriver(T.testingDbUrl) // create a driver pointing to testing's DB getCollections().forEach(pointToTestingDB) // point collections to testing's DB @@ -23,6 +23,12 @@ T = { // eslint-disable-line process.env.RUN_TESTS !== 'cont' && process.exit(T.exceptions.length) // end the process unless option is specified + T.itCount = 0 + T.successfulItCount = 0 + T.analyzing = true + T.needToBoot = true + T.suites = [] + function pointToTestingDB (collection) { collection.latte_original_driver = collection._driver // keep track of original driver, to point back to development's DB once tests have finished collection._driver = testingDB @@ -78,21 +84,11 @@ T = { // eslint-disable-line T.exceptions.push(e) // if `T.exceptions` has any item at the en of the test run, exit code will be != 0 } }, - beforeAll: function (fn) { - if (T.analyzing) { return } - T.beforeAllBlocks.push({ fn: fn, deepLevel: T.deepLevel }) // keep track of beforeAll blocks, to run them later - }, - beforeEach: function (fn) { - if (T.analyzing) { return } - T.beforeEachBlocks.push({ fn: fn, deepLevel: T.deepLevel }) - }, - afterAll: function (fn) { - if (T.analyzing) { return } - T.afterAllBlocks.push({ fn: fn, deepLevel: T.deepLevel }) - }, - afterEach: function (fn) { - if (T.analyzing) { return } - T.afterEachBlocks.push({ fn: fn, deepLevel: T.deepLevel }) + defineHook: function (type) { + return function (fn) { + if (T.analyzing) { return } + T[type + 'Blocks'].push({ fn: fn, deepLevel: T.deepLevel }) + } }, message: function (type, label, deepLevel) { // pretty print messages for console report var prefix = '' @@ -116,8 +112,9 @@ T = { // eslint-disable-line onlyRootDescribeBlocksForIit: [], describeMessages: [], itBlockRunLevel: 0, - isFirstAddedSuite: true, + needToBoot: true, analyzing: true, + preProcess: true, onlySuites: [], testingDbUrl: 'mongodb://127.0.0.1:3001/meteor_latte' } @@ -139,32 +136,18 @@ function descriptionBlock (type, options) { if (!process.env.RUN_TESTS) { return function () {} } // don't run any test related stuff unless explicitly told so options = options || {} - return function analyzeOrExec (label, fn) { + return function describeBlock (label, fn) { + T.needToBoot && Meteor.startup(T.run) + T.needToBoot = false + if (T.preProcess) { return T.describeBlocks.push(describeBlock.bind(this, label, fn)) } if (T.deepLevel === 0 && options.runOnly && !excludedSuite(T.onlySuites, label) && !T.onlySuitesAsUserParams) { T.onlySuites.push(label) } if (T.deepLevel === 0 && preventsSuiteFromRunning(label)) { return } - - return (T.analyzing ? analizeBlock(label, fn) : describeBlock(label, fn)) - } - - function analizeBlock (label, fn) { - if (T.deepLevel === 0) { + if (T.analyzing && T.deepLevel === 0) { var testSuite = describeBlock.bind(this, label, fn) T.currentRootDescribeBlock = testSuite T.suites.push(testSuite) - T.isFirstAddedSuite && Meteor.startup(function () { // upon first suite addition, add a callback to startup to run tests - T.analize() // look at suites structure and prepare the test run (this allows, for example, iit behavior) - T.run() // run code defined inside suites (describe blocks) - }) - T.isFirstAddedSuite = false } - T.deepLevel++ - fn() - T.deepLevel-- - } - - function describeBlock (label, fn) { - if (T.deepLevel === 0 && preventsSuiteFromRunning(label)) { return } - T.describeMessages.push(T.message(type, label, T.deepLevel)) + !T.analyzing && T.describeMessages.push(T.message(type, label, T.deepLevel)) T.deepLevel++ fn() if (T.itBlockRunLevel >= T.deepLevel) { @@ -245,10 +228,10 @@ describe = T.describe.bind(T) context = T.context.bind(T) it = T.it.bind(T) iit = T.iit.bind(T) -beforeAll = T.beforeAll.bind(T) -beforeEach = T.beforeEach.bind(T) -afterAll = T.afterAll.bind(T) -afterEach = T.afterEach.bind(T) +beforeAll = T.defineHook('beforeAll').bind(T) +beforeEach = T.defineHook('beforeEach').bind(T) +afterAll = T.defineHook('afterAll').bind(T) +afterEach = T.defineHook('afterEach').bind(T) ddescribe = T.ddescribe.bind(T) ccontext = T.ccontext.bind(T) /*eslint-enable */ diff --git a/packages/latte/package.js b/packages/latte/package.js index 2686915..c55e134 100644 --- a/packages/latte/package.js +++ b/packages/latte/package.js @@ -1,6 +1,6 @@ Package.describe({ name: 'canotto90:latte', - version: '0.6.4', + version: '0.7.4', summary: 'Run mocha-like specs in Meteor, without Velocity\'s overhead.', git: 'https://github.com/taromero/latte.git', documentation: '../../README.md' From 80c2b8d1e333734ab554240503760e26fcac283f Mon Sep 17 00:00:00 2001 From: Tomas Romero Date: Wed, 5 Aug 2015 01:09:23 -0300 Subject: [PATCH 2/3] Pass either the file or the describe label of the suite to run (by http) --- .meteor/versions | 3 ++- methods.js | 7 ------- package.json | 2 +- packages/latte/http_api.js | 9 +++++++++ packages/latte/latte.js | 20 ++++++++++++++++++-- packages/latte/package.js | 2 ++ 6 files changed, 32 insertions(+), 11 deletions(-) delete mode 100644 methods.js create mode 100644 packages/latte/http_api.js diff --git a/.meteor/versions b/.meteor/versions index 214e794..fb11d70 100644 --- a/.meteor/versions +++ b/.meteor/versions @@ -6,8 +6,9 @@ blaze@2.1.2 blaze-tools@1.0.3 boilerplate-generator@1.0.3 callback-hook@1.0.3 -canotto90:latte@0.6.4 +canotto90:latte@0.7.4 canotto90:pretty-errors@0.0.1 +cfs:http-methods@0.0.29 check@1.0.5 coffeescript@1.0.6 ddp@1.1.0 diff --git a/methods.js b/methods.js deleted file mode 100644 index 94546b6..0000000 --- a/methods.js +++ /dev/null @@ -1,7 +0,0 @@ -Meteor.methods({ - test: function (input) { - T.needToBoot = false - T.run(input) - } -}) - diff --git a/package.json b/package.json index 9d07a45..278a843 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "describe", "ddescribe", "context", "ccontext", "it", "iit", "beforeAll", "beforeEach", "T", "afterAll", "afterEach", "expect", "should", "_", - "figures", "Npm" + "figures", "Npm", "HTTP" ] } } diff --git a/packages/latte/http_api.js b/packages/latte/http_api.js new file mode 100644 index 0000000..af28db3 --- /dev/null +++ b/packages/latte/http_api.js @@ -0,0 +1,9 @@ +HTTP.methods({ + '/test': { + get: function () { + T.needToBoot = false + T.run(this.query.suite) + } + } +}) + diff --git a/packages/latte/latte.js b/packages/latte/latte.js index fe0ad58..fa1f6dc 100644 --- a/packages/latte/latte.js +++ b/packages/latte/latte.js @@ -1,9 +1,11 @@ var figures = Npm.require('figures') +var readFile = Meteor.wrapAsync(Npm.require('fs').readFile) T = { // eslint-disable-line - run: function (onlySuites) { + run: function (input) { if (!process.env.RUN_TESTS) { return } - if (onlySuites) { T.onlySuites = onlySuites } + getOnlySuitesFromInput(input) + T.preProcess = false T.describeBlocks.forEach(exec) T.analyzing = false @@ -220,6 +222,20 @@ function getCollections () { } } +// input can be either the file or the describe label to run +function getOnlySuitesFromInput (input) { + if (!input) { return } + var onlySuites = null + var file = null + try { file = input && readFile(input.toString()).toString() } catch(e) {} + if (file) { + var start = file.indexOf('describe(') + 'describe('.length + 1 + var end = file.indexOf(', function') - 1 + onlySuites = [file.substring(start, end)] + } + T.onlySuites = onlySuites || input +} + // Global variables are not attached to the `global` object in Meteor packages, so we ignore style checker for this section. // Details: http://stackoverflow.com/questions/31526454/global-variables-not-being-attached-to-the-global-object-on-meteorjs-packages diff --git a/packages/latte/package.js b/packages/latte/package.js index c55e134..92aa555 100644 --- a/packages/latte/package.js +++ b/packages/latte/package.js @@ -13,7 +13,9 @@ Npm.depends({ Package.onUse(function (api) { api.use('mongo@1.1.0', 'server') api.use('nooitaf:colors@0.0.2') + api.use('cfs:http-methods@0.0.29') api.addFiles('latte.js', 'server') + api.addFiles('http_api.js', 'server') api.export('T', 'server') api.export('describe', 'server') api.export('context', 'server') From 0ef885d4978e817204029844d70e16d5a2affe87 Mon Sep 17 00:00:00 2001 From: Tomas Romero Date: Mon, 30 Nov 2015 22:54:43 -0300 Subject: [PATCH 3/3] checkpoint --- packages/latte/latte.js | 12 +++++++++++- specs/ddescribe_iit_spec.js | 4 +++- specs/ddescribe_spec.js | 1 + specs/iit_spec.js | 1 + specs/multiple_ddescribe_spec.js | 2 ++ specs/sample_spec.js | 2 +- 6 files changed, 19 insertions(+), 3 deletions(-) diff --git a/packages/latte/latte.js b/packages/latte/latte.js index fa1f6dc..cc618fc 100644 --- a/packages/latte/latte.js +++ b/packages/latte/latte.js @@ -4,32 +4,42 @@ var readFile = Meteor.wrapAsync(Npm.require('fs').readFile) T = { // eslint-disable-line run: function (input) { if (!process.env.RUN_TESTS) { return } - getOnlySuitesFromInput(input) + console.log('T.onlySuites', T.onlySuites) + console.log('T.analyzing', T.analyzing) T.preProcess = false T.describeBlocks.forEach(exec) + getOnlySuitesFromInput(input) + console.log('T.onlySuites', T.onlySuites) T.analyzing = false T.needToBoot = false var testingDB = new global.MongoInternals.RemoteCollectionDriver(T.testingDbUrl) // create a driver pointing to testing's DB getCollections().forEach(pointToTestingDB) // point collections to testing's DB getCollections().forEach(removeAll) // erase date on testing DB (though there should be none) + console.log('0') + console.log('T.onlyRootDescribeBlocksForIit', T.onlyRootDescribeBlocksForIit) T.onlyRootDescribeBlocksForIit.length ? T.onlyRootDescribeBlocksForIit.forEach(exec) : T.suites.forEach(exec) // if there's `iit` blocks, only run those // output number of successful over total tests log('\n' + (T.itCount + ' tests: ').yellow + (T.successfulItCount + ' passing, ').green + (T.itCount - T.successfulItCount + ' failing.').red) + console.log('1') getCollections().forEach(pointBackToDevelopDB) // point collections back to development's DB _(T.postRunCallbacks).reject(preventsSuiteFromRunning).map(fns).forEach(exec) // allow to run a callback when testing has finished (before possibly ending the process) + console.log('A') process.env.RUN_TESTS !== 'cont' && process.exit(T.exceptions.length) // end the process unless option is specified + console.log('B') T.itCount = 0 T.successfulItCount = 0 T.analyzing = true T.needToBoot = true T.suites = [] + T.onlyRootDescribeBlocksForIit = [] + console.log('C') function pointToTestingDB (collection) { collection.latte_original_driver = collection._driver // keep track of original driver, to point back to development's DB once tests have finished diff --git a/specs/ddescribe_iit_spec.js b/specs/ddescribe_iit_spec.js index 6969eba..7b35294 100644 --- a/specs/ddescribe_iit_spec.js +++ b/specs/ddescribe_iit_spec.js @@ -24,7 +24,9 @@ describe('describe block containing an iit block, in presence of a ddescribe blo T.postRunCallbacks.push({ label: 'ddescribe should take precedence over iit blocks', fn: function () { - if (ddescribeCounter !== 1) { throw new Error('some assertion failed to exec. ddescribeCounter = ' + ddescribeCounter) } + console.log('prca') + if (ddescribeCounter !== 1) { console.log('prca1'); throw new Error('some assertion failed to exec. ddescribeCounter = ' + ddescribeCounter) } + console.log('prca2') } }) diff --git a/specs/ddescribe_spec.js b/specs/ddescribe_spec.js index ece4014..ecaa705 100644 --- a/specs/ddescribe_spec.js +++ b/specs/ddescribe_spec.js @@ -35,6 +35,7 @@ describe('unnested describe blocks in presence of a ddescribe block', function ( T.postRunCallbacks.push({ label: 'if there is a ddescribe block', fn: function () { + console.log('prcb') if (ddescribeCounter !== 2) { throw new Error('ddescribe_spec: some assertion failed to exec. ddescribeCounter == ' + ddescribeCounter) } } }) diff --git a/specs/iit_spec.js b/specs/iit_spec.js index d6e77f0..44c1d03 100644 --- a/specs/iit_spec.js +++ b/specs/iit_spec.js @@ -66,6 +66,7 @@ describe('iit behaviour', function () { T.postRunCallbacks.push({ label: 'iit behaviour', fn: function () { + console.log('prcd') if (iitCounter !== 3) { throw new Error('some assertion failed to exec. iitCounter == ' + iitCounter) } if (allCounter !== 4) { throw new Error('some before/afterAll block failed to exec. allCounter == ' + allCounter) } if (eachCounter !== 6) { throw new Error('some before/afterEach block failed to exec. eachCounter == ' + eachCounter) } diff --git a/specs/multiple_ddescribe_spec.js b/specs/multiple_ddescribe_spec.js index 51f7a22..9235c82 100644 --- a/specs/multiple_ddescribe_spec.js +++ b/specs/multiple_ddescribe_spec.js @@ -22,6 +22,7 @@ ddescribe('second ddescribe', function () { T.postRunCallbacks.push({ label: 'first ddescribe', fn: function () { + console.log('prcc') if (ddescribeCounter1 !== 1) { throw new Error('some assertion failed to exec. ddescribeCounter = ' + ddescribeCounter1) } } }) @@ -29,6 +30,7 @@ T.postRunCallbacks.push({ T.postRunCallbacks.push({ label: 'second ddescribe', fn: function () { + console.log('prcd') if (ddescribeCounter2 !== 1) { throw new Error('some assertion failed to exec. ddescribeCounter = ' + ddescribeCounter2) } } }) diff --git a/specs/sample_spec.js b/specs/sample_spec.js index 304de6d..0e29592 100644 --- a/specs/sample_spec.js +++ b/specs/sample_spec.js @@ -22,7 +22,7 @@ describe('Subject seeding', function () { }) it('should not create new subjects', function () { - Subjects.find().count().should.eq(1) + Subjects.find().count().should.eq(2) }) })