1- import { ethers } from "hardhat"
2- import { Overrides } from "ethers"
3- import assert from "assert"
4-
51/*
62 *
73 * The `test` function is a wrapper around Mocha's `it` function. It provides a normalized framework for running the
@@ -37,96 +33,10 @@ import assert from "assert"
3733 */
3834
3935// Below are the types that help define all the different ways to call `test`
40- type FnNameOrObject = string | string [ ] | MethodObject | MethodObject [ ]
41-
42- // Limit `from` property to be a `string` instead of `string | Promise<string>`
43- type CallOverrides = Overrides & { from ?: string }
44-
45- type MethodObject = { method : string , debug ?: boolean , overrides ?: CallOverrides , shouldFail ?: boolean }
46-
47- // This type is after all default values have been applied
48- type MethodWithDebugAndOverrides = MethodObject & { debug : boolean , overrides : CallOverrides , shouldFail : boolean }
49-
50- // `test` is used very similarly to `it` from Mocha
51- export const test = ( name , fnNameOrObject , overrides = { } ) => it ( name , buildTestFn ( fnNameOrObject , overrides ) )
52- // `test.only` is used very similarly to `it.only` from Mocha, it will isolate all tests marked with `test.only`
53- test . only = ( name , fnNameOrObject , overrides = { } ) => it . only ( name , buildTestFn ( fnNameOrObject , overrides ) )
54- // `test.debug` is used to apply `debug: true` to all DSTest contract method calls in the test
55- test . debug = ( name , fnNameOrObject , overrides = { } ) => it . only ( name , buildTestFn ( fnNameOrObject , overrides , true ) )
56- // `test.skip` is used very similarly to `it.skip` from Mocha, it will skip all tests marked with `test.skip`
57- test . skip = ( name , fnNameOrObject , overrides = { } ) => it . skip ( name , buildTestFn ( fnNameOrObject , overrides ) )
58-
59- // `buildTestFn` is a higher-order function. It returns a function that can be used as the test function for `it`
60- const buildTestFn = ( fnNameOrObject : FnNameOrObject , overrides = { } , debug = false ) => {
61- // normalize the input to an array of objects
62- const fnObjects : MethodWithDebugAndOverrides [ ] = ( Array . isArray ( fnNameOrObject ) ? fnNameOrObject : [ fnNameOrObject ] ) . map ( fnNameOrObject => {
63- fnNameOrObject = typeof fnNameOrObject === 'string' ? { method : fnNameOrObject } : fnNameOrObject
64- // assign all default values and overrides
65- fnNameOrObject . overrides = Object . assign ( { } , overrides , fnNameOrObject . overrides ?? { } )
66- fnNameOrObject . debug = fnNameOrObject . debug ?? debug
67- fnNameOrObject . shouldFail = fnNameOrObject . shouldFail ?? false
68-
69- return fnNameOrObject as MethodWithDebugAndOverrides
70- } )
71-
72- // only `step_` prefixed functions can be called on the `DSTest` contracts to clearly separate tests and helpers
73- assert ( fnObjects . every ( ( { method } ) => method . startsWith ( 'step_' ) ) , "Solidity test functions must be prefixed with 'step_'" )
74-
75- // return the test function that will be used by `it`
76- // this function must be defined with the `function` keyword so that `this` is bound to the Mocha context
77- return async function ( ) {
78- // `Array.prototype.reduce` is used here to ensure that the test functions are called in order.
79- // Each test function waits for its predecessor to complete before starting
80- return fnObjects . reduce ( ( p : Promise < undefined > , fn ) => p . then ( async ( ) => {
81- const contract = fn . overrides . from
82- ? this . testContract . connect ( await ethers . getSigner ( fn . overrides . from ) )
83- : this . testContract
84- const tx = await contract [ fn . method ] ( fn . overrides ) . catch ( err => {
85- if ( fn . shouldFail ) {
86- if ( fn . debug ) {
87- console . error ( `smart contract call failed with error:\n${ err } \n` )
88- }
89-
90- return { failed : true }
91- }
92-
93- console . error ( "smart contract call failed with error:" , err )
94- throw err
95- } )
96-
97- // no more assertions necessary if the method-call should fail and did fail
98- if ( tx . failed && fn . shouldFail ) return
99-
100- const txReceipt = await tx . wait ( ) . catch ( err => {
101- if ( fn . debug ) console . error ( `tx failed with error:\n${ err } \n` )
102- return err . receipt
103- } )
104-
105- // `txReceipt.status` will be `0` if the transaction failed.
106- // `contract.failed` will return `true` if any of the `DSTest` assertions failed.
107- const failed = txReceipt . status === 0 ? true : await contract . failed . staticCall ( )
108- if ( fn . debug || failed ) {
109- console . log ( '' )
110-
111- if ( ! txReceipt . events ) console . warn ( 'WARNING: No parseable events found in tx-receipt\n' )
112-
113- // If `DSTest` assertions failed, the contract will emit logs describing the assertion failure(s).
114- txReceipt
115- . events
116- ?. filter ( event => fn . debug || event . event ?. startsWith ( 'log' ) )
117- . map ( event => event . args ?. forEach ( arg => console . log ( arg ) ) )
118-
119- console . log ( '' )
120- }
121-
122- assert ( ! failed , `${ fn . method } failed` )
123- } ) , Promise . resolve ( ) )
124- }
125- }
12636
12737export const Roles = {
12838 None : 0 ,
12939 Enabled : 1 ,
13040 Admin : 2 ,
13141 Manager : 3 ,
132- }
42+ }
0 commit comments