diff --git a/test/introspection/SupportsInterface.behavior.js b/test/introspection/SupportsInterface.behavior.js index fde7f5cc6..da8ed98c1 100644 --- a/test/introspection/SupportsInterface.behavior.js +++ b/test/introspection/SupportsInterface.behavior.js @@ -1,10 +1,10 @@ const { makeInterfaceId } = require('openzeppelin-test-helpers'); -const INTERFACE_IDS = { - ERC165: makeInterfaceId([ +const INTERFACES = { + ERC165: [ 'supportsInterface(bytes4)', - ]), - ERC721: makeInterfaceId([ + ], + ERC721: [ 'balanceOf(address)', 'ownerOf(uint256)', 'approve(address,uint256)', @@ -14,38 +14,56 @@ const INTERFACE_IDS = { 'transferFrom(address,address,uint256)', 'safeTransferFrom(address,address,uint256)', 'safeTransferFrom(address,address,uint256,bytes)', - ]), - ERC721Enumerable: makeInterfaceId([ + ], + ERC721Enumerable: [ 'totalSupply()', 'tokenOfOwnerByIndex(address,uint256)', 'tokenByIndex(uint256)', - ]), - ERC721Metadata: makeInterfaceId([ + ], + ERC721Metadata: [ 'name()', 'symbol()', 'tokenURI(uint256)', - ]), - ERC721Exists: makeInterfaceId([ - 'exists(uint256)', - ]), + ], }; +const INTERFACE_IDS = {}; +const FN_SIGNATURES = {}; +for (const k of Object.getOwnPropertyNames(INTERFACES)) { + INTERFACE_IDS[k] = makeInterfaceId(INTERFACES[k]); + for (const fnName of INTERFACES[k]) { + // the interface id of a single function is equivalent to its function signature + FN_SIGNATURES[fnName] = makeInterfaceId([fnName]); + } +} + function shouldSupportInterfaces (interfaces = []) { - describe('ERC165\'s supportsInterface(bytes4)', function () { + describe('Contract interface', function () { beforeEach(function () { - this.thing = this.mock || this.token; + this.contractUnderTest = this.mock || this.token; }); for (const k of interfaces) { const interfaceId = INTERFACE_IDS[k]; describe(k, function () { - it('should use less than 30k gas', async function () { - (await this.thing.supportsInterface.estimateGas(interfaceId)).should.be.lte(30000); + describe('ERC165\'s supportsInterface(bytes4)', function () { + it('should use less than 30k gas', async function () { + (await this.contractUnderTest.supportsInterface.estimateGas(interfaceId)).should.be.lte(30000); + }); + + it('should claim support', async function () { + (await this.contractUnderTest.supportsInterface(interfaceId)).should.equal(true); + }); }); - it('is supported', async function () { - (await this.thing.supportsInterface(interfaceId)).should.equal(true); - }); + for (const fnName of INTERFACES[k]) { + const fnSig = FN_SIGNATURES[fnName]; + describe(fnName, function () { + it('should be implemented', function () { + this.contractUnderTest.abi.filter(fn => fn.signature === fnSig).length.should.equal(1); + }); + }); + } }); } });