| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  | let describe; | 
					
						
							|  |  |  | let test; | 
					
						
							|  |  |  | let expect; | 
					
						
							| 
									
										
										
										
											2020-04-13 10:31:13 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  | // Stores the results of each test and suite. Has a terrible
 | 
					
						
							|  |  |  | // name to avoid name collision.
 | 
					
						
							|  |  |  | let __TestResults__ = {}; | 
					
						
							| 
									
										
										
										
											2020-04-19 23:01:45 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-04 20:23:46 -07:00
										 |  |  | // So test names like "toString" don't automatically produce an error
 | 
					
						
							|  |  |  | Object.setPrototypeOf(__TestResults__, null); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  | // This array is used to communicate with the C++ program. It treats
 | 
					
						
							|  |  |  | // each message in this array as a separate message. Has a terrible
 | 
					
						
							|  |  |  | // name to avoid name collision.
 | 
					
						
							|  |  |  | let __UserOutput__ = []; | 
					
						
							| 
									
										
										
										
											2020-05-26 20:31:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  | // We also rebind console.log here to use the array above
 | 
					
						
							|  |  |  | console.log = (...args) => { | 
					
						
							|  |  |  |     __UserOutput__.push(args.join(" ")); | 
					
						
							| 
									
										
										
										
											2020-04-21 19:21:26 +01:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 18:09:35 -07:00
										 |  |  | class ExpectationError extends Error { | 
					
						
							|  |  |  |     constructor(message, fileName, lineNumber) { | 
					
						
							|  |  |  |         super(message, fileName, lineNumber); | 
					
						
							|  |  |  |         this.name = "ExpectationError"; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  | // Use an IIFE to avoid polluting the global namespace as much as possible
 | 
					
						
							|  |  |  | (() => { | 
					
						
							| 
									
										
										
										
											2020-06-10 23:30:36 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  | // FIXME: This is a very naive deepEquals algorithm
 | 
					
						
							|  |  |  | const deepEquals = (a, b) => { | 
					
						
							| 
									
										
										
										
											2020-06-10 23:30:36 -07:00
										 |  |  |     if (Array.isArray(a)) | 
					
						
							|  |  |  |         return Array.isArray(b) && deepArrayEquals(a, b); | 
					
						
							|  |  |  |     if (typeof a === "object") | 
					
						
							|  |  |  |         return typeof b === "object" && deepObjectEquals(a, b); | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |     return Object.is(a, b); | 
					
						
							| 
									
										
										
										
											2020-06-10 23:30:36 -07:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  | const deepArrayEquals = (a, b) => { | 
					
						
							| 
									
										
										
										
											2020-06-10 23:30:36 -07:00
										 |  |  |     if (a.length !== b.length) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     for (let i = 0; i < a.length; ++i) { | 
					
						
							|  |  |  |         if (!deepEquals(a[i], b[i])) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  | const deepObjectEquals = (a, b) => { | 
					
						
							| 
									
										
										
										
											2020-06-10 23:30:36 -07:00
										 |  |  |     if (a === null) | 
					
						
							|  |  |  |         return b === null; | 
					
						
							|  |  |  |     for (let key of Reflect.ownKeys(a)) { | 
					
						
							|  |  |  |         if (!deepEquals(a[key], b[key])) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | class Expector { | 
					
						
							|  |  |  |     constructor(target, inverted) { | 
					
						
							|  |  |  |         this.target = target; | 
					
						
							|  |  |  |         this.inverted = !!inverted; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     get not() { | 
					
						
							|  |  |  |         return new Expector(this.target, !this.inverted); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toBe(value) { | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(Object.is(this.target, value)); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-04 10:09:48 -07:00
										 |  |  |     // FIXME: Take a precision argument like jest's toBeCloseTo matcher
 | 
					
						
							|  |  |  |     toBeCloseTo(value) { | 
					
						
							|  |  |  |         this.__expect(typeof this.target === "number"); | 
					
						
							|  |  |  |         this.__expect(typeof value === "number"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(Math.abs(this.target - value) < 0.000001); | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |     toHaveLength(length) { | 
					
						
							| 
									
										
										
										
											2020-07-03 18:09:35 -07:00
										 |  |  |         this.__expect(typeof this.target.length === "number"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(Object.is(this.target.length, length)); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toHaveProperty(property, value) { | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             let object = this.target; | 
					
						
							| 
									
										
										
										
											2020-07-03 18:09:35 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |             if (typeof property === "string" && property.includes(".")) { | 
					
						
							|  |  |  |                 let propertyArray = []; | 
					
						
							| 
									
										
										
										
											2020-07-03 18:09:35 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 while (property.includes(".")) { | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |                     let index = property.indexOf("."); | 
					
						
							|  |  |  |                     propertyArray.push(property.substring(0, index)); | 
					
						
							| 
									
										
										
										
											2020-07-03 18:09:35 -07:00
										 |  |  |                     if (index + 1 >= property.length) | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     property = property.substring(index + 1, property.length); | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2020-07-03 18:09:35 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 propertyArray.push(property); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |                 property = propertyArray; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-07-03 18:09:35 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |             if (Array.isArray(property)) { | 
					
						
							|  |  |  |                 for (let key of property) { | 
					
						
							| 
									
										
										
										
											2020-07-03 18:09:35 -07:00
										 |  |  |                     this.__expect(object !== undefined && object !== null); | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |                     object = object[key]; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } else { | 
					
						
							|  |  |  |                 object = object[property]; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             this.__expect(object !== undefined); | 
					
						
							|  |  |  |             if (value !== undefined) | 
					
						
							|  |  |  |                 this.__expect(deepEquals(object, value)); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toBeDefined() { | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(this.target !== undefined); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toBeInstanceOf(class_) { | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(this.target instanceof class_); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toBeNull() { | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(this.target === null); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toBeUndefined() { | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(this.target === undefined); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toBeNaN() { | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(isNaN(this.target)); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 23:13:06 -07:00
										 |  |  |     toBeTrue() { | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(this.target === true); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toBeFalse() { | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(this.target === false); | 
					
						
							| 
									
										
										
										
											2020-07-04 10:09:48 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     __validateNumericComparisonTypes(value) { | 
					
						
							|  |  |  |         this.__expect(typeof this.target === "number" || typeof this.target === "bigint"); | 
					
						
							|  |  |  |         this.__expect(typeof value === "number" || typeof value === "bigint"); | 
					
						
							|  |  |  |         this.__expect(typeof this.target === typeof value); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toBeLessThan(value) { | 
					
						
							|  |  |  |         this.__validateNumericComparisonTypes(value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(this.target < value); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toBeLessThanOrEqual(value) { | 
					
						
							|  |  |  |         this.__validateNumericComparisonTypes(value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(this.target <= value); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toBeGreaterThan(value) { | 
					
						
							|  |  |  |         this.__validateNumericComparisonTypes(value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(this.target > value); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toBeGreaterThanOrEqual(value) { | 
					
						
							|  |  |  |         this.__validateNumericComparisonTypes(value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(this.target >= value); | 
					
						
							|  |  |  |         }); | 
					
						
							| 
									
										
										
										
											2020-07-03 23:13:06 -07:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |     toContain(item) { | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             // FIXME: Iterator check
 | 
					
						
							|  |  |  |             for (let element of this.target) { | 
					
						
							|  |  |  |                 if (item === element) | 
					
						
							|  |  |  |                     return; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-07-03 18:09:35 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |             throw new ExpectationError(); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toContainEqual(item) { | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             // FIXME: Iterator check
 | 
					
						
							|  |  |  |             for (let element of this.target) { | 
					
						
							|  |  |  |                 if (deepEquals(item, element)) | 
					
						
							|  |  |  |                     return; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-07-03 18:09:35 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |             throw new ExpectationError(); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toEqual(value) { | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(deepEquals(this.target, value)); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toThrow(value) { | 
					
						
							|  |  |  |         this.__expect(typeof this.target === "function"); | 
					
						
							| 
									
										
										
										
											2020-07-03 18:09:35 -07:00
										 |  |  |         this.__expect(typeof value === "string" | 
					
						
							|  |  |  |                    || typeof value === "function" | 
					
						
							|  |  |  |                    || typeof value === "object" | 
					
						
							|  |  |  |                    || value === undefined); | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							| 
									
										
										
										
											2020-07-03 18:09:35 -07:00
										 |  |  |             let threw = true; | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |             try { | 
					
						
							|  |  |  |                 this.target(); | 
					
						
							| 
									
										
										
										
											2020-07-03 18:09:35 -07:00
										 |  |  |                 threw = false; | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |             } catch (e) { | 
					
						
							|  |  |  |                 if (typeof value === "string") { | 
					
						
							|  |  |  |                     this.__expect(e.message.includes(value)); | 
					
						
							|  |  |  |                 } else if (typeof value === "function") { | 
					
						
							|  |  |  |                     this.__expect(e instanceof value); | 
					
						
							| 
									
										
										
										
											2020-07-03 18:09:35 -07:00
										 |  |  |                 } else if (typeof value === "object") { | 
					
						
							|  |  |  |                     this.__expect(e.message === value.message); | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-07-03 18:09:35 -07:00
										 |  |  |             this.__expect(threw); | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pass(message) { | 
					
						
							|  |  |  |         // FIXME: This does nothing. If we want to implement things
 | 
					
						
							|  |  |  |         // like assertion count, this will have to do something
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // jest-extended
 | 
					
						
							|  |  |  |     fail(message) { | 
					
						
							|  |  |  |         // FIXME: message is currently ignored
 | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(false); | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // jest-extended
 | 
					
						
							|  |  |  |     toThrowWithMessage(class_, message) { | 
					
						
							|  |  |  |         this.__expect(typeof this.target === "function"); | 
					
						
							|  |  |  |         this.__expect(class_ !== undefined); | 
					
						
							|  |  |  |         this.__expect(message !== undefined); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             try { | 
					
						
							|  |  |  |                 this.target(); | 
					
						
							|  |  |  |                 this.__expect(false); | 
					
						
							|  |  |  |             } catch (e) { | 
					
						
							|  |  |  |                 this.__expect(e instanceof class_); | 
					
						
							|  |  |  |                 this.__expect(e.message.includes(message)); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Test for syntax errors; target must be a string
 | 
					
						
							|  |  |  |     toEval() { | 
					
						
							|  |  |  |         this.__expect(typeof this.target === "string"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!this.inverted) { | 
					
						
							|  |  |  |             try { | 
					
						
							|  |  |  |                 new Function(this.target)(); | 
					
						
							|  |  |  |             } catch (e) { | 
					
						
							|  |  |  |                 throw new ExpectationError(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2020-07-03 18:09:35 -07:00
										 |  |  |             let threw; | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |             try { | 
					
						
							|  |  |  |                 new Function(this.target)(); | 
					
						
							| 
									
										
										
										
											2020-07-03 18:09:35 -07:00
										 |  |  |                 threw = false; | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |             } catch (e) { | 
					
						
							| 
									
										
										
										
											2020-07-03 18:09:35 -07:00
										 |  |  |                 threw = true; | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-07-03 18:09:35 -07:00
										 |  |  |             this.__expect(threw); | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Must compile regardless of inverted-ness
 | 
					
						
							|  |  |  |     toEvalTo(value) { | 
					
						
							|  |  |  |         this.__expect(typeof this.target === "string"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         let result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         try { | 
					
						
							|  |  |  |             result = new Function(this.target)(); | 
					
						
							|  |  |  |         } catch (e) { | 
					
						
							|  |  |  |             throw new ExpectationError(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(deepEquals(value, result)); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 23:13:06 -07:00
										 |  |  |     toHaveConfigurableProperty(property) { | 
					
						
							|  |  |  |         this.__expect(this.target !== undefined && this.target !== null); | 
					
						
							|  |  |  |         let d = Object.getOwnPropertyDescriptor(this.target, property); | 
					
						
							|  |  |  |         this.__expect(d !== undefined); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(d.configurable); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toHaveEnumerableProperty(property) { | 
					
						
							|  |  |  |         this.__expect(this.target !== undefined && this.target !== null); | 
					
						
							|  |  |  |         let d = Object.getOwnPropertyDescriptor(this.target, property); | 
					
						
							|  |  |  |         this.__expect(d !== undefined); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(d.enumerable); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toHaveWritableProperty(property) { | 
					
						
							|  |  |  |         this.__expect(this.target !== undefined && this.target !== null); | 
					
						
							|  |  |  |         let d = Object.getOwnPropertyDescriptor(this.target, property); | 
					
						
							|  |  |  |         this.__expect(d !== undefined); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(d.writable); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toHaveValueProperty(property, value) { | 
					
						
							|  |  |  |         this.__expect(this.target !== undefined && this.target !== null); | 
					
						
							|  |  |  |         let d = Object.getOwnPropertyDescriptor(this.target, property); | 
					
						
							|  |  |  |         this.__expect(d !== undefined); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(d.value !== undefined); | 
					
						
							|  |  |  |             if (value !== undefined) | 
					
						
							|  |  |  |                 this.__expect(deepEquals(value, d.value)); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toHaveGetterProperty(property) { | 
					
						
							|  |  |  |         this.__expect(this.target !== undefined && this.target !== null); | 
					
						
							|  |  |  |         let d = Object.getOwnPropertyDescriptor(this.target, property); | 
					
						
							|  |  |  |         this.__expect(d !== undefined); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(d.get !== undefined); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toHaveSetterProperty(property) { | 
					
						
							|  |  |  |         this.__expect(this.target !== undefined && this.target !== null); | 
					
						
							|  |  |  |         let d = Object.getOwnPropertyDescriptor(this.target, property); | 
					
						
							|  |  |  |         this.__expect(d !== undefined); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         this.__doMatcher(() => { | 
					
						
							|  |  |  |             this.__expect(d.set !== undefined); | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |     __doMatcher(matcher) { | 
					
						
							|  |  |  |         if (!this.inverted) { | 
					
						
							|  |  |  |             matcher(); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             let threw = false; | 
					
						
							|  |  |  |             try { | 
					
						
							|  |  |  |                 matcher(); | 
					
						
							|  |  |  |             } catch (e) { | 
					
						
							|  |  |  |                 if (e.name === "ExpectationError") | 
					
						
							|  |  |  |                     threw = true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             if (!threw) | 
					
						
							|  |  |  |                 throw new ExpectationError(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     __expect(value) { | 
					
						
							|  |  |  |         if (value !== true) | 
					
						
							|  |  |  |             throw new ExpectationError(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | expect = value => new Expector(value); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // describe is able to lump test results inside of it by using this context
 | 
					
						
							| 
									
										
										
										
											2020-07-04 12:57:12 -07:00
										 |  |  | // variable. Top level tests have the default suite message
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  | const defaultSuiteMessage = "__$$TOP_LEVEL$$__"; | 
					
						
							|  |  |  | let suiteMessage = defaultSuiteMessage; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | describe = (message, callback) => { | 
					
						
							|  |  |  |     suiteMessage = message; | 
					
						
							|  |  |  |     callback(); | 
					
						
							|  |  |  |     suiteMessage = defaultSuiteMessage; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-04 12:57:12 -07:00
										 |  |  | test = (message, callback) => { | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |     if (!__TestResults__[suiteMessage]) | 
					
						
							|  |  |  |         __TestResults__[suiteMessage] = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const suite = __TestResults__[suiteMessage]; | 
					
						
							| 
									
										
										
										
											2020-07-04 20:23:46 -07:00
										 |  |  |     if (suite[message]) { | 
					
						
							|  |  |  |         suite[message] = { | 
					
						
							|  |  |  |             result: "fail" | 
					
						
							|  |  |  |         }; | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     try { | 
					
						
							|  |  |  |         callback(); | 
					
						
							|  |  |  |         suite[message] = { | 
					
						
							| 
									
										
										
										
											2020-07-04 12:57:12 -07:00
										 |  |  |             result: "pass", | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |         }; | 
					
						
							|  |  |  |     } catch (e) { | 
					
						
							|  |  |  |         suite[message] = { | 
					
						
							| 
									
										
										
										
											2020-07-04 11:37:50 -07:00
										 |  |  |             result: "fail", | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  |         }; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-04 12:57:12 -07:00
										 |  |  | test.skip = (message, callback) => { | 
					
						
							|  |  |  |     if (typeof callback !== "function") | 
					
						
							|  |  |  |         throw new Error("test.skip has invalid second argument (must be a function)"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!__TestResults__[suiteMessage]) | 
					
						
							|  |  |  |         __TestResults__[suiteMessage] = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const suite = __TestResults__[suiteMessage]; | 
					
						
							|  |  |  |     if (suite[message]) | 
					
						
							|  |  |  |         throw new Error("Duplicate test name: " + message); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     suite[message] = { | 
					
						
							|  |  |  |         result: "skip", | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2020-07-04 11:37:50 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-03 14:36:58 -07:00
										 |  |  | })(); |