From dbba0cf847bd83222b7d45f376ac0535cb379147 Mon Sep 17 00:00:00 2001 From: Nicholas Palenchar Date: Wed, 8 Jan 2020 20:40:50 -0500 Subject: [PATCH 01/26] wip --- functions/postwomanTesting.js | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 functions/postwomanTesting.js diff --git a/functions/postwomanTesting.js b/functions/postwomanTesting.js new file mode 100644 index 000000000..096ee9d32 --- /dev/null +++ b/functions/postwomanTesting.js @@ -0,0 +1,31 @@ +export default function runTestScriptWitVariables(script, variables) { + + let pw = { + assert + // globals that the script is allowed to have access to. + }; + Object.assign(pw, variables); + + // run pre-request script within this function so that it has access to the pw object. + let errors = null; + try { + new Function("pw", script)(pw); + } + catch (e) { + errors = e; + } + return errors; + +} + +function assert(expression) { + if (!expression) { + throw {name: "PostWomanTestError", message: "expression evaluated to false"} + } +} + +class PostwomanTestFailure { + constructor(message) { + return {message} + } +} From 311d87b22323ea7cf3031138dc62f31769b1b968 Mon Sep 17 00:00:00 2001 From: Nicholas Palenchar Date: Sat, 11 Jan 2020 12:18:29 -0500 Subject: [PATCH 02/26] Expectation class --- functions/postwomanTesting.js | 53 +++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/functions/postwomanTesting.js b/functions/postwomanTesting.js index 096ee9d32..01c792afd 100644 --- a/functions/postwomanTesting.js +++ b/functions/postwomanTesting.js @@ -1,6 +1,7 @@ export default function runTestScriptWitVariables(script, variables) { let pw = { + _errors: [], assert // globals that the script is allowed to have access to. }; @@ -24,6 +25,58 @@ function assert(expression) { } } +function expect(expectValue) { + return new Expectation(expectValue); +} + +class Expectation { + constructor(expectValue, _not, _testReports) { + this.expectValue = expectValue; + this.not = _not || new Expectation(this.expectValue, true); + this._testReports = _testReports; // this values is used within Test.it, which wraps Expectation and passes _testReports value. + this._satisfies = function(targetValue) { + // Used for testing if two values match the expectation, which could be === OR !==, depending on if not + // was used. Expectation#_satisfies prevents the need to have an if(this.not) branch in every test method. + if (this.not === true) { + // test the inverse. this.not is always truthly, but an Expectation that is inverted will always be strictly `true` + return this.expectValue !== targetValue; + } else { + return this.expectValue === targetValue; + } + } + } + _fmtNot(message) { + // given a string with "(not)" in it, replaces with "not" or "", depending if the expectation is expecting the positive or inverse (this._not) + if (this.not === true) { + return message.replace("(not)", "not "); + } else { + return message.replace("(not)", "") + } + } + _fail(message) { + if (this._testReports) { + this._testReports.push({pass: false, message}) + } else { + throw {message} + } + } + _pass(message) { + if (this._testReports) { + this._testReports.push({pass: true, message}); + } else { + return true; + } + } + // TEST METHODS DEFINED BELOW + // these are the usual methods that would follow expect(...) + toBe(value) { + return this._satisfies(value) ? this._pass() : this._fail(this._fmtNot(`Expected ${this.expectValue} (not)to be ${value}`)); + } + toHaveProperty(value) { + return this._satisfies(this.expectValue.hasOwnProperty(value)) ? this._pass() : this._fail(`Expected object ${this.expectValue} to (not)have property ${value}`) + } +} + class PostwomanTestFailure { constructor(message) { return {message} From dce58bdb2fa0e972d588d9ae3aa6ab5cbaefcbfa Mon Sep 17 00:00:00 2001 From: Nicholas Palenchar Date: Sat, 11 Jan 2020 13:01:42 -0500 Subject: [PATCH 03/26] wip - basic test scaffolding --- functions/postwomanTesting.js | 83 ++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 12 deletions(-) diff --git a/functions/postwomanTesting.js b/functions/postwomanTesting.js index 01c792afd..d5311b729 100644 --- a/functions/postwomanTesting.js +++ b/functions/postwomanTesting.js @@ -1,8 +1,12 @@ +import {parse} from "graphql"; + export default function runTestScriptWitVariables(script, variables) { let pw = { _errors: [], - assert + _report: '', + expect, + test // globals that the script is allowed to have access to. }; Object.assign(pw, variables); @@ -16,13 +20,23 @@ export default function runTestScriptWitVariables(script, variables) { errors = e; } return errors; - } -function assert(expression) { - if (!expression) { - throw {name: "PostWomanTestError", message: "expression evaluated to false"} - } +function test(descriptor, func) { + let testReports = []; + let expect = (expectValue) => new Expectation(expectValue, undefined, testReports); + let it = (descriptor, func) => { + testReports.push({descriptor: true, message: descriptor}); + func(); + }; + let xit = (descriptor, func) => { + testReports.push({descriptor: true, message: `⊖ ${descriptor} [skipped]`}) + }; + + func(); + + // TODO: Organieze and generate text report of each {descriptor: true} section in testReports. + // add checkmark or x depending on if each testReport is pass=true or pass=false } function expect(expectValue) { @@ -32,16 +46,21 @@ function expect(expectValue) { class Expectation { constructor(expectValue, _not, _testReports) { this.expectValue = expectValue; - this.not = _not || new Expectation(this.expectValue, true); + this.not = _not || new Expectation(this.expectValue, true, _testReports); this._testReports = _testReports; // this values is used within Test.it, which wraps Expectation and passes _testReports value. - this._satisfies = function(targetValue) { + this._satisfies = function(expectValue, targetValue) { // Used for testing if two values match the expectation, which could be === OR !==, depending on if not // was used. Expectation#_satisfies prevents the need to have an if(this.not) branch in every test method. + // Signature is _satisfies([expectValue,] targetValue): if only one argument is given, it is assumed the targetValue, and expectValue is set to this.expectValue + if (!targetValue) { + targetValue = expectValue; + expectValue = this.expectValue; + } if (this.not === true) { // test the inverse. this.not is always truthly, but an Expectation that is inverted will always be strictly `true` - return this.expectValue !== targetValue; + return expectValue !== targetValue; } else { - return this.expectValue === targetValue; + return expectValue === targetValue; } } } @@ -70,10 +89,50 @@ class Expectation { // TEST METHODS DEFINED BELOW // these are the usual methods that would follow expect(...) toBe(value) { - return this._satisfies(value) ? this._pass() : this._fail(this._fmtNot(`Expected ${this.expectValue} (not)to be ${value}`)); + return this._satisfies(value) + ? this._pass() + : this._fail(this._fmtNot(`Expected ${this.expectValue} (not)to be ${value}`)); } toHaveProperty(value) { - return this._satisfies(this.expectValue.hasOwnProperty(value)) ? this._pass() : this._fail(`Expected object ${this.expectValue} to (not)have property ${value}`) + return this._satisfies(this.expectValue.hasOwnProperty(value), true) + ? this._pass() + : this._fail(this._fmtNot(`Expected object ${this.expectValue} to (not)have property ${value}`)) + } + toBeLevel2xx() { + let code = parseInt(this.expectValue); + if (Number.isNaN(code)) { + return this._fail(`Expecteded 200-level status but could not parse value ${this.expectValue}`); + } + return this._satisfies(code >= 200 && code < 300) + ? this._pass() : + this._fail(this._fmtNot(`Expected ${this.expectValue} to (not)be 200-level status`)); + } + toBeLevel3xx() { + let code = parseInt(this.expectValue); + if (Number.isNaN(code)) { + return this._fail(`Expected 300-level status but could not parse value ${this.expectValue}`); + } + return this._satisfies(code >= 300 && code < 400) + ? this._pass() : + this._fail(this._fmtNot(`Expected ${this.expectValue} to (not)be 300-level status`)); + } + toBeLevel4xx() { + let code = parseInt(this.expectValue); + if (Number.isNaN(code)) { + return this._fail(`Expected 400-level status but could not parse value ${this.expectValue}`); + } + return this._satisfies(code >= 400 && code < 500) + ? this._pass() : + this._fail(this._fmtNot(`Expected ${this.expectValue} to (not)be 400-level status`)); + } + toBeLevel5xx() { + let code = parseInt(this.expectValue); + if (Number.isNaN(code)) { + return this._fail(`Expected 200-level status but could not parse value ${this.expectValue}`); + } + return this._satisfies(code >= 500 && code < 600) + ? this._pass() + : this._fail(this._fmtNot(`Expected ${this.expectValue} to (not)be 500-level status`)); } } From 3ecf62857c57c7c072a1de3bcdfc807ef572ba65 Mon Sep 17 00:00:00 2001 From: Nicholas Palenchar Date: Sat, 18 Jan 2020 12:06:45 -0500 Subject: [PATCH 04/26] :lipstick: add tests section to UI --- pages/index.vue | 3173 ++++++++++++++++++++++++----------------------- 1 file changed, 1617 insertions(+), 1556 deletions(-) diff --git a/pages/index.vue b/pages/index.vue index 71926504f..cc4a8cce1 100644 --- a/pages/index.vue +++ b/pages/index.vue @@ -117,7 +117,8 @@ :source="validContentTypes" :spellcheck="false" v-model="contentType" - >Content TypeContent Type + @@ -276,10 +277,30 @@ class="material-icons" :class="showPreRequestScript" v-if="!showPreRequestScript" - >codecode closeclose + + @@ -315,9 +336,46 @@ + + +
- +
visibilityvisibility visibility_offvisibility_off @@ -545,7 +603,7 @@
- +
@@ -627,7 +685,7 @@
- +
@@ -745,7 +803,7 @@
  • - +
    @@ -830,12 +888,12 @@