diff --git a/CHANGELOG.md b/CHANGELOG.md index 254b01b04..3329baac4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,9 @@ # Changelog ## vNEXT -- Migrate IexecAccessors tests Typescript & Hardhat. (#96) +- Migrate unit test files to Typescript & Hardhat: + - IexecCategoryManager (#97) + - IexecAccessors (#96) - Wait for transactions occurring during deployment. (#95) - Deploy and configure ENS with hardhat. (#93) - Fix contribute & finalize with callbacks. (#92) diff --git a/deploy/0_deploy.ts b/deploy/0_deploy.ts index 363293196..96347eab2 100644 --- a/deploy/0_deploy.ts +++ b/deploy/0_deploy.ts @@ -41,11 +41,7 @@ import { import { Ownable__factory } from '../typechain/factories/@openzeppelin/contracts/access'; import { FactoryDeployerHelper } from '../utils/FactoryDeployerHelper'; import { getBaseNameFromContractFactory } from '../utils/deploy-tools'; -interface Category { - name: string; - description: string; - workClockTimeRef: number; -} +import { Category } from '../utils/poco-tools'; const CONFIG = require('../config/config.json'); /** diff --git a/test/byContract/IexecCategoryManager/IexecCategoryManager.js b/test/byContract/IexecCategoryManager/IexecCategoryManager.js deleted file mode 100644 index 981a76e54..000000000 --- a/test/byContract/IexecCategoryManager/IexecCategoryManager.js +++ /dev/null @@ -1,142 +0,0 @@ -// SPDX-FileCopyrightText: 2020-2024 IEXEC BLOCKCHAIN TECH -// SPDX-License-Identifier: Apache-2.0 - -const loadTruffleFixtureDeployment = require('../../../scripts/truffle-fixture-deployer'); -// Config -var DEPLOYMENT = require('../../../config/config.json').chains.default; -// Artefacts -var RLC = artifacts.require('rlc-faucet-contract/contracts/RLC'); -var ERC1538Proxy = artifacts.require('iexec-solidity/ERC1538Proxy'); -var IexecInterface = artifacts.require(`IexecInterface${DEPLOYMENT.asset}`); -var AppRegistry = artifacts.require('AppRegistry'); -var DatasetRegistry = artifacts.require('DatasetRegistry'); -var WorkerpoolRegistry = artifacts.require('WorkerpoolRegistry'); -var App = artifacts.require('App'); -var Dataset = artifacts.require('Dataset'); -var Workerpool = artifacts.require('Workerpool'); - -const { BN, expectEvent, expectRevert } = require('@openzeppelin/test-helpers'); -const tools = require('../../../utils/tools'); -const enstools = require('../../../utils/ens-tools'); -const odbtools = require('../../../utils/odb-tools'); -const constants = require('../../../utils/constants'); - -Object.extract = (obj, keys) => keys.map((key) => obj[key]); - -contract('CategoryManager', async (accounts) => { - assert.isAtLeast(accounts.length, 10, 'should have at least 10 accounts'); - let iexecAdmin = null; - let appProvider = null; - let datasetProvider = null; - let scheduler = null; - let worker1 = null; - let worker2 = null; - let worker3 = null; - let worker4 = null; - let worker5 = null; - let user = null; - - var RLCInstance = null; - var IexecInstance = null; - var AppRegistryInstance = null; - var DatasetRegistryInstance = null; - var WorkerpoolRegistryInstance = null; - - var categories = []; - - /*************************************************************************** - * Environment configuration * - ***************************************************************************/ - before('configure', async () => { - await loadTruffleFixtureDeployment(); - console.log('# web3 version:', web3.version); - - /** - * Retreive deployed contracts - */ - IexecInstance = await IexecInterface.at((await ERC1538Proxy.deployed()).address); - AppRegistryInstance = await AppRegistry.deployed(); - DatasetRegistryInstance = await DatasetRegistry.deployed(); - WorkerpoolRegistryInstance = await WorkerpoolRegistry.deployed(); - ERC712_domain = await IexecInstance.domain(); - RLCInstance = - DEPLOYMENT.asset == 'Native' - ? { address: constants.NULL.ADDRESS } - : await RLC.at(await IexecInstance.token()); - - broker = new odbtools.Broker(IexecInstance); - iexecAdmin = new odbtools.iExecAgent(IexecInstance, accounts[0]); - appProvider = new odbtools.iExecAgent(IexecInstance, accounts[1]); - datasetProvider = new odbtools.iExecAgent(IexecInstance, accounts[2]); - scheduler = new odbtools.Scheduler(IexecInstance, accounts[3]); - worker1 = new odbtools.Worker(IexecInstance, accounts[4]); - worker2 = new odbtools.Worker(IexecInstance, accounts[5]); - worker3 = new odbtools.Worker(IexecInstance, accounts[6]); - worker4 = new odbtools.Worker(IexecInstance, accounts[7]); - worker5 = new odbtools.Worker(IexecInstance, accounts[8]); - user = new odbtools.iExecAgent(IexecInstance, accounts[9]); - await broker.initialize(); - }); - - describe('view', async () => { - describe('invalid index', async () => { - it('reverts', async () => { - assert.equal(await IexecInstance.countCategory(), 5, 'Error in category count'); - // Needs to be checked as an assertion not a revert because it fails - // with the error "VM Exception while processing transaction: invalid opcode" - await expectRevert.assertion(IexecInstance.viewCategory(5)); - assert.equal(await IexecInstance.countCategory(), 5, 'Error in category count'); - }); - }); - }); - - describe('create', async () => { - describe('unauthorized create', async () => { - it('reverts', async () => { - assert.equal(await IexecInstance.countCategory(), 5, 'Error in category count'); - await expectRevert.unspecified( - IexecInstance.createCategory( - 'fake category', - 'this is an attack', - 0xffffffffff, - { from: user.address }, - ), - ); - assert.equal(await IexecInstance.countCategory(), 5, 'Error in category count'); - }); - }); - - describe('authorized', async () => { - it('success', async () => { - assert.equal(await IexecInstance.countCategory(), 5, 'Error in category count'); - - txMined = await IexecInstance.createCategory('Tiny', 'Small but impractical', 3, { - from: iexecAdmin.address, - }); - }); - - it('emits event', async () => { - events = tools.extractEvents(txMined, IexecInstance.address, 'CreateCategory'); - assert.equal(events[0].args.catid, 5, 'check catid'); - assert.equal(events[0].args.name, 'Tiny', 'check name'); - assert.equal( - events[0].args.description, - 'Small but impractical', - 'check description', - ); - assert.equal(events[0].args.workClockTimeRef, 3, 'check workClockTimeRef'); - }); - - it('count update', async () => { - assert.equal(await IexecInstance.countCategory(), 6, 'Error in category count'); - }); - - it('view newly created category', async () => { - category = await IexecInstance.viewCategory(5); - assert.equal(category.name, 'Tiny', 'check name'); - assert.equal(category.description, 'Small but impractical', 'check description'); - assert.equal(category.workClockTimeRef, 3, 'check workClockTimeRef'); - }); - }); - }); -}); diff --git a/test/byContract/IexecCategoryManager/IexecCategoryManager.ts b/test/byContract/IexecCategoryManager/IexecCategoryManager.ts new file mode 100644 index 000000000..6cd031fef --- /dev/null +++ b/test/byContract/IexecCategoryManager/IexecCategoryManager.ts @@ -0,0 +1,72 @@ +// SPDX-FileCopyrightText: 2020-2024 IEXEC BLOCKCHAIN TECH +// SPDX-License-Identifier: Apache-2.0 + +import { loadFixture } from '@nomicfoundation/hardhat-network-helpers'; +import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers'; +import { expect } from 'hardhat'; +import { loadHardhatFixtureDeployment } from '../../../scripts/hardhat-fixture-deployer'; +import { IexecInterfaceNative, IexecInterfaceNative__factory } from '../../../typechain'; +import { Category, getIexecAccounts } from '../../../utils/poco-tools'; +const CONFIG = require('../../../config/config.json'); + +const name = 'name'; +const description = 'description'; +const timeRef = 100; +const args = [name, description, timeRef] as [string, string, number]; + +describe('CategoryManager', async () => { + let proxyAddress: string; + let [iexecPoco, iexecPocoAsAnyone]: IexecInterfaceNative[] = []; + let [iexecAdmin, anyone]: SignerWithAddress[] = []; + + beforeEach('Deploy', async () => { + // Deploy all contracts + proxyAddress = await loadHardhatFixtureDeployment(); + // Initialize test environment + await loadFixture(initFixture); + }); + + async function initFixture() { + const accounts = await getIexecAccounts(); + ({ iexecAdmin, anyone } = accounts); + iexecPoco = IexecInterfaceNative__factory.connect(proxyAddress, iexecAdmin); + iexecPocoAsAnyone = iexecPoco.connect(anyone); + } + + it('Should view categories', async () => { + const categories = CONFIG.categories as Category[]; + for (let i = 0; i < categories.length; i++) { + const expectedCategory = categories[i]; + const category = await iexecPocoAsAnyone.viewCategory(i); + expect(category.name).to.equal(expectedCategory.name); + expect(category.description).to.equal(JSON.stringify(expectedCategory.description)); + expect(category.workClockTimeRef).to.equal(expectedCategory.workClockTimeRef); + } + }); + + it('Should not view category with bad index', async () => { + const lastCategoryIndex = (await iexecPocoAsAnyone.countCategory()).toNumber() - 1; + await expect( + iexecPocoAsAnyone.viewCategory(lastCategoryIndex + 1), + ).to.be.revertedWithoutReason(); + }); + + it('Should create category', async () => { + const newCategoryIndex = 5; + expect(await iexecPoco.callStatic.createCategory(...args)).to.equal(newCategoryIndex); + await expect(iexecPoco.createCategory(...args)) + .to.emit(iexecPoco, 'CreateCategory') + .withArgs(newCategoryIndex, name, description, timeRef); + expect(await iexecPocoAsAnyone.countCategory()).to.equal(6); + const category = await iexecPocoAsAnyone.viewCategory(newCategoryIndex); + expect(category.name).to.equal(name); + expect(category.description).to.equal(description); + expect(category.workClockTimeRef).to.equal(timeRef); + }); + + it('Should not create category when sender not authorized', async () => { + await expect(iexecPocoAsAnyone.createCategory(...args)).to.be.revertedWith( + 'Ownable: caller is not the owner', + ); + }); +}); diff --git a/utils/poco-tools.ts b/utils/poco-tools.ts index d80d2560b..c160081d7 100644 --- a/utils/poco-tools.ts +++ b/utils/poco-tools.ts @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: 2023 IEXEC BLOCKCHAIN TECH +// SPDX-FileCopyrightText: 2023-2024 IEXEC BLOCKCHAIN TECH // SPDX-License-Identifier: Apache-2.0 import { TypedDataDomain } from '@ethersproject/abstract-signer'; @@ -8,6 +8,12 @@ import { ethers } from 'hardhat'; import { IexecLibOrders_v5 } from '../typechain'; import { hashOrder } from './createOrders'; +export interface Category { + name: string; + description: string; + workClockTimeRef: number; +} + export enum TaskStatusEnum { UNSET, ACTIVE,