From edc04b5976ea047212fea594fe3512adf2e7c301 Mon Sep 17 00:00:00 2001 From: Honza Javorek Date: Fri, 22 Mar 2019 21:51:02 +0100 Subject: [PATCH] test: split dredd-test.js into multiple better themed files --- test/integration/apiary-reporter-test.js | 374 +++++++++++++++++++++++ test/integration/dredd-test.js | 317 +------------------ test/integration/openapi2-test.js | 152 +++++++++ 3 files changed, 527 insertions(+), 316 deletions(-) create mode 100644 test/integration/apiary-reporter-test.js create mode 100644 test/integration/openapi2-test.js diff --git a/test/integration/apiary-reporter-test.js b/test/integration/apiary-reporter-test.js new file mode 100644 index 000000000..2a649afa9 --- /dev/null +++ b/test/integration/apiary-reporter-test.js @@ -0,0 +1,374 @@ +const bodyParser = require('body-parser'); +const clone = require('clone'); +const express = require('express'); +const fs = require('fs'); +const { assert } = require('chai'); + +const logger = require('../../lib/logger'); +const reporterOutputLogger = require('../../lib/reporters/reporterOutputLogger'); +const Dredd = require('../../lib/Dredd'); + +const PORT = 9876; + +let exitStatus; + +let output = ''; + +function execCommand(options = {}, cb) { + output = ''; + exitStatus = null; + let finished = false; + if (!options.server) { options.server = `http://127.0.0.1:${PORT}`; } + if (!options.loglevel) { options.loglevel = 'warning'; } + new Dredd(options).run((error, stats = {}) => { + if (!finished) { + finished = true; + if (error ? error.message : undefined) { + output += error.message; + } + exitStatus = (error || (((1 * stats.failures) + (1 * stats.errors)) > 0)) ? 1 : 0; + cb(); + } + }); +} + + +function record(transport, level, message) { + output += `\n${level}: ${message}`; +} + + +// These tests were separated out from a larger file. They deserve a rewrite, +// see https://github.com/apiaryio/dredd/issues/1288 +describe('Apiary reporter', () => { + before(() => { + logger.transports.console.silent = true; + logger.on('logging', record); + + reporterOutputLogger.transports.console.silent = true; + reporterOutputLogger.on('logging', record); + }); + + after(() => { + logger.transports.console.silent = false; + logger.removeListener('logging', record); + + reporterOutputLogger.transports.console.silent = false; + reporterOutputLogger.removeListener('logging', record); + }); + + describe("when using reporter -r apiary with 'debug' logging with custom apiaryApiKey and apiaryApiName", () => { + let server; + let server2; + let receivedRequest; + let receivedRequestTestRuns; + let receivedHeaders; + let receivedHeadersRuns; + exitStatus = null; + + before((done) => { + const cmd = { + options: { + path: ['./test/fixtures/single-get.apib'], + reporter: ['apiary'], + loglevel: 'debug', + }, + custom: { + apiaryApiUrl: `http://127.0.0.1:${PORT + 1}`, + apiaryApiKey: 'the-key', + apiaryApiName: 'the-api-name', + }, + }; + + receivedHeaders = {}; + receivedHeadersRuns = {}; + + const apiary = express(); + const app = express(); + + apiary.use(bodyParser.json({ size: '5mb' })); + + apiary.post('/apis/*', (req, res) => { + if (req.body && (req.url.indexOf('/tests/steps') > -1)) { + if (!receivedRequest) { receivedRequest = clone(req.body); } + Object.keys(req.headers).forEach((name) => { + receivedHeaders[name.toLowerCase()] = req.headers[name]; + }); + } + if (req.body && (req.url.indexOf('/tests/runs') > -1)) { + if (!receivedRequestTestRuns) { receivedRequestTestRuns = clone(req.body); } + Object.keys(req.headers).forEach((name) => { + receivedHeadersRuns[name.toLowerCase()] = req.headers[name]; + }); + } + res.status(201).json({ + _id: '1234_id', + testRunId: '6789_testRunId', + reportUrl: 'http://url.me/test/run/1234_id', + }); + }); + + apiary.all('*', (req, res) => res.json({})); + + app.get('/machines', (req, res) => res.json([{ type: 'bulldozer', name: 'willy' }])); + + server = app.listen(PORT, () => { + server2 = apiary.listen((PORT + 1), () => { + execCommand(cmd, () => server2.close(() => server.close(() => done()))); + }); + }); + }); + + it('should not print warning about missing Apiary API settings', () => assert.notInclude(output, 'Apiary API Key or API Project Subdomain were not provided.')); + + it('should contain Authentication header thanks to apiaryApiKey and apiaryApiName configuration', () => { + assert.propertyVal(receivedHeaders, 'authentication', 'Token the-key'); + assert.propertyVal(receivedHeadersRuns, 'authentication', 'Token the-key'); + }); + + it('should send the test-run as a non-public one', () => { + assert.isObject(receivedRequestTestRuns); + assert.propertyVal(receivedRequestTestRuns, 'public', false); + }); + + it('should print using the new reporter', () => assert.include(output, 'http://url.me/test/run/1234_id')); + + it('should send results from Gavel', () => { + assert.isObject(receivedRequest); + assert.nestedProperty(receivedRequest, 'resultData.request'); + assert.nestedProperty(receivedRequest, 'resultData.realResponse'); + assert.nestedProperty(receivedRequest, 'resultData.expectedResponse'); + assert.nestedProperty(receivedRequest, 'resultData.result.body.validator'); + assert.nestedProperty(receivedRequest, 'resultData.result.headers.validator'); + assert.nestedProperty(receivedRequest, 'resultData.result.statusCode.validator'); + + it('prints out an error message', () => assert.notEqual(exitStatus, 0)); + }); + }); + + describe('when called with arguments', () => { + describe("when using reporter -r apiary and the server isn't running", () => { + let server2; + let receivedRequest; + exitStatus = null; + + before((done) => { + const cmd = { + options: { + path: ['./test/fixtures/single-get.apib'], + reporter: ['apiary'], + loglevel: 'debug', + }, + custom: { + apiaryReporterEnv: { + APIARY_API_URL: `http://127.0.0.1:${PORT + 1}`, + }, + }, + }; + + const apiary = express(); + + apiary.use(bodyParser.json({ size: '5mb' })); + + apiary.post('/apis/*', (req, res) => { + if (req.body && (req.url.indexOf('/tests/steps') > -1)) { + if (!receivedRequest) { receivedRequest = clone(req.body); } + } + res.status(201).json({ + _id: '1234_id', + testRunId: '6789_testRunId', + reportUrl: 'http://url.me/test/run/1234_id', + }); + }); + + apiary.all('*', (req, res) => res.json({})); + + server2 = apiary.listen((PORT + 1), () => execCommand(cmd, () => server2.close(() => {}))); + + server2.on('close', done); + }); + + it('should print using the reporter', () => assert.include(output, 'http://url.me/test/run/1234_id')); + + it('should send results from gavel', () => { + assert.isObject(receivedRequest); + assert.nestedProperty(receivedRequest, 'resultData.request'); + assert.nestedProperty(receivedRequest, 'resultData.expectedResponse'); + assert.nestedProperty(receivedRequest, 'resultData.result.general'); + }); + + it('report should have message about server being down', () => { + const message = receivedRequest.resultData.result.general[0].message; + assert.include(message, 'connect'); + }); + }); + + describe('when using reporter -r apiary', () => { + let server; + let server2; + let receivedRequest; + exitStatus = null; + + before((done) => { + const cmd = { + options: { + path: ['./test/fixtures/single-get.apib'], + reporter: ['apiary'], + loglevel: 'debug', + }, + custom: { + apiaryReporterEnv: { + APIARY_API_URL: `http://127.0.0.1:${PORT + 1}`, + }, + }, + }; + + const apiary = express(); + const app = express(); + + apiary.use(bodyParser.json({ size: '5mb' })); + + apiary.post('/apis/*', (req, res) => { + if (req.body && (req.url.indexOf('/tests/steps') > -1)) { + if (!receivedRequest) { receivedRequest = clone(req.body); } + } + res.status(201).json({ + _id: '1234_id', + testRunId: '6789_testRunId', + reportUrl: 'http://url.me/test/run/1234_id', + }); + }); + + apiary.all('*', (req, res) => res.json({})); + + app.get('/machines', (req, res) => res.json([{ type: 'bulldozer', name: 'willy' }])); + + server = app.listen(PORT, () => { server2 = apiary.listen((PORT + 1), () => {}); }); + + execCommand(cmd, () => server2.close(() => server.close(() => {}))); + + server.on('close', done); + }); + + it('should print warning about missing Apiary API settings', () => assert.include(output, 'Apiary API Key or API Project Subdomain were not provided.')); + + it('should print link to documentation', () => assert.include(output, 'https://dredd.org/en/latest/how-to-guides/#using-apiary-reporter-and-apiary-tests')); + + it('should print using the new reporter', () => assert.include(output, 'http://url.me/test/run/1234_id')); + + it('should send results from Gavel', () => { + assert.isObject(receivedRequest); + assert.nestedProperty(receivedRequest, 'resultData.request'); + assert.nestedProperty(receivedRequest, 'resultData.realResponse'); + assert.nestedProperty(receivedRequest, 'resultData.expectedResponse'); + assert.nestedProperty(receivedRequest, 'resultData.result.body.validator'); + assert.nestedProperty(receivedRequest, 'resultData.result.headers.validator'); + assert.nestedProperty(receivedRequest, 'resultData.result.statusCode.validator'); + }); + }); + }); + + describe("when API description document should be loaded from 'http(s)://...' url", () => { + let app; + let server; + let connectedToServer = null; + let notFound; + let fileFound; + + const errorCmd = { + server: `http://127.0.0.1:${PORT + 1}`, + options: { + path: [`http://127.0.0.1:${PORT + 1}/connection-error.apib`], + }, + }; + + const wrongCmd = { + options: { + path: [`http://127.0.0.1:${PORT}/not-found.apib`], + }, + }; + + const goodCmd = { + options: { + path: [`http://127.0.0.1:${PORT}/file.apib`], + }, + }; + + afterEach(() => { connectedToServer = null; }); + + before((done) => { + app = express(); + + app.use((req, res, next) => { + connectedToServer = true; + next(); + }); + + app.get('/', (req, res) => res.sendStatus(404)); + + app.get('/file.apib', (req, res) => { + fileFound = true; + res.type('text'); + fs.createReadStream('./test/fixtures/single-get.apib').pipe(res); + }); + + app.get('/machines', (req, res) => res.json([{ type: 'bulldozer', name: 'willy' }])); + + app.get('/not-found.apib', (req, res) => { + notFound = true; + res.status(404).end(); + }); + + server = app.listen(PORT, () => done()); + }); + + after(done => server.close(() => { + app = null; + server = null; + done(); + })); + + describe('and I try to load a file from bad hostname at all', () => { + before(done => execCommand(errorCmd, () => done())); + + after(() => { connectedToServer = null; }); + + it('should not send a GET to the server', () => assert.isNull(connectedToServer)); + + it('should exit with status 1', () => assert.equal(exitStatus, 1)); + + it('should print error message to the output', () => { + assert.include(output, 'Error when loading file from URL'); + assert.include(output, 'connection-error.apib'); + }); + }); + + describe('and I try to load a file that does not exist from an existing server', () => { + before(done => execCommand(wrongCmd, () => done())); + + after(() => { connectedToServer = null; }); + + it('should connect to the right server', () => assert.isTrue(connectedToServer)); + + it('should send a GET to server at wrong URL', () => assert.isTrue(notFound)); + + it('should exit with status 1', () => assert.equal(exitStatus, 1)); + + it('should print error message to the output', () => { + assert.include(output, 'Server did not send any blueprint back'); + assert.include(output, 'responded with status code 404'); + assert.include(output, 'not-found.apib'); + }); + }); + + describe('and I try to load a file that actually is there', () => { + before(done => execCommand(goodCmd, () => done())); + + it('should send a GET to the right server', () => assert.isTrue(connectedToServer)); + + it('should send a GET to server at good URL', () => assert.isTrue(fileFound)); + + it('should exit with status 0', () => assert.equal(exitStatus, 0)); + }); + }); +}); diff --git a/test/integration/dredd-test.js b/test/integration/dredd-test.js index f5b6e702c..c0e185e43 100644 --- a/test/integration/dredd-test.js +++ b/test/integration/dredd-test.js @@ -1,5 +1,3 @@ -const bodyParser = require('body-parser'); -const clone = require('clone'); const express = require('express'); const fs = require('fs'); const { assert } = require('chai'); @@ -38,7 +36,7 @@ function record(transport, level, message) { } -describe('Dredd class Integration', () => { +describe('Dredd', () => { before(() => { logger.transports.console.silent = true; logger.on('logging', record); @@ -97,97 +95,6 @@ describe('Dredd class Integration', () => { }); }); - - describe("when using reporter -r apiary with 'debug' logging with custom apiaryApiKey and apiaryApiName", () => { - let server; - let server2; - let receivedRequest; - let receivedRequestTestRuns; - let receivedHeaders; - let receivedHeadersRuns; - exitStatus = null; - - before((done) => { - const cmd = { - options: { - path: ['./test/fixtures/single-get.apib'], - reporter: ['apiary'], - loglevel: 'debug', - }, - custom: { - apiaryApiUrl: `http://127.0.0.1:${PORT + 1}`, - apiaryApiKey: 'the-key', - apiaryApiName: 'the-api-name', - }, - }; - - receivedHeaders = {}; - receivedHeadersRuns = {}; - - const apiary = express(); - const app = express(); - - apiary.use(bodyParser.json({ size: '5mb' })); - - apiary.post('/apis/*', (req, res) => { - if (req.body && (req.url.indexOf('/tests/steps') > -1)) { - if (!receivedRequest) { receivedRequest = clone(req.body); } - Object.keys(req.headers).forEach((name) => { - receivedHeaders[name.toLowerCase()] = req.headers[name]; - }); - } - if (req.body && (req.url.indexOf('/tests/runs') > -1)) { - if (!receivedRequestTestRuns) { receivedRequestTestRuns = clone(req.body); } - Object.keys(req.headers).forEach((name) => { - receivedHeadersRuns[name.toLowerCase()] = req.headers[name]; - }); - } - res.status(201).json({ - _id: '1234_id', - testRunId: '6789_testRunId', - reportUrl: 'http://url.me/test/run/1234_id', - }); - }); - - apiary.all('*', (req, res) => res.json({})); - - app.get('/machines', (req, res) => res.json([{ type: 'bulldozer', name: 'willy' }])); - - server = app.listen(PORT, () => { - server2 = apiary.listen((PORT + 1), () => { - execCommand(cmd, () => server2.close(() => server.close(() => done()))); - }); - }); - }); - - it('should not print warning about missing Apiary API settings', () => assert.notInclude(output, 'Apiary API Key or API Project Subdomain were not provided.')); - - it('should contain Authentication header thanks to apiaryApiKey and apiaryApiName configuration', () => { - assert.propertyVal(receivedHeaders, 'authentication', 'Token the-key'); - assert.propertyVal(receivedHeadersRuns, 'authentication', 'Token the-key'); - }); - - it('should send the test-run as a non-public one', () => { - assert.isObject(receivedRequestTestRuns); - assert.propertyVal(receivedRequestTestRuns, 'public', false); - }); - - it('should print using the new reporter', () => assert.include(output, 'http://url.me/test/run/1234_id')); - - it('should send results from Gavel', () => { - assert.isObject(receivedRequest); - assert.nestedProperty(receivedRequest, 'resultData.request'); - assert.nestedProperty(receivedRequest, 'resultData.realResponse'); - assert.nestedProperty(receivedRequest, 'resultData.expectedResponse'); - assert.nestedProperty(receivedRequest, 'resultData.result.body.validator'); - assert.nestedProperty(receivedRequest, 'resultData.result.headers.validator'); - assert.nestedProperty(receivedRequest, 'resultData.result.statusCode.validator'); - - it('prints out an error message', () => assert.notEqual(exitStatus, 0)); - }); - }); - - describe('when called with arguments', () => { describe('--path argument is a string', () => { before((done) => { @@ -213,129 +120,8 @@ describe('Dredd class Integration', () => { it('prints out ok', () => assert.equal(exitStatus, 0)); }); - - describe("when using reporter -r apiary and the server isn't running", () => { - let server2; - let receivedRequest; - exitStatus = null; - - before((done) => { - const cmd = { - options: { - path: ['./test/fixtures/single-get.apib'], - reporter: ['apiary'], - loglevel: 'debug', - }, - custom: { - apiaryReporterEnv: { - APIARY_API_URL: `http://127.0.0.1:${PORT + 1}`, - }, - }, - }; - - const apiary = express(); - - apiary.use(bodyParser.json({ size: '5mb' })); - - apiary.post('/apis/*', (req, res) => { - if (req.body && (req.url.indexOf('/tests/steps') > -1)) { - if (!receivedRequest) { receivedRequest = clone(req.body); } - } - res.status(201).json({ - _id: '1234_id', - testRunId: '6789_testRunId', - reportUrl: 'http://url.me/test/run/1234_id', - }); - }); - - apiary.all('*', (req, res) => res.json({})); - - server2 = apiary.listen((PORT + 1), () => execCommand(cmd, () => server2.close(() => {}))); - - server2.on('close', done); - }); - - it('should print using the reporter', () => assert.include(output, 'http://url.me/test/run/1234_id')); - - it('should send results from gavel', () => { - assert.isObject(receivedRequest); - assert.nestedProperty(receivedRequest, 'resultData.request'); - assert.nestedProperty(receivedRequest, 'resultData.expectedResponse'); - assert.nestedProperty(receivedRequest, 'resultData.result.general'); - }); - - it('report should have message about server being down', () => { - const message = receivedRequest.resultData.result.general[0].message; - assert.include(message, 'connect'); - }); - }); - - describe('when using reporter -r apiary', () => { - let server; - let server2; - let receivedRequest; - exitStatus = null; - - before((done) => { - const cmd = { - options: { - path: ['./test/fixtures/single-get.apib'], - reporter: ['apiary'], - loglevel: 'debug', - }, - custom: { - apiaryReporterEnv: { - APIARY_API_URL: `http://127.0.0.1:${PORT + 1}`, - }, - }, - }; - - const apiary = express(); - const app = express(); - - apiary.use(bodyParser.json({ size: '5mb' })); - - apiary.post('/apis/*', (req, res) => { - if (req.body && (req.url.indexOf('/tests/steps') > -1)) { - if (!receivedRequest) { receivedRequest = clone(req.body); } - } - res.status(201).json({ - _id: '1234_id', - testRunId: '6789_testRunId', - reportUrl: 'http://url.me/test/run/1234_id', - }); - }); - - apiary.all('*', (req, res) => res.json({})); - - app.get('/machines', (req, res) => res.json([{ type: 'bulldozer', name: 'willy' }])); - - server = app.listen(PORT, () => { server2 = apiary.listen((PORT + 1), () => {}); }); - - execCommand(cmd, () => server2.close(() => server.close(() => {}))); - - server.on('close', done); - }); - - it('should print warning about missing Apiary API settings', () => assert.include(output, 'Apiary API Key or API Project Subdomain were not provided.')); - - it('should print link to documentation', () => assert.include(output, 'https://dredd.org/en/latest/how-to-guides/#using-apiary-reporter-and-apiary-tests')); - - it('should print using the new reporter', () => assert.include(output, 'http://url.me/test/run/1234_id')); - - it('should send results from Gavel', () => { - assert.isObject(receivedRequest); - assert.nestedProperty(receivedRequest, 'resultData.request'); - assert.nestedProperty(receivedRequest, 'resultData.realResponse'); - assert.nestedProperty(receivedRequest, 'resultData.expectedResponse'); - assert.nestedProperty(receivedRequest, 'resultData.result.body.validator'); - assert.nestedProperty(receivedRequest, 'resultData.result.headers.validator'); - assert.nestedProperty(receivedRequest, 'resultData.result.statusCode.validator'); - }); - }); }); - describe("when API description document should be loaded from 'http(s)://...' url", () => { let app; let server; @@ -440,105 +226,4 @@ describe('Dredd class Integration', () => { it('should exit with status 0', () => assert.equal(exitStatus, 0)); }); }); - - describe('when OpenAPI 2 document has multiple responses', () => { - const reTransaction = /(skip|fail): (\w+) \((\d+)\) \/honey/g; - let actual; - - before(done => execCommand({ - options: { - path: './test/fixtures/multiple-responses.yaml', - }, - }, - (err) => { - let groups; - const matches = []; - // eslint-disable-next-line - while (groups = reTransaction.exec(output)) { matches.push(groups); } - actual = matches.map((match) => { - const keyMap = { - 0: 'name', 1: 'action', 2: 'method', 3: 'statusCode', - }; - return match.reduce((result, element, i) => Object.assign(result, { [keyMap[i]]: element }), - {}); - }); - done(err); - })); - - it('recognizes all 3 transactions', () => assert.equal(actual.length, 3)); - - [ - { action: 'skip', statusCode: '400' }, - { action: 'skip', statusCode: '500' }, - { action: 'fail', statusCode: '200' }, - ].forEach((expected, i) => context(`the transaction #${i + 1}`, () => { - it(`has status code ${expected.statusCode}`, () => assert.equal(expected.statusCode, actual[i].statusCode)); - it(`is ${expected.action === 'skip' ? '' : 'not '}skipped by default`, () => assert.equal(expected.action, actual[i].action)); - })); - }); - - describe('when OpenAPI 2 document has multiple responses and hooks unskip some of them', () => { - const reTransaction = /(skip|fail): (\w+) \((\d+)\) \/honey/g; - let actual; - - before(done => execCommand({ - options: { - path: './test/fixtures/multiple-responses.yaml', - hookfiles: './test/fixtures/openapi2-multiple-responses.js', - }, - }, - (err) => { - let groups; - const matches = []; - // eslint-disable-next-line - while (groups = reTransaction.exec(output)) { matches.push(groups); } - actual = matches.map((match) => { - const keyMap = { - 0: 'name', 1: 'action', 2: 'method', 3: 'statusCode', - }; - return match.reduce((result, element, i) => Object.assign(result, { [keyMap[i]]: element }), - {}); - }); - done(err); - })); - - it('recognizes all 3 transactions', () => assert.equal(actual.length, 3)); - - [ - { action: 'skip', statusCode: '400' }, - { action: 'fail', statusCode: '200' }, - { action: 'fail', statusCode: '500' }, // Unskipped in hooks - ].forEach((expected, i) => context(`the transaction #${i + 1}`, () => { - it(`has status code ${expected.statusCode}`, () => assert.equal(expected.statusCode, actual[i].statusCode)); - - const defaultMessage = `is ${expected.action === 'skip' ? '' : 'not '}skipped by default`; - const unskippedMessage = 'is unskipped in hooks'; - it(`${expected.statusCode === '500' ? unskippedMessage : defaultMessage}`, () => assert.equal(expected.action, actual[i].action)); - })); - }); - - describe('when using OpenAPI 2 document with hooks', () => { - const reTransactionName = /hook: (.+)/g; - let matches; - - before(done => execCommand({ - options: { - path: './test/fixtures/multiple-responses.yaml', - hookfiles: './test/fixtures/openapi2-transaction-names.js', - }, - }, - (err) => { - let groups; - matches = []; - // eslint-disable-next-line - while (groups = reTransactionName.exec(output)) { matches.push(groups[1]); } - done(err); - })); - - it('transaction names contain status code and content type', () => assert.deepEqual(matches, [ - '/honey > GET > 200 > application/json', - '/honey > GET > 400 > application/json', - '/honey > GET > 500 > application/json', - ])); - }); }); diff --git a/test/integration/openapi2-test.js b/test/integration/openapi2-test.js new file mode 100644 index 000000000..7576b28d6 --- /dev/null +++ b/test/integration/openapi2-test.js @@ -0,0 +1,152 @@ +const { assert } = require('chai'); + +const logger = require('../../lib/logger'); +const reporterOutputLogger = require('../../lib/reporters/reporterOutputLogger'); +const Dredd = require('../../lib/Dredd'); + +const PORT = 9876; + +let output = ''; + +function execCommand(options = {}, cb) { + output = ''; + let finished = false; + if (!options.server) { options.server = `http://127.0.0.1:${PORT}`; } + if (!options.loglevel) { options.loglevel = 'warning'; } + new Dredd(options).run((error) => { + if (!finished) { + finished = true; + if (error ? error.message : undefined) { + output += error.message; + } + cb(); + } + }); +} + + +function record(transport, level, message) { + output += `\n${level}: ${message}`; +} + + +// These tests were separated out from a larger file. They deserve a rewrite, +// see https://github.com/apiaryio/dredd/issues/1288 +describe('OpenAPI 2', () => { + before(() => { + logger.transports.console.silent = true; + logger.on('logging', record); + + reporterOutputLogger.transports.console.silent = true; + reporterOutputLogger.on('logging', record); + }); + + after(() => { + logger.transports.console.silent = false; + logger.removeListener('logging', record); + + reporterOutputLogger.transports.console.silent = false; + reporterOutputLogger.removeListener('logging', record); + }); + + describe('when OpenAPI 2 document has multiple responses', () => { + const reTransaction = /(skip|fail): (\w+) \((\d+)\) \/honey/g; + let actual; + + before(done => execCommand({ + options: { + path: './test/fixtures/multiple-responses.yaml', + }, + }, + (err) => { + let groups; + const matches = []; + // eslint-disable-next-line + while (groups = reTransaction.exec(output)) { matches.push(groups); } + actual = matches.map((match) => { + const keyMap = { + 0: 'name', 1: 'action', 2: 'method', 3: 'statusCode', + }; + return match.reduce((result, element, i) => Object.assign(result, { [keyMap[i]]: element }), + {}); + }); + done(err); + })); + + it('recognizes all 3 transactions', () => assert.equal(actual.length, 3)); + + [ + { action: 'skip', statusCode: '400' }, + { action: 'skip', statusCode: '500' }, + { action: 'fail', statusCode: '200' }, + ].forEach((expected, i) => context(`the transaction #${i + 1}`, () => { + it(`has status code ${expected.statusCode}`, () => assert.equal(expected.statusCode, actual[i].statusCode)); + it(`is ${expected.action === 'skip' ? '' : 'not '}skipped by default`, () => assert.equal(expected.action, actual[i].action)); + })); + }); + + describe('when OpenAPI 2 document has multiple responses and hooks unskip some of them', () => { + const reTransaction = /(skip|fail): (\w+) \((\d+)\) \/honey/g; + let actual; + + before(done => execCommand({ + options: { + path: './test/fixtures/multiple-responses.yaml', + hookfiles: './test/fixtures/openapi2-multiple-responses.js', + }, + }, + (err) => { + let groups; + const matches = []; + // eslint-disable-next-line + while (groups = reTransaction.exec(output)) { matches.push(groups); } + actual = matches.map((match) => { + const keyMap = { + 0: 'name', 1: 'action', 2: 'method', 3: 'statusCode', + }; + return match.reduce((result, element, i) => Object.assign(result, { [keyMap[i]]: element }), + {}); + }); + done(err); + })); + + it('recognizes all 3 transactions', () => assert.equal(actual.length, 3)); + + [ + { action: 'skip', statusCode: '400' }, + { action: 'fail', statusCode: '200' }, + { action: 'fail', statusCode: '500' }, // Unskipped in hooks + ].forEach((expected, i) => context(`the transaction #${i + 1}`, () => { + it(`has status code ${expected.statusCode}`, () => assert.equal(expected.statusCode, actual[i].statusCode)); + + const defaultMessage = `is ${expected.action === 'skip' ? '' : 'not '}skipped by default`; + const unskippedMessage = 'is unskipped in hooks'; + it(`${expected.statusCode === '500' ? unskippedMessage : defaultMessage}`, () => assert.equal(expected.action, actual[i].action)); + })); + }); + + describe('when using OpenAPI 2 document with hooks', () => { + const reTransactionName = /hook: (.+)/g; + let matches; + + before(done => execCommand({ + options: { + path: './test/fixtures/multiple-responses.yaml', + hookfiles: './test/fixtures/openapi2-transaction-names.js', + }, + }, + (err) => { + let groups; + matches = []; + // eslint-disable-next-line + while (groups = reTransactionName.exec(output)) { matches.push(groups[1]); } + done(err); + })); + + it('transaction names contain status code and content type', () => assert.deepEqual(matches, [ + '/honey > GET > 200 > application/json', + '/honey > GET > 400 > application/json', + '/honey > GET > 500 > application/json', + ])); + }); +});