From adffcb67f240f90bf248c21e80a39b9b37df4a5b Mon Sep 17 00:00:00 2001 From: Behzad Rabiei <53224485+Behzad-rabiei@users.noreply.github.com> Date: Fri, 19 Jul 2024 22:17:43 +0400 Subject: [PATCH] feat: complete the updateApplication function --- contracts/ApplicationManager.sol | 29 ++++++++++--- test/ApplicationManager.ts | 73 +++++++++++++++++++++++++++++--- 2 files changed, 91 insertions(+), 11 deletions(-) diff --git a/contracts/ApplicationManager.sol b/contracts/ApplicationManager.sol index 5daa5ac..fe9122f 100644 --- a/contracts/ApplicationManager.sol +++ b/contracts/ApplicationManager.sol @@ -5,27 +5,44 @@ import {IApplicationManager} from "./IApplicationManager.sol"; contract ApplicationManager is IApplicationManager { mapping(uint => Application) private applications; + mapping(address => bool) private addressUsed; uint private nextApplicationId; constructor() {} - function getNextApplicationId() external view returns (uint) { + function applicationExists(uint id) internal view returns (bool) { + return applications[id].account != address(0); + } + function getNextApplicationId() external view override returns (uint) { return nextApplicationId; } - function createApplication(Application memory application) external { + function createApplication(Application memory application) external override { + require(!addressUsed[application.account], "Address already used for another application"); applications[nextApplicationId] = application; + addressUsed[application.account] = true; emit ApplicationCreated(nextApplicationId, applications[nextApplicationId]); nextApplicationId++; } - function updateApplication(uint id, Application memory application) external override {} + function updateApplication(uint id, Application memory application) external override { + require(applicationExists(id), "Application does not exist"); + require(!addressUsed[application.account] || applications[id].account == application.account, + "Address already used for another application"); + applications[id] = application; + emit ApplicationUpdated(id, applications[id]); + } - function deleteApplication(uint id) external override {} + function deleteApplication(uint id) external override { + } - function getApplication(uint id) external view returns (Application memory) { + function getApplication(uint id) external view override returns (Application memory) { + require(applicationExists(id), "Application does not exist"); return applications[id]; } - function getApplications(uint start, uint limit) external override returns (Application[] memory application) {} + function getApplications(uint start, uint limit) external view override returns (Application[] memory) { + } + + } diff --git a/test/ApplicationManager.ts b/test/ApplicationManager.ts index fc3d36f..582d29d 100644 --- a/test/ApplicationManager.ts +++ b/test/ApplicationManager.ts @@ -1,7 +1,11 @@ import { loadFixture } from "@nomicfoundation/hardhat-toolbox-viem/network-helpers"; import { expect } from "chai"; import hre from "hardhat"; -import { type Address, getAddress, parseUnits } from "viem"; +import { type Address, getAddress, parseUnits, } from "viem"; +import { generatePrivateKey,privateKeyToAccount } from 'viem/accounts' + +const privateKey = generatePrivateKey() + interface Application { name: string; @@ -43,18 +47,17 @@ describe("ApplicationManager", () => { // biome-ignore lint/suspicious/noExplicitAny: let contract: any; let app: Application; - + let account= privateKeyToAccount(generatePrivateKey()).address beforeEach(async () => { const fixture = await loadFixture(deploy); contract = fixture.contract; - app = { name: "app", - account: getAddress(fixture.app1Account.account.address), + account, }; }); - it("Should accept name (string) and account (address) as inputs", async () => { + it("Should accept Application as inputs", async () => { expect(await contract.write.createApplication([app])).to.be.string; }); it("Should increment nextApplicationId", async () => { @@ -85,5 +88,65 @@ describe("ApplicationManager", () => { expect(event.args.id).to.be.equal(applicationId); expect(event.args.application).to.contain(app); }); + + it("Should revert if the account address is already used", async () => { + await contract.write.createApplication([app]); + await expect(contract.write.createApplication([app])).to.be.rejectedWith( + "Address already used for another application" + ); + }); + }); + + describe("updateApplication", () => { + // biome-ignore lint/suspicious/noExplicitAny: + let contract: any; + let app: Application; + let applicationId: string; + let account= privateKeyToAccount(generatePrivateKey()).address + + beforeEach(async () => { + const fixture = await loadFixture(deploy); + contract = fixture.contract; + + app = { + name: "app", + account, + }; + + applicationId = await contract.read.getNextApplicationId(); + await contract.write.createApplication([app]); + }); + + it("Should accept Application as inputs", async () => { + expect(await contract.write.updateApplication([applicationId, app])).to.be + .string; + }); + it("Should update the Application struct in the applications mapping with the provided applicationId to have the application data", async () => { + await contract.write.updateApplication([ + applicationId, + { account: app.account, name: "new app name" }, + ]); + expect(await contract.read.getApplication([applicationId])).to.contain({ + account: app.account, + name: "new app name", + }); + }); + it("Should revert if the account address is already used", async () => { + const t1 = await contract.read.getNextApplicationId(); + expect(t1).to.equal(parseUnits("1", 0)); + await contract.write.createApplication([{ + account: privateKeyToAccount(generatePrivateKey()).address, + name: "new app" + }]); + + await expect(contract.write.updateApplication([t1, app])).to.be.rejectedWith( + "Address already used for another application" + ); + }); + it("Should revert if the application does not exist", async () => { + await expect(contract.write.updateApplication(["1", app])).to.be.rejectedWith( + "Application does not exist" + ); + }); }); });