openzeppelin-test-helpers icon indicating copy to clipboard operation
openzeppelin-test-helpers copied to clipboard

Provide TypeScript type definitions

Open frangio opened this issue 4 years ago • 12 comments

Requested in https://github.com/OpenZeppelin/openzeppelin-test-environment/issues/73#issuecomment-629425128.

Some prior conversation in https://github.com/OpenZeppelin/openzeppelin-test-helpers/pull/116#issuecomment-611281410.

frangio avatar May 15 '20 21:05 frangio

@bruce-plutusds is there a chance we could see your port of this library to TypeScript?

frangio avatar May 15 '20 21:05 frangio

I tried running TypeScript to generate type declarations from our current JavaScript files, but it's triggering a compiler bug, and it doesn't seem feasible to fix it. So we will have to migrate everything to TypeScript. We can do this in two steps:

  1. Migrate all source files to TypeScript, with generous use of any. Keep the tests in JavaScript for now, since the priority is getting type definitions for the public API.
  2. Progressively remove uses of any. Remember that the priority is typing the public API, and internal functions are not as important (for now).

Things to watch out for:

  • Truffle and Web3 receipts, which we use in expectEvent. I'm not sure if those packages provide their own types. However, since our library receives the receipt objects from the user, and we use very few properties anyway, I'd suggest we define our own interfaces with the properties we need.
  • Numbers. Functions that receive numbers may work with BN, number, or even string. We have to check and type appropriately.

frangio avatar May 18 '20 23:05 frangio

Are there any plans to tackle this soon? :grin:

nventuro avatar Sep 10 '20 18:09 nventuro

@nventuro Sorry we don't have the time to tackle this right now, but would welcome and review any PRs. :slightly_smiling_face:

frangio avatar Sep 14 '20 16:09 frangio

Big fan of this library. I started a PR to add type definitions: https://github.com/OpenZeppelin/openzeppelin-test-helpers/pull/141.

omarish avatar Nov 14 '20 03:11 omarish

Hey! Any news on this one?

nowtryz avatar Apr 20 '21 13:04 nowtryz

No news, sorry.

frangio avatar Apr 20 '21 15:04 frangio

+1. Haven't had much time to continue this. Happy to pass the torch to someone else if they want to run with it.

omarish avatar Apr 20 '21 18:04 omarish

Hope that base configuration can be integrated, then other people can convert partially

codler avatar May 30 '21 06:05 codler

I think I can spare the bandwidth to finish this off, provided the scope is set in advance.

OS dev is frustrating, and so is submitting PR's that immediately fall by the way because they don't check box (X) :-)

FrozenKiwi avatar Dec 02 '21 21:12 FrozenKiwi

Are there any plans on tackling this? Anybody doing the port? Thanks!

robercano avatar Sep 22 '22 12:09 robercano

I also ran into this trying to test events so I added:

// types/openzeppelin-test-helpers.d.ts
declare module '@openzeppelin/test-helpers' {
  import { ContractReceipt } from 'ethers'

  export function expectEvent(receipt: ContractReceipt, eventName: string, eventArgs: Record<string, any>): void
}

which gets picked up by default via tsc (typeRoots setting in tsconfig) and allowed me to use

import { expectEvent } from '@openzeppelin/test-helpers'

in my .test.ts TypeScript test files.

But strangely it was throwing errors that it couldn't find events which were clearly there due to my hand-written test code that validated it.

So ultimately I decided to remove the dependency on @openzeppelin/test-helpers and write my own helper function for testing events:

import { ContractReceipt } from "@ethersproject/contracts";
import { EventFilter } from "@ethersproject/abstract-provider";
import { expect } from "chai";

// Asserts that the logs in receipt contain an event with name eventName and arguments
// that match those specified in eventArgs.
function expectEvent(
  receipt: ContractReceipt,
  eventName: string,
  eventArgs: Record<string, any>
) {
  expect(receipt.events).to.not.be.undefined;

  const event = receipt.events?.find((e) => e.event === eventName);
  expect(event, `Event '${eventName}' not found`).to.not.be.undefined;

  for (const [key, value] of Object.entries(eventArgs)) {
    expect(event?.args?.[key], `Event argument '${key}' not found`).to.equal(value);
  }
}

// Asserts that the logs in receipt contain a single event with name eventName and arguments
// that match those specified in eventArgs.
function expectOneEvent(receipt: ContractReceipt, eventName: string, eventArgs: Record<string, any>) {
  expect(receipt.events).to.not.be.undefined
  expect(receipt.events?.length, `Expected exactly 1 event`).to.equal(1)

  expectEvent(receipt, eventName, eventArgs)
}

which readers are welcome to use or adapt to their use case.

stoooops avatar Mar 16 '23 12:03 stoooops