diff --git a/contracts/IStudentRegistry.sol b/contracts/IStudentRegistry.sol index b87e8bbe..5badcb6b 100644 --- a/contracts/IStudentRegistry.sol +++ b/contracts/IStudentRegistry.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity ^0.8.19; import "./Student.sol"; interface IStudentRegistry { diff --git a/contracts/Student.sol b/contracts/Student.sol index f7246ea0..506afe8d 100644 --- a/contracts/Student.sol +++ b/contracts/Student.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity ^0.8.19; struct Student { address studentAddr; string name; diff --git a/contracts/StudentRegistry.sol b/contracts/StudentRegistry.sol index 591618e1..eaa55510 100644 --- a/contracts/StudentRegistry.sol +++ b/contracts/StudentRegistry.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; +pragma solidity ^0.8.19; import "./Ownable.sol"; import "./Student.sol"; diff --git a/hardhat.config.js b/hardhat.config.js index 8ba99bc9..87c52f5f 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -2,5 +2,5 @@ require("@nomicfoundation/hardhat-toolbox"); /** @type import('hardhat/config').HardhatUserConfig */ module.exports = { - solidity: "0.8.24", + solidity: "0.8.19", }; diff --git a/package-lock.json b/package-lock.json index 11bfb810..331b33d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,9 @@ "packages": { "": { "name": "hardhat-project", + "dependencies": { + "ethers": "^6.13.2" + }, "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^5.0.0", "hardhat": "^2.22.6" @@ -14,9 +17,7 @@ "version": "1.10.1", "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", - "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", @@ -973,9 +974,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", - "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@noble/hashes": "1.3.2" }, @@ -987,9 +986,7 @@ "version": "1.3.2", "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", - "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">= 16" }, @@ -2099,9 +2096,7 @@ "version": "4.0.0-beta.5", "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", - "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/agent-base": { "version": "6.0.2", @@ -3728,7 +3723,6 @@ "version": "6.13.2", "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.2.tgz", "integrity": "sha512-9VkriTTed+/27BGuY1s0hf441kqwHJ1wtN2edksEtiRvXx+soxRX3iSXTfFqq2+YwrOqbDoTHjIhQnjJRlzKmg==", - "dev": true, "funding": [ { "type": "individual", @@ -3739,8 +3733,6 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], - "license": "MIT", - "peer": true, "dependencies": { "@adraffy/ens-normalize": "1.10.1", "@noble/curves": "1.2.0", @@ -3758,9 +3750,7 @@ "version": "18.15.13", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==", - "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/ethjs-unit": { "version": "0.1.6", @@ -7192,9 +7182,7 @@ "version": "2.4.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", - "dev": true, - "license": "0BSD", - "peer": true + "license": "0BSD" }, "node_modules/tsort": { "version": "0.0.1", @@ -7650,9 +7638,7 @@ "version": "8.17.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10.0.0" }, diff --git a/package.json b/package.json index d66eef1c..b72ceefe 100644 --- a/package.json +++ b/package.json @@ -3,5 +3,8 @@ "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^5.0.0", "hardhat": "^2.22.6" + }, + "dependencies": { + "ethers": "^6.13.2" } -} \ No newline at end of file +} diff --git a/test/Counter.js b/test/Counter.js index 6cde3045..e3eedd22 100644 --- a/test/Counter.js +++ b/test/Counter.js @@ -2,7 +2,7 @@ const { time, loadFixture, } = require("@nomicfoundation/hardhat-toolbox/network-helpers"); - // const { anyValue } = require("@nomicfoundation/hardhat-chai-matchers/withArgs"); + const { anyValue } = require("@nomicfoundation/hardhat-chai-matchers/withArgs"); const { expect } = require("chai"); // const { ethers } = require("hardhat"); @@ -101,5 +101,33 @@ const { }); }); }); + + describe("Events", () => { + it("should emit an event when count is increased", async () => { + const deployedCounter = await loadFixture(deployUtil); + + const count1 = await deployedCounter.count(); + console.log("count1 ___", count1); + expect(count1).to.eq(0); + + await expect(deployedCounter.increaseByOne()) + .to.emit(deployedCounter, "CountIncreased") + .withArgs(count1 + BigInt(1), anyValue) + }) + + it("should emit an event when count is decreased", async () => { + const deployedCounter = await loadFixture(deployUtil); + + await deployedCounter.increaseByOne(); + + const count1 = await deployedCounter.count(); + console.log("count1 ____", count1); + expect(count1).to.eq(1); + + await expect(deployedCounter.decreaseByOne()) + .to.emit(deployedCounter, "CountDecreased") + .withArgs(count1 - BigInt(1), anyValue) + }) + }); }); \ No newline at end of file diff --git a/test/StudentRegistry.js b/test/StudentRegistry.js new file mode 100644 index 00000000..3b721b8f --- /dev/null +++ b/test/StudentRegistry.js @@ -0,0 +1,145 @@ +const { + time, + loadFixture, + } = require("@nomicfoundation/hardhat-toolbox/network-helpers"); + const { anyValue } = require("@nomicfoundation/hardhat-chai-matchers/withArgs"); + const { ethers } = require("hardhat"); + const { expect } = require("chai"); + + const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000"; + + describe("Student Registry Test Suite", () => { + // deployUtil function + const deployUtil = async () => { + const [owner, newOwner, otherAccount] = await ethers.getSigners(); + const StudentRegistry = await ethers.getContractFactory("StudentRegistry"); + const deployedRegistry = await StudentRegistry.deploy(); + return {deployedRegistry, owner, newOwner, otherAccount}; + } + + describe("Student Mapping", () => { + it("should return correct details from mapping", async () => { + const { deployedRegistry, otherAccount } = await loadFixture(deployUtil); + + await expect( + deployedRegistry.studentsMapping(otherAccount) + ).to.not.be.reverted; + }) + }) + + describe("Add Students", () => { + it("should add a student successfully", async () => { + const { deployedRegistry, otherAccount } = await loadFixture(deployUtil); + + await expect( + deployedRegistry.connect(otherAccount).addStudent(otherAccount.address, "Made", 19) + ).to.not.be.reverted; + }) + + it("should be reverted when name is empty", async () => { + const { deployedRegistry, otherAccount } = await loadFixture(deployUtil); + + await expect( + deployedRegistry.connect(otherAccount).addStudent(otherAccount.address, "", 19) + ).to.be.revertedWithCustomError(deployedRegistry, "NameIsEmpty"); + }) + + it("should be reverted when age is less than 18", async () => { + const { deployedRegistry, otherAccount } = await loadFixture(deployUtil); + + await expect( + deployedRegistry.connect(otherAccount).addStudent(otherAccount.address, "John", 12) + ).to.be.revertedWithCustomError(deployedRegistry, "UnderAge").withArgs(12, 18); + }) + }) + + describe("Delete Students", () => { + it("should delete a student successfully", async () => { + const { deployedRegistry, owner, otherAccount } = await loadFixture(deployUtil); + + await deployedRegistry.addStudent(otherAccount.address, "John", 19); + + await expect( + deployedRegistry.connect(owner).deleteStudent(otherAccount.address)) + .to.not.be.reverted; + }) + + it("should be reverted when another account tries to delete", async () => { + const { deployedRegistry, otherAccount } = await loadFixture(deployUtil); + + await expect( + deployedRegistry.connect(otherAccount).deleteStudent(otherAccount.address)) + .to.be.revertedWith("Caller not owner"); + }) + + it("should be reverted when trying to delete a student that has not been added", async () => { + const { deployedRegistry, owner, otherAccount } = await loadFixture(deployUtil); + + await expect( + deployedRegistry.connect(owner).deleteStudent(otherAccount.address) + ).to.be.revertedWith("Student does not exist"); + }) + }) + + describe("Get Students", () => { + it("should get student successfully", async() => { + const { deployedRegistry, otherAccount } = await loadFixture(deployUtil); + + await deployedRegistry.addStudent(otherAccount.address, "John", 19); + + await expect( + deployedRegistry.getStudent(1) + ).to.not.be.reverted; + }) + + it("should revert when an invalid ID is used to get student", async() => { + const { deployedRegistry, otherAccount } = await loadFixture(deployUtil); + + await deployedRegistry.addStudent(otherAccount.address, "John", 19); + + await expect( + deployedRegistry.getStudent(0) + ).to.be.reverted; + }) + }) + + describe("Get Student From Mapping", () => { + it("should successfully get student from mapping", async () => { + const { deployedRegistry, otherAccount } = await loadFixture(deployUtil); + + await deployedRegistry.addStudent(otherAccount.address, "John", 19); + + await expect( + deployedRegistry.connect(otherAccount).getStudentFromMapping(otherAccount.address) + ).to.not.be.reverted; + }) + + }) + + describe("Modify Owner", () => { + it("should successfully modify owner", async () => { + const { deployedRegistry, owner, newOwner } = await loadFixture(deployUtil); + + await expect( + deployedRegistry.connect(owner).modifyOwner(newOwner.address) + ).to.not.be.reverted; + }) + + it("should be reverted when other account tries to change owner", async () => { + const { deployedRegistry, otherAccount, newOwner } = await loadFixture(deployUtil); + + await expect( + deployedRegistry.connect(otherAccount).modifyOwner(newOwner.address) + ).to.be.revertedWith("Caller not owner"); + }) + + it("should revert when trying to set new owner as address zero", async () => { + const { deployedRegistry, owner } = await loadFixture(deployUtil); + + await expect( + deployedRegistry.connect(owner).modifyOwner(ZERO_ADDRESS) + ).to.be.revertedWith("Owner can not be address zero"); + }) + }) + + }); \ No newline at end of file