From 4d645ef24d4bb34e85e3e846a5d405630d80698d Mon Sep 17 00:00:00 2001 From: Honza Javorek Date: Wed, 24 Aug 2016 11:45:04 +0200 Subject: [PATCH] fix: Use just the 1st req-res pair within APIB transaction examples BREAKING CHANGE: This change tests and fixes a problem introduced with migration to API Elements in order to support Swagger in Dredd. Original implementation always selected the first request-response pair from each transaction example. This wasn't re-implemented correctly on top of API Elements. Instead, all specified responses are appearing, which breaks Dredd's behavior in many ways. Respective test was ported, but unfortunately with the same mistake. This commit fixes the situation. Some early adopters discovered the issue and considered it to be a new feature, but it really breaks how Dredd should work at the moment and needs to be removed. It leads to duplicate transaction names and other undefined behavior. In order to implement apiaryio/dredd#25 and apiaryio/dredd#78, which many believed happened when they discovered the bug, much more work needs to be done. Namely designing and adopting a new way of addressing transactions in Dredd apiaryio/dredd#227. Closes https://github.com/apiaryio/dredd/issues/615 --- package.json | 2 +- test/fixtures/regression-615.apib | 22 +++++ .../regression-319-354-test.coffee | 1 + test/regressions/regression-615-test.coffee | 93 +++++++++++++++++++ 4 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 test/fixtures/regression-615.apib create mode 100644 test/regressions/regression-615-test.coffee diff --git a/package.json b/package.json index 122b9149e..327374afa 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "clone": "^1.0.2", "coffee-script": "^1.10.0", "colors": "^1.1.2", - "dredd-transactions": "^1.6.0", + "dredd-transactions": "^2.0.0", "file": "^0.2.2", "gavel": "^0.5.3", "glob": "^7.0.5", diff --git a/test/fixtures/regression-615.apib b/test/fixtures/regression-615.apib new file mode 100644 index 000000000..b067abafb --- /dev/null +++ b/test/fixtures/regression-615.apib @@ -0,0 +1,22 @@ +FORMAT: 1A + +# Beehive API + +## Honey [/honey] + +### Retrieve [GET] + ++ Request (application/json) ++ Request (application/xml) ++ Response 200 ++ Response 500 + +### Remove [DELETE] + ++ Request (application/json) ++ Response 200 ++ Response 403 ++ Response 500 + ++ Request (text/plain) ++ Response 200 diff --git a/test/regressions/regression-319-354-test.coffee b/test/regressions/regression-319-354-test.coffee index 1a101686c..9a12e37c4 100644 --- a/test/regressions/regression-319-354-test.coffee +++ b/test/regressions/regression-319-354-test.coffee @@ -30,6 +30,7 @@ parseJSON = (body) -> body +# This can be removed once https://github.com/apiaryio/dredd/issues/341 is done parseOutput = (output) -> # Parse individual entries (deals also with multi-line entries) entries = [] diff --git a/test/regressions/regression-615-test.coffee b/test/regressions/regression-615-test.coffee new file mode 100644 index 000000000..fa8944e50 --- /dev/null +++ b/test/regressions/regression-615-test.coffee @@ -0,0 +1,93 @@ +{assert} = require 'chai' +{exec} = require 'child_process' +express = require 'express' +clone = require 'clone' + + +PORT = 3333 +DREDD_BIN = require.resolve '../../bin/dredd' + + +runDredd = (descriptionFile, cb) -> + result = {} + cmd = "#{DREDD_BIN} #{descriptionFile} http://localhost:#{PORT} -ed --no-color" + + cli = exec cmd, (err, stdout, stderr) -> + result.exitStatus = err?.code or null + result.stdout = '' + stdout + result.stderr = '' + stderr + + cli.on 'close', (code) -> + result.exitStatus ?= code if code + cb null, result + + +parseJSON = (body) -> + return undefined unless body + try + JSON.parse body + catch + body + + +# This can be removed once https://github.com/apiaryio/dredd/issues/341 is done +parseOutput = (output) -> + # Parse individual entries (deals also with multi-line entries) + entries = [] + entry = undefined + for line in output.split /\r?\n/ + match = line.match /^(\w+): (.+)?$/ + if match + if entry + entry.body = entry.body.trim() + entries.push entry + entry = {label: match[1], body: match[2] or ''} + else + entry.body += "\n#{line.trim()}" + + # Correction of following situation: + # + # fail: POST /customers duration: 13ms + # fail: body: At '/name' Invalid type: null (expected string) + # body: At '/shoeSize' Invalid type: string (expected number) + entries = entries.filter (entry, i) -> + previousEntry = entries[i - 1] + if entry.label is 'body' and previousEntry.label is 'fail' + previousEntry.body += '\n' + entry.body + return false + return true + + # Re-arrange data from entries + results = {summary: '', failures: []} + for entry in entries + switch entry.label + when 'complete' then results.summary = entry.body + when 'fail' then results.failures.push entry.body + return results + + +describe 'Regression: Issue #615', -> + requests = [] + results = undefined + + beforeEach (done) -> + app = express() + + # Attaching endpoint for each testing scenario + app.all '/honey', (req, res) -> + res.status(200).send '' + + # Spinning up the Express server, running Dredd, and saving results + server = app.listen PORT, -> + runDredd './test/fixtures/regression-615.apib', (err, result) -> + results = parseOutput result.stdout + server.close done + + it 'outputs no failures', -> + # Intentionally not testing just '.length' as this approach will output the difference + assert.deepEqual results.failures, [] + it 'results in exactly three tests', -> + assert.include results.summary, '3 total' + it 'results in three passing tests', -> + # Ensures just the 200 responses were selected, because the server returns only 200s + assert.include results.summary, '3 passing'