api-client/functions/postwomanTesting.js

148 lines
5.2 KiB
JavaScript
Raw Normal View History

const PASS = "PASS"
const FAIL = "FAIL"
const ERROR = "ERROR"
2020-01-11 18:01:42 +00:00
2020-01-24 16:51:40 +00:00
const styles = {
[PASS]: { icon: "check", class: "success-response" },
[FAIL]: { icon: "close", class: "cl-error-response" },
[ERROR]: { icon: "close", class: "cl-error-response" },
none: { icon: "", class: "" },
2020-02-24 18:44:50 +00:00
}
2020-01-24 16:51:40 +00:00
2020-01-27 12:47:01 +00:00
// TODO: probably have to use a more global state for `test`
2020-01-19 15:46:04 +00:00
export default function runTestScriptWithVariables(script, variables) {
2020-01-09 01:40:50 +00:00
let pw = {
2020-01-11 17:18:29 +00:00
_errors: [],
2020-01-19 15:46:04 +00:00
_testReports: [],
_report: "",
2020-01-24 19:30:45 +00:00
expect(value) {
try {
2020-02-24 18:44:50 +00:00
return expect(value, this._testReports)
} catch (e) {
2020-02-24 18:44:50 +00:00
pw._testReports.push({ result: ERROR, message: e })
}
},
2020-02-24 18:44:50 +00:00
test: (descriptor, func) => test(descriptor, func, pw._testReports),
2020-01-09 01:40:50 +00:00
// globals that the script is allowed to have access to.
2020-02-24 18:44:50 +00:00
}
Object.assign(pw, variables)
2020-01-09 01:40:50 +00:00
// run pre-request script within this function so that it has access to the pw object.
new Function("pw", script)(pw)
//
2020-01-24 17:18:55 +00:00
const testReports = pw._testReports.map(item => {
if (item.result) {
2020-02-24 18:44:50 +00:00
item.styles = styles[item.result]
2020-01-24 16:51:40 +00:00
} else {
2020-02-24 18:44:50 +00:00
item.styles = styles.none
2020-01-24 16:51:40 +00:00
}
2020-02-24 18:44:50 +00:00
return item
})
return { report: pw._report, errors: pw._errors, testResults: testReports }
2020-01-09 01:40:50 +00:00
}
2020-01-19 15:46:04 +00:00
function test(descriptor, func, _testReports) {
2020-02-24 18:44:50 +00:00
_testReports.push({ startBlock: descriptor })
try {
2020-02-24 18:44:50 +00:00
func()
} catch (e) {
2020-02-24 18:44:50 +00:00
_testReports.push({ result: ERROR, message: e })
}
2020-02-24 18:44:50 +00:00
_testReports.push({ endBlock: true })
2020-01-11 18:01:42 +00:00
2020-01-27 12:46:40 +00:00
// TODO: Organize and generate text report of each {descriptor: true} section in testReports.
2020-01-11 18:01:42 +00:00
// add checkmark or x depending on if each testReport is pass=true or pass=false
2020-01-09 01:40:50 +00:00
}
function expect(expectValue, _testReports) {
2020-02-24 18:44:50 +00:00
return new Expectation(expectValue, null, _testReports)
2020-01-11 17:18:29 +00:00
}
class Expectation {
constructor(expectValue, _not, _testReports) {
2020-02-24 18:44:50 +00:00
this.expectValue = expectValue
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.
2020-01-11 18:01:42 +00:00
this._satisfies = function(expectValue, targetValue) {
2020-01-11 17:18:29 +00:00
// 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.
2020-01-11 18:01:42 +00:00
// 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) {
2020-02-24 18:44:50 +00:00
targetValue = expectValue
expectValue = this.expectValue
2020-01-11 18:01:42 +00:00
}
2020-01-11 17:18:29 +00:00
if (this.not === true) {
// test the inverse. this.not is always truthly, but an Expectation that is inverted will always be strictly `true`
2020-02-24 18:44:50 +00:00
return expectValue !== targetValue
2020-01-11 17:18:29 +00:00
} else {
2020-02-24 18:44:50 +00:00
return expectValue === targetValue
2020-01-11 17:18:29 +00:00
}
2020-02-24 18:44:50 +00:00
}
2020-01-11 17:18:29 +00:00
}
_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 ")
2020-01-11 17:18:29 +00:00
} else {
return message.replace("(not)", "")
2020-01-11 17:18:29 +00:00
}
}
_fail(message) {
2020-02-24 18:44:50 +00:00
this._testReports.push({ result: FAIL, message })
2020-01-11 17:18:29 +00:00
}
_pass(message) {
2020-02-24 18:44:50 +00:00
this._testReports.push({ result: PASS })
2020-01-11 17:18:29 +00:00
}
// TEST METHODS DEFINED BELOW
// these are the usual methods that would follow expect(...)
toBe(value) {
2020-01-11 18:01:42 +00:00
return this._satisfies(value)
? this._pass()
2020-02-24 18:44:50 +00:00
: this._fail(this._fmtNot(`Expected ${this.expectValue} (not)to be ${value}`))
2020-01-11 17:18:29 +00:00
}
toHaveProperty(value) {
2020-01-11 18:01:42 +00:00
return this._satisfies(this.expectValue.hasOwnProperty(value), true)
? this._pass()
2020-01-24 19:30:45 +00:00
: this._fail(
2020-02-24 18:44:50 +00:00
this._fmtNot(`Expected object ${this.expectValue} to (not)have property ${value}`)
)
2020-01-11 18:01:42 +00:00
}
toBeLevel2xx() {
2020-02-24 18:44:50 +00:00
const code = parseInt(this.expectValue)
2020-01-11 18:01:42 +00:00
if (Number.isNaN(code)) {
2020-02-24 18:44:50 +00:00
return this._fail(`Expected 200-level status but could not parse value ${this.expectValue}`)
2020-01-11 18:01:42 +00:00
}
return this._satisfies(code >= 200 && code < 300)
2020-01-24 19:30:45 +00:00
? this._pass()
2020-02-24 18:44:50 +00:00
: this._fail(this._fmtNot(`Expected ${this.expectValue} to (not)be 200-level status`))
2020-01-11 18:01:42 +00:00
}
toBeLevel3xx() {
2020-02-24 18:44:50 +00:00
const code = parseInt(this.expectValue)
2020-01-11 18:01:42 +00:00
if (Number.isNaN(code)) {
2020-02-24 18:44:50 +00:00
return this._fail(`Expected 300-level status but could not parse value ${this.expectValue}`)
2020-01-11 18:01:42 +00:00
}
return this._satisfies(code >= 300 && code < 400)
2020-01-24 19:30:45 +00:00
? this._pass()
2020-02-24 18:44:50 +00:00
: this._fail(this._fmtNot(`Expected ${this.expectValue} to (not)be 300-level status`))
2020-01-11 18:01:42 +00:00
}
toBeLevel4xx() {
2020-02-24 18:44:50 +00:00
const code = parseInt(this.expectValue)
2020-01-11 18:01:42 +00:00
if (Number.isNaN(code)) {
2020-02-24 18:44:50 +00:00
return this._fail(`Expected 400-level status but could not parse value ${this.expectValue}`)
2020-01-11 18:01:42 +00:00
}
return this._satisfies(code >= 400 && code < 500)
2020-01-24 19:30:45 +00:00
? this._pass()
2020-02-24 18:44:50 +00:00
: this._fail(this._fmtNot(`Expected ${this.expectValue} to (not)be 400-level status`))
2020-01-11 18:01:42 +00:00
}
toBeLevel5xx() {
2020-02-24 18:44:50 +00:00
const code = parseInt(this.expectValue)
2020-01-11 18:01:42 +00:00
if (Number.isNaN(code)) {
2020-02-24 18:44:50 +00:00
return this._fail(`Expected 500-level status but could not parse value ${this.expectValue}`)
2020-01-11 18:01:42 +00:00
}
return this._satisfies(code >= 500 && code < 600)
? this._pass()
2020-02-24 18:44:50 +00:00
: this._fail(this._fmtNot(`Expected ${this.expectValue} to (not)be 500-level status`))
2020-01-11 17:18:29 +00:00
}
}