diff --git a/package.json b/package.json index c805483..bd177ea 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "async": "^2.6.2", "axios": "^0.19.1", "chai": "^4.2.0", + "chai-spies": "^1.0.0", "commander": "^2.19.0", "esprima": "^4.0.1", "form-data": "^3.0.0", diff --git a/src/Runner.js b/src/Runner.js index ad6cef9..34df531 100644 --- a/src/Runner.js +++ b/src/Runner.js @@ -116,7 +116,7 @@ class Runner { const files = await recursive(path.join(this[type].dir)); const tests = _.get(this, 'filters.tests', files); - if (!tests.length) return files; + if (!tests.length) return files; //@todo check if needed return _.filter(files, file => _.includes(tests, file)); // @todo Make sorts diff --git a/test/assets/runner/.artilleryrc.js b/test/assets/runner/.artilleryrc.js new file mode 100644 index 0000000..9fbd4ef --- /dev/null +++ b/test/assets/runner/.artilleryrc.js @@ -0,0 +1,14 @@ +module.exports = { + config: { + tls: { + rejectUnauthorized: false, + }, + http: { + timeout: 10, + }, + phases: [{ + duration: 10, + arrivalRate: 1, + }], + }, +}; diff --git a/test/assets/runner/.mocharc.js b/test/assets/runner/.mocharc.js new file mode 100644 index 0000000..0e590f5 --- /dev/null +++ b/test/assets/runner/.mocharc.js @@ -0,0 +1,30 @@ +module.exports = { + reporter: "mochawesome", // Reporter name. + reporterOptions: { // Reporter settings object. + reportDir: 'reports/func/', + reportFilename: 'index.js', + }, + color: true, // Color TTY output from reporter? + // allowUncaught: "boolean", // Propagate uncaught errors? + // asyncOnly: "boolean", // Force done callback or promise? + // bail: "boolean", // Bail after first test failure? + // checkLeaks: "boolean", // If true, check leaks. + // delay: "boolean", // Delay root suite execution? + // enableTimeouts: "boolean", // Enable timeouts? + // fgrep: "string", // Test filter given string. + // forbidOnly: "boolean", // Tests marked only fail the suite? + // forbidPending: "boolean", // Pending tests fail the suite? + // fullStackTrace: "boolean", // Full stacktrace upon failure? + // global: "Array:string", // Variables expected in global scope. + // grep: "RegExp | string", // Test filter given regular expression. + // growl: "boolean", // Enable desktop notifications? + // hideDiff: "boolean", // Suppress diffs from failures? + // ignoreLeaks: "boolean", // Ignore global leaks? + // invert: "boolean", // Invert test filter matches? + // noHighlighting: "boolean", // Disable syntax highlighting? + // retries: "number", // Number of times to retry failed tests. + // slow: "number", // Slow threshold value. + // timeout: "number | string", // Timeout threshold value. + // ui: "string", // Interface name. + // useInlineDiffs: "boolean", // Use inline diffs? +}; diff --git a/test/assets/runner/Test.postman_collection.json b/test/assets/runner/Test.postman_collection.json new file mode 100644 index 0000000..cf7ed24 --- /dev/null +++ b/test/assets/runner/Test.postman_collection.json @@ -0,0 +1,34 @@ +{ + "info": { + "_postman_id": "test", + "name": "Test", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "Test", + "item": [ + { + "name": "Get", + "request": { + "method": "GET", + "header": [], + "url": { + "raw": "localhost:4000/test", + "host": [ + "localhost" + ], + "port": "4000", + "path": [ + "test" + ] + } + }, + "response": [] + } + ], + "protocolProfileBehavior": {} + } + ], + "protocolProfileBehavior": {} +} \ No newline at end of file diff --git a/test/assets/runner/func/test.js b/test/assets/runner/func/test.js new file mode 100644 index 0000000..2e0a15f --- /dev/null +++ b/test/assets/runner/func/test.js @@ -0,0 +1,8 @@ +const { describe, it, beforeEach } = require('mocha'); +const { expect } = require('chai'); + +describe('Test', function () { + it('Returns True', function () { + expect(true).to.be.true; + }); +}); diff --git a/test/assets/runner/load/test.js b/test/assets/runner/load/test.js new file mode 100644 index 0000000..e69de29 diff --git a/test/driverProvider.spec.js b/test/driverProvider.spec.js new file mode 100644 index 0000000..1b6d45d --- /dev/null +++ b/test/driverProvider.spec.js @@ -0,0 +1,45 @@ +const { describe, it } = require('mocha'); +const { expect } = require('chai'); + +const DriverProvider = require('../src/DriverProvider'); +const mochaDriver = require('../src/drivers/func/mocha'); +const artilleryDriver = require('../src/drivers/load/artillery'); + +describe('Driver Provider', function () { + describe('#resolve', function () { + it('should resolve path to the required func driver', function () { + DriverProvider.setRunType('func'); + const resolved = DriverProvider.resolve(); + + expect(resolved).to.be.equal(mochaDriver); + }); + + it('should resolve path to the required load driver', function () { + DriverProvider.setRunType('load'); + const resolved = DriverProvider.resolve(); + + expect(resolved).to.be.equal(artilleryDriver); + }); + }); + + describe('#setRunType', function () { + it('should set passed run type', function () { + const runType = 'func'; + + DriverProvider.setRunType(runType); + expect(DriverProvider.runType).to.be.equal(runType); + }); + }); + + describe('#setDrivers', function () { + it('should set passed drivers', function () { + const drivers = { + func: 'jest', + load: 'gatling' + }; + + DriverProvider.setDrivers(drivers); + expect(DriverProvider.drivers).to.be.equal(drivers); + }); + }); +}); diff --git a/test/runner.spec.js b/test/runner.spec.js new file mode 100644 index 0000000..fdb6247 --- /dev/null +++ b/test/runner.spec.js @@ -0,0 +1,179 @@ +const { describe, it } = require('mocha'); +const { expect } = require('chai'); + +const path = require('path'); +const Readable = require('stream').Readable; +const config = require('../config'); +const testCollection = require('./assets/runner/Test.postman_collection'); + +const Runner = require('../src/Runner'); + +describe('Runner', function () { + describe('constructor', function () { + it('should throw an error without configuration argument', function () { + const runner = () => ( new Runner() ); + + expect(runner).to.throw(); + }); + + it('should create runner with correct dir path', function () { + const testsDir = path.resolve(process.cwd(), 'test', 'assets', 'runner'); + const runner = new Runner({ + testsDir, + }); + const testsDirFunc = path.resolve(testsDir, 'func'); + const testsDirLoad = path.resolve(testsDir, 'load'); + + expect(runner.func.dir).to.be.equal(testsDirFunc); + expect(runner.load.dir).to.be.equal(testsDirLoad); + }); + + it('should set passed postman collection', function () { + new Runner({ + postmanCollection: testCollection, + }); + + expect(config.get('postman:collection')).to.deep.equal(testCollection); + }); + + it('should create readable logstream', function () { + const runner = new Runner({}); + + expect(runner.logStream).to.be.instanceof(Readable); + }); + + it('should create runner with correct passed configs', function () { + const assetsPath = path.resolve(process.cwd(), 'test', 'assets', 'runner'); + const configsSettings = { + funcCfg: path.join(assetsPath, '.mocharc.js'), + loadCfg: path.join(assetsPath, '.artilleryrc.js'), + }; + new Runner(configsSettings); + + expect(config.get('func_cfg')).to.be.equal(configsSettings.funcCfg); + expect(config.get('load_cfg')).to.be.equal(configsSettings.loadCfg); + }); + + it('should create runner with correct default configs', function () { + const configPath = path.resolve(process.cwd(), 'config'); + const configsSettings = { + funcCfg: path.join(configPath, '.mocharc.js'), + loadCfg: path.join(configPath, '.artilleryrc.js'), + }; + + new Runner({}); + + expect(config.get('func_cfg')).to.be.equal(configsSettings.funcCfg); + expect(config.get('load_cfg')).to.be.equal(configsSettings.loadCfg); + }); + }); + + describe('#run', function () { + it('should fail if no tests are specified', function () { + expect(true).to.be.true; + }); + + it('should run tests with default parameters', async function () { + const testsDir = path.resolve(process.cwd(), 'test', 'assets', 'runner'); + const objKeys = ['start', 'end', 'suites', 'tests', 'passes', 'pending', 'failures', 'duration']; + const runner = new Runner({ + testsDir, + }); + + const res = await runner.run('func', false, [], { + onTestEnd: () => {} + }); + + expect(res).to.have.all.keys(objKeys); + expect(res.suites).to.be.equal(1); + }); + + it('should run tests with load type', function () { + expect(true).to.be.true; + }); + + it('should run tests with passed files', async function () { + const runner = new Runner({}); + const filePath = path.join(path.resolve(process.cwd(), 'test', 'assets', 'runner', 'func'), 'test.js'); + + const res = await runner.run('func', false, [filePath], { + onTestEnd: () => {}, + }); + + expect(res.suites).to.equal(1); + expect(res.tests).to.equal(1); + expect(res.passes).to.equal(1); + expect(res.failures).to.equal(0); + }); + + it('should call onTestEnd function each time a test runs', async function () { + const testsDir = path.resolve(process.cwd(), 'test', 'assets', 'runner'); + const runner = new Runner({ + testsDir, + }); + let counter = 0; + + await runner.run('func', false, [], { + onTestEnd: () => counter++, + }); + + expect(counter).to.be.equal(1); + }); + }); + + describe('#getCurrentType', function () { + it('should return current type', function () { + const runner = new Runner({}); + + expect(runner.getCurrentType()).to.be.equal(runner.type); + }); + }); + + describe('#setFilters', function () { + it('should set passed filters', function () { + const filters = { + tests: { + func: 'mocha', + load: 'artillery' + } + }; + const runner = new Runner({}); + + runner.setFilters(filters); + + expect(runner.filters).to.be.equal(filters); + }); + }); + + describe('#getStatus', function () { + it('should return status if tests run successfully', async function () { + const testsDir = path.resolve(process.cwd(), 'test', 'assets', 'runner'); + const runner = new Runner({ + testsDir, + }); + + await runner.run('func', false, [], { + onTestEnd: () => {}, + }); + + expect(runner.getStatus()).to.be.equal('inPending'); + }); + }); + + describe('#getFilter', function () { + it('should return files according to type', async function () { + const testsDir = path.resolve(process.cwd(), 'test', 'assets', 'runner'); + const runner = new Runner({ + testsDir, + }); + + expect( await runner.getFilter('func') ).to.deep.equal({ + [path.join(testsDir, 'func', 'test.js')]: true, + }); + + expect( await runner.getFilter('load') ).to.deep.equal({ + [path.join(testsDir, 'load', 'test.js')]: true, + }); + }); + }); +}); diff --git a/test/service.spec.js b/test/service.spec.js new file mode 100644 index 0000000..18e5fcc --- /dev/null +++ b/test/service.spec.js @@ -0,0 +1,57 @@ +const { describe, it } = require('mocha'); +const { expect } = require('chai'); + +const Service = require('../src/Service'); +const DriverProvider = require('../src/DriverProvider'); + +describe('Service', function () { + describe('constructor', function () { + it('should set host from passed options', function () { + const host = { + develop: 'http://develop', + testing: 'http://testing', + product: 'http://product' + }; + const service = new Service({ + host, + }); + + expect(service.host).to.be.equal(host); + expect(service.headers).to.deep.equal({}); + }); + + it('should set headers from passed options', function () { + const headers = { + develop: 'header1', + testing: 'header2', + product: 'header3' + }; + const service = new Service({ + headers, + }); + + expect(service.headers).to.be.equal(headers); + }); + }); + + describe('#send', function () { + it('should return methods', function () { + DriverProvider.runType = 'func'; + const service = new Service({ + host: { + develop: 'http://develop', + testing: 'http://testing', + product: 'http://product' + }, + headers: { + develop: 'header1', + testing: 'header2', + product: 'header3' + } + }); + + const res = service.send({}); + expect(Object.keys(res)).to.deep.equal(['getTraceLink', 'send']); + }); + }); +}); diff --git a/test/services.spec.js b/test/services.spec.js new file mode 100644 index 0000000..1e9de03 --- /dev/null +++ b/test/services.spec.js @@ -0,0 +1,36 @@ +const { describe, it } = require('mocha'); +const chai = require('chai'), spies = require('chai-spies'); +chai.use(spies); +const expect = chai.expect; +const path = require('path'); +const requireDir = require('require-dir'); + +const Services = require('../src/Services'); + +describe('Services', function () { + describe('#init', function () { + it('should require directory', function () { + const servicePath = path.join(process.cwd(), 'test', 'assets', 'services'); + const services = new Services(); + const spyFunc = chai.spy(requireDir); + + chai.spy.on(services, 'init', spyFunc); + services.init(servicePath); + + expect(spyFunc).to.have.been.called.with.exactly(servicePath); + }); + }); + + describe('#register', function () { + it('should set new service instance', function () { + const services = new Services(); + services.register('Jaeger', { + host: { + debug: 'http://localhost:16686' + }, + }); + + expect(services.Jaeger.host.debug).to.be.equal('http://localhost:16686'); + }); + }); +});