refactor: update postwomanTesting to typescript
This commit is contained in:
@@ -1,29 +1,51 @@
|
|||||||
export const PASS = "PASS"
|
import { HoppRESTResponse } from "./types/HoppRESTResponse"
|
||||||
export const FAIL = "FAIL"
|
|
||||||
export const ERROR = "ERROR"
|
|
||||||
|
|
||||||
const styles = {
|
const styles = {
|
||||||
[PASS]: { icon: "check", class: "success-response" },
|
PASS: { icon: "check", class: "success-response" },
|
||||||
[FAIL]: { icon: "close", class: "cl-error-response" },
|
FAIL: { icon: "close", class: "cl-error-response" },
|
||||||
[ERROR]: { icon: "close", class: "cl-error-response" },
|
ERROR: { icon: "close", class: "cl-error-response" },
|
||||||
none: { icon: "", class: "" },
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: probably have to use a more global state for `test`
|
type TestScriptVariables = {
|
||||||
|
response: HoppRESTResponse
|
||||||
|
}
|
||||||
|
|
||||||
export default function runTestScriptWithVariables(script, variables) {
|
type TestReportStartBlock = {
|
||||||
|
startBlock: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestReportEndBlock = {
|
||||||
|
endBlock: true
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestReportEntry = {
|
||||||
|
styles: {
|
||||||
|
icon: string
|
||||||
|
}
|
||||||
|
} & ({ result: "PASS" } | { result: "FAIL" | "ERROR"; message: string })
|
||||||
|
type TestReport = TestReportStartBlock | TestReportEntry | TestReportEndBlock
|
||||||
|
|
||||||
|
export default function runTestScriptWithVariables(
|
||||||
|
script: string,
|
||||||
|
variables: TestScriptVariables
|
||||||
|
) {
|
||||||
const pw = {
|
const pw = {
|
||||||
_errors: [],
|
_errors: [],
|
||||||
_testReports: [],
|
_testReports: [] as TestReport[],
|
||||||
_report: "",
|
_report: "",
|
||||||
expect(value) {
|
expect(value: any) {
|
||||||
try {
|
try {
|
||||||
return expect(value, this._testReports)
|
return expect(value, this._testReports)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
pw._testReports.push({ result: ERROR, message: e })
|
pw._testReports.push({
|
||||||
|
result: "ERROR",
|
||||||
|
message: e.toString(),
|
||||||
|
styles: styles.ERROR,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
test: (descriptor, func) => test(descriptor, func, pw._testReports),
|
test: (descriptor: string, func: () => void) =>
|
||||||
|
test(descriptor, func, pw._testReports),
|
||||||
// globals that the script is allowed to have access to.
|
// globals that the script is allowed to have access to.
|
||||||
}
|
}
|
||||||
Object.assign(pw, variables)
|
Object.assign(pw, variables)
|
||||||
@@ -31,24 +53,24 @@ export default function runTestScriptWithVariables(script, variables) {
|
|||||||
// run pre-request script within this function so that it has access to the pw object.
|
// run pre-request script within this function so that it has access to the pw object.
|
||||||
// eslint-disable-next-line no-new-func
|
// eslint-disable-next-line no-new-func
|
||||||
new Function("pw", script)(pw)
|
new Function("pw", script)(pw)
|
||||||
//
|
|
||||||
const testReports = pw._testReports.map((item) => {
|
return {
|
||||||
if (item.result) {
|
report: pw._report,
|
||||||
item.styles = styles[item.result]
|
errors: pw._errors,
|
||||||
} else {
|
testResults: pw._testReports,
|
||||||
item.styles = styles.none
|
|
||||||
}
|
}
|
||||||
return item
|
|
||||||
})
|
|
||||||
return { report: pw._report, errors: pw._errors, testResults: testReports }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function test(descriptor, func, _testReports) {
|
function test(
|
||||||
|
descriptor: string,
|
||||||
|
func: () => void,
|
||||||
|
_testReports: TestReport[]
|
||||||
|
) {
|
||||||
_testReports.push({ startBlock: descriptor })
|
_testReports.push({ startBlock: descriptor })
|
||||||
try {
|
try {
|
||||||
func()
|
func()
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
_testReports.push({ result: ERROR, message: e })
|
_testReports.push({ result: "ERROR", message: e, styles: styles.ERROR })
|
||||||
}
|
}
|
||||||
_testReports.push({ endBlock: true })
|
_testReports.push({ endBlock: true })
|
||||||
|
|
||||||
@@ -56,16 +78,26 @@ function test(descriptor, func, _testReports) {
|
|||||||
// add checkmark or x depending on if each testReport is pass=true or pass=false
|
// add checkmark or x depending on if each testReport is pass=true or pass=false
|
||||||
}
|
}
|
||||||
|
|
||||||
function expect(expectValue, _testReports) {
|
function expect(expectValue: any, _testReports: TestReport[]) {
|
||||||
return new Expectation(expectValue, null, _testReports)
|
return new Expectation(expectValue, null, _testReports)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Expectation {
|
class Expectation {
|
||||||
constructor(expectValue, _not, _testReports) {
|
private expectValue: any
|
||||||
|
private not: true | Expectation
|
||||||
|
private _testReports: TestReport[]
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
expectValue: any,
|
||||||
|
_not: boolean | null,
|
||||||
|
_testReports: TestReport[]
|
||||||
|
) {
|
||||||
this.expectValue = expectValue
|
this.expectValue = expectValue
|
||||||
this.not = _not || new Expectation(this.expectValue, true, _testReports)
|
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._testReports = _testReports // this values is used within Test.it, which wraps Expectation and passes _testReports value.
|
||||||
this._satisfies = function (expectValue, targetValue) {
|
}
|
||||||
|
|
||||||
|
private _satisfies(expectValue: any, targetValue?: any): boolean {
|
||||||
// Used for testing if two values match the expectation, which could be === OR !==, depending on if not
|
// 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.
|
// 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
|
// Signature is _satisfies([expectValue,] targetValue): if only one argument is given, it is assumed the targetValue, and expectValue is set to this.expectValue
|
||||||
@@ -80,9 +112,8 @@ class Expectation {
|
|||||||
return expectValue === targetValue
|
return expectValue === targetValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
_fmtNot(message) {
|
_fmtNot(message: string) {
|
||||||
// given a string with "(not)" in it, replaces with "not" or "", depending if the expectation is expecting the positive or inverse (this._not)
|
// 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) {
|
if (this.not === true) {
|
||||||
return message.replace("(not)", "not ")
|
return message.replace("(not)", "not ")
|
||||||
@@ -91,17 +122,21 @@ class Expectation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_fail(message) {
|
_fail(message: string) {
|
||||||
return this._testReports.push({ result: FAIL, message })
|
return this._testReports.push({
|
||||||
|
result: "FAIL",
|
||||||
|
message,
|
||||||
|
styles: styles.FAIL,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
_pass() {
|
_pass() {
|
||||||
return this._testReports.push({ result: PASS })
|
return this._testReports.push({ result: "PASS", styles: styles.PASS })
|
||||||
}
|
}
|
||||||
|
|
||||||
// TEST METHODS DEFINED BELOW
|
// TEST METHODS DEFINED BELOW
|
||||||
// these are the usual methods that would follow expect(...)
|
// these are the usual methods that would follow expect(...)
|
||||||
toBe(value) {
|
toBe(value: any) {
|
||||||
return this._satisfies(value)
|
return this._satisfies(value)
|
||||||
? this._pass()
|
? this._pass()
|
||||||
: this._fail(
|
: this._fail(
|
||||||
@@ -109,7 +144,7 @@ class Expectation {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
toHaveProperty(value) {
|
toHaveProperty(value: string) {
|
||||||
return this._satisfies(
|
return this._satisfies(
|
||||||
Object.prototype.hasOwnProperty.call(this.expectValue, value),
|
Object.prototype.hasOwnProperty.call(this.expectValue, value),
|
||||||
true
|
true
|
||||||
@@ -186,7 +221,7 @@ class Expectation {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
toHaveLength(expectedLength) {
|
toHaveLength(expectedLength: number) {
|
||||||
const actualLength = this.expectValue.length
|
const actualLength = this.expectValue.length
|
||||||
return this._satisfies(actualLength, expectedLength)
|
return this._satisfies(actualLength, expectedLength)
|
||||||
? this._pass()
|
? this._pass()
|
||||||
@@ -197,7 +232,7 @@ class Expectation {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
toBeType(expectedType) {
|
toBeType(expectedType: string) {
|
||||||
const actualType = typeof this.expectValue
|
const actualType = typeof this.expectValue
|
||||||
if (
|
if (
|
||||||
![
|
![
|
||||||
Reference in New Issue
Block a user