chore: refactor hardhat tests (#103)
* chore: rearrange hardhat tests folder structure * chore: add FleekERC721 hardhat test helpers * test: split out deployment tests * test: split out minting tests * test: split out token uri tests * test: split out token roles tests * test: split out collection roles tests * test: split out access points tests * test: split out update properties tests * test: improve test setup for aps and deployment * test: move test resultant base64 logos to constants file
This commit is contained in:
parent
0af0da7477
commit
18d3319fd7
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,211 @@
|
|||
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
|
||||
import { expect } from 'chai';
|
||||
import { Fixtures } from './helpers';
|
||||
|
||||
describe('AccessPoints', () => {
|
||||
let fixture: Awaited<ReturnType<typeof Fixtures.withMint>>;
|
||||
const DefaultAP = 'accesspoint.com';
|
||||
|
||||
beforeEach(async () => {
|
||||
fixture = await loadFixture(Fixtures.withMint);
|
||||
fixture.contract.addAccessPoint(fixture.tokenId, DefaultAP);
|
||||
});
|
||||
|
||||
it('should add an AP', async () => {
|
||||
const { contract, owner, tokenId } = fixture;
|
||||
|
||||
await expect(contract.addAccessPoint(tokenId, 'random.com'))
|
||||
.to.emit(contract, 'NewAccessPoint')
|
||||
.withArgs('random.com', tokenId, owner.address);
|
||||
|
||||
expect(await contract.appAccessPoints(tokenId)).eql([
|
||||
DefaultAP,
|
||||
'random.com',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should return a AP json object', async () => {
|
||||
const { contract, owner, tokenId } = fixture;
|
||||
|
||||
const ap = await contract.getAccessPointJSON(DefaultAP);
|
||||
const parsedAp = JSON.parse(ap);
|
||||
|
||||
expect(parsedAp).to.eql({
|
||||
tokenId,
|
||||
score: 0,
|
||||
owner: owner.address.toLowerCase(),
|
||||
contentVerified: false,
|
||||
nameVerified: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('should revert if AP does not exist', async () => {
|
||||
const { contract, tokenId } = fixture;
|
||||
|
||||
await expect(contract.getAccessPointJSON('random.com')).to.be.revertedWith(
|
||||
'FleekERC721: invalid AP'
|
||||
);
|
||||
});
|
||||
|
||||
it('should increase the AP score', async () => {
|
||||
const { contract, owner, tokenId } = fixture;
|
||||
|
||||
await contract.increaseAccessPointScore(DefaultAP);
|
||||
|
||||
const ap = await contract.getAccessPointJSON(DefaultAP);
|
||||
const parsedAp = JSON.parse(ap);
|
||||
|
||||
expect(parsedAp).to.eql({
|
||||
tokenId,
|
||||
score: 1,
|
||||
owner: owner.address.toLowerCase(),
|
||||
contentVerified: false,
|
||||
nameVerified: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('should decrease the AP score', async () => {
|
||||
const { contract, owner, tokenId } = fixture;
|
||||
|
||||
await contract.increaseAccessPointScore(DefaultAP);
|
||||
await contract.increaseAccessPointScore(DefaultAP);
|
||||
await contract.decreaseAccessPointScore(DefaultAP);
|
||||
|
||||
const ap = await contract.getAccessPointJSON(DefaultAP);
|
||||
const parsedAp = JSON.parse(ap);
|
||||
|
||||
expect(parsedAp).to.eql({
|
||||
tokenId,
|
||||
score: 1,
|
||||
owner: owner.address.toLowerCase(),
|
||||
contentVerified: false,
|
||||
nameVerified: false,
|
||||
});
|
||||
});
|
||||
|
||||
it('should allow anyone to change AP score', async () => {
|
||||
const { contract, otherAccount, tokenId } = fixture;
|
||||
|
||||
await contract.increaseAccessPointScore(DefaultAP);
|
||||
await contract.connect(otherAccount).increaseAccessPointScore(DefaultAP);
|
||||
});
|
||||
|
||||
it('should remove an AP', async () => {
|
||||
const { contract, owner, tokenId } = fixture;
|
||||
|
||||
await expect(contract.removeAccessPoint(DefaultAP))
|
||||
.to.emit(contract, 'RemoveAccessPoint')
|
||||
.withArgs(DefaultAP, tokenId, owner.address);
|
||||
|
||||
expect(await contract.appAccessPoints(tokenId)).eql([]);
|
||||
});
|
||||
|
||||
it('should allow only AP owner to remove it', async () => {
|
||||
const { contract, otherAccount } = fixture;
|
||||
|
||||
await expect(
|
||||
contract.connect(otherAccount).removeAccessPoint(DefaultAP)
|
||||
).to.be.revertedWith('FleekERC721: must be AP owner');
|
||||
});
|
||||
|
||||
it('should not be allowed to add the same AP more than once', async () => {
|
||||
const { contract, tokenId } = fixture;
|
||||
|
||||
await expect(
|
||||
contract.addAccessPoint(tokenId, DefaultAP)
|
||||
).to.be.revertedWith('FleekERC721: AP already exists');
|
||||
});
|
||||
|
||||
it('should change "contentVerified" to true', async () => {
|
||||
const { contract } = fixture;
|
||||
|
||||
await contract.setAccessPointContentVerify(DefaultAP, true);
|
||||
|
||||
const ap = await contract.getAccessPointJSON(DefaultAP);
|
||||
const parsedAp = JSON.parse(ap);
|
||||
|
||||
expect(parsedAp.contentVerified).to.be.true;
|
||||
});
|
||||
|
||||
it('should change "contentVerified" to false', async () => {
|
||||
const { contract } = fixture;
|
||||
|
||||
const beforeAp = await contract.getAccessPointJSON(DefaultAP);
|
||||
const beforeParsedAp = JSON.parse(beforeAp);
|
||||
expect(beforeParsedAp.contentVerified).to.be.false;
|
||||
|
||||
await contract.setAccessPointContentVerify(DefaultAP, true);
|
||||
await contract.setAccessPointContentVerify(DefaultAP, false);
|
||||
|
||||
const ap = await contract.getAccessPointJSON(DefaultAP);
|
||||
const parsedAp = JSON.parse(ap);
|
||||
|
||||
expect(parsedAp.contentVerified).to.be.false;
|
||||
});
|
||||
|
||||
it('should change "nameVerified" to true', async () => {
|
||||
const { contract } = fixture;
|
||||
|
||||
await contract.setAccessPointNameVerify(DefaultAP, true);
|
||||
|
||||
const ap = await contract.getAccessPointJSON(DefaultAP);
|
||||
const parsedAp = JSON.parse(ap);
|
||||
|
||||
expect(parsedAp.nameVerified).to.be.true;
|
||||
});
|
||||
|
||||
it('should change "nameVerified" to false', async () => {
|
||||
const { contract } = fixture;
|
||||
|
||||
const beforeAp = await contract.getAccessPointJSON(DefaultAP);
|
||||
const beforeParsedAp = JSON.parse(beforeAp);
|
||||
expect(beforeParsedAp.nameVerified).to.be.false;
|
||||
|
||||
await contract.setAccessPointNameVerify(DefaultAP, true);
|
||||
await contract.setAccessPointNameVerify(DefaultAP, false);
|
||||
|
||||
const ap = await contract.getAccessPointJSON(DefaultAP);
|
||||
const parsedAp = JSON.parse(ap);
|
||||
|
||||
expect(parsedAp.nameVerified).to.be.false;
|
||||
});
|
||||
|
||||
it('should get a list of added APs for an app', async () => {
|
||||
const { contract, tokenId } = fixture;
|
||||
|
||||
await contract.addAccessPoint(tokenId, 'accesspoint1.com');
|
||||
await contract.addAccessPoint(tokenId, 'accesspoint2.com');
|
||||
await contract.addAccessPoint(tokenId, 'accesspoint3.com');
|
||||
await contract.addAccessPoint(tokenId, 'accesspoint4.com');
|
||||
|
||||
const aps = await contract.appAccessPoints(tokenId);
|
||||
|
||||
expect(aps).to.eql([
|
||||
DefaultAP,
|
||||
'accesspoint1.com',
|
||||
'accesspoint2.com',
|
||||
'accesspoint3.com',
|
||||
'accesspoint4.com',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should get a list of added APs for an app after removing one', async () => {
|
||||
const { contract, tokenId } = fixture;
|
||||
|
||||
await contract.addAccessPoint(tokenId, 'accesspoint1.com');
|
||||
await contract.addAccessPoint(tokenId, 'accesspoint2.com');
|
||||
await contract.addAccessPoint(tokenId, 'accesspoint3.com');
|
||||
await contract.addAccessPoint(tokenId, 'accesspoint4.com');
|
||||
|
||||
await contract.removeAccessPoint('accesspoint2.com');
|
||||
|
||||
const aps = await contract.appAccessPoints(tokenId);
|
||||
|
||||
expect(aps).to.eql([
|
||||
DefaultAP,
|
||||
'accesspoint1.com',
|
||||
'accesspoint4.com',
|
||||
'accesspoint3.com',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,165 @@
|
|||
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
|
||||
import { expect } from 'chai';
|
||||
import { TestConstants, Fixtures } from './helpers';
|
||||
|
||||
const { Roles } = TestConstants;
|
||||
|
||||
describe('FleekERC721.CollectionRoles', () => {
|
||||
let fixture: Awaited<ReturnType<typeof Fixtures.default>>;
|
||||
|
||||
beforeEach(async () => {
|
||||
fixture = await loadFixture(Fixtures.default);
|
||||
});
|
||||
|
||||
it('should assign the owner of the contract on contract creation', async () => {
|
||||
const { owner, contract } = fixture;
|
||||
|
||||
expect(await contract.hasCollectionRole(Roles.Owner, owner.address)).to.be
|
||||
.true;
|
||||
});
|
||||
|
||||
it('should assign owner role to address', async () => {
|
||||
const { otherAccount, contract } = fixture;
|
||||
|
||||
await contract.grantCollectionRole(Roles.Owner, otherAccount.address);
|
||||
|
||||
expect(await contract.hasCollectionRole(Roles.Owner, otherAccount.address))
|
||||
.to.be.true;
|
||||
});
|
||||
|
||||
it('should assign controller role to address', async () => {
|
||||
const { owner, contract } = fixture;
|
||||
|
||||
await contract.grantCollectionRole(Roles.Controller, owner.address);
|
||||
|
||||
expect(await contract.hasCollectionRole(Roles.Controller, owner.address)).to
|
||||
.be.true;
|
||||
});
|
||||
|
||||
it('should remove an assigned controller', async () => {
|
||||
const { otherAccount, contract } = fixture;
|
||||
|
||||
await contract.grantCollectionRole(Roles.Owner, otherAccount.address);
|
||||
await contract.revokeCollectionRole(Roles.Owner, otherAccount.address);
|
||||
|
||||
expect(await contract.hasCollectionRole(Roles.Owner, otherAccount.address))
|
||||
.to.be.false;
|
||||
});
|
||||
|
||||
it('should remove an assigned controller', async () => {
|
||||
const { owner, contract } = fixture;
|
||||
|
||||
await contract.grantCollectionRole(Roles.Controller, owner.address);
|
||||
await contract.revokeCollectionRole(Roles.Controller, owner.address);
|
||||
|
||||
expect(await contract.hasCollectionRole(Roles.Controller, owner.address)).to
|
||||
.be.false;
|
||||
});
|
||||
|
||||
it('should fetch the list of controllers', async () => {
|
||||
const { owner, contract } = fixture;
|
||||
|
||||
await contract.grantCollectionRole(Roles.Controller, owner.address);
|
||||
await contract.grantCollectionRole(
|
||||
Roles.Controller,
|
||||
'0x7ED735b7095C05d78dF169F991f2b7f1A1F1A049'
|
||||
);
|
||||
|
||||
expect(await contract.getCollectionRoleMembers(Roles.Controller)).to.eql([
|
||||
owner.address,
|
||||
'0x7ED735b7095C05d78dF169F991f2b7f1A1F1A049',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should fetch the list of owners', async () => {
|
||||
const { owner, contract, otherAccount } = fixture;
|
||||
|
||||
await contract.grantCollectionRole(Roles.Owner, otherAccount.address);
|
||||
await contract.grantCollectionRole(
|
||||
Roles.Owner,
|
||||
'0x7ED735b7095C05d78dF169F991f2b7f1A1F1A049'
|
||||
);
|
||||
|
||||
expect(await contract.getCollectionRoleMembers(Roles.Owner)).to.eql([
|
||||
owner.address,
|
||||
otherAccount.address,
|
||||
'0x7ED735b7095C05d78dF169F991f2b7f1A1F1A049',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not be able to add new owner', async () => {
|
||||
const { otherAccount, contract } = fixture;
|
||||
|
||||
await expect(
|
||||
contract
|
||||
.connect(otherAccount)
|
||||
.grantCollectionRole(Roles.Owner, otherAccount.address)
|
||||
).to.be.revertedWith('FleekAccessControl: must have collection role');
|
||||
});
|
||||
|
||||
it('should not be able to add new controller', async () => {
|
||||
const { otherAccount, contract } = fixture;
|
||||
|
||||
await expect(
|
||||
contract
|
||||
.connect(otherAccount)
|
||||
.grantCollectionRole(Roles.Controller, otherAccount.address)
|
||||
).to.be.revertedWith('FleekAccessControl: must have collection role');
|
||||
});
|
||||
|
||||
it('should be able to add roles after owner being granted', async () => {
|
||||
const { otherAccount, contract } = fixture;
|
||||
|
||||
await contract.grantCollectionRole(Roles.Owner, otherAccount.address);
|
||||
|
||||
await expect(
|
||||
contract
|
||||
.connect(otherAccount)
|
||||
.grantCollectionRole(Roles.Controller, otherAccount.address)
|
||||
).to.not.be.reverted;
|
||||
await expect(
|
||||
contract
|
||||
.connect(otherAccount)
|
||||
.revokeCollectionRole(Roles.Controller, otherAccount.address)
|
||||
).to.not.be.reverted;
|
||||
});
|
||||
|
||||
it('should not be able to change roles for controllers', async () => {
|
||||
const { owner, otherAccount, contract } = fixture;
|
||||
|
||||
await contract.grantCollectionRole(Roles.Controller, otherAccount.address);
|
||||
|
||||
await expect(
|
||||
contract
|
||||
.connect(otherAccount)
|
||||
.grantCollectionRole(Roles.Owner, owner.address)
|
||||
).to.be.revertedWith('FleekAccessControl: must have collection role');
|
||||
await expect(
|
||||
contract
|
||||
.connect(otherAccount)
|
||||
.revokeCollectionRole(Roles.Owner, owner.address)
|
||||
).to.be.revertedWith('FleekAccessControl: must have collection role');
|
||||
});
|
||||
|
||||
it('should emit event when role is granted', async () => {
|
||||
const { owner, contract, otherAccount } = fixture;
|
||||
|
||||
await expect(
|
||||
contract.grantCollectionRole(Roles.Controller, otherAccount.address)
|
||||
)
|
||||
.to.emit(contract, 'CollectionRoleGranted')
|
||||
.withArgs(Roles.Controller, otherAccount.address, owner.address);
|
||||
});
|
||||
|
||||
it('should emit event when role is revoked', async () => {
|
||||
const { owner, contract, otherAccount } = fixture;
|
||||
|
||||
await contract.grantCollectionRole(Roles.Controller, otherAccount.address);
|
||||
|
||||
await expect(
|
||||
contract.revokeCollectionRole(Roles.Controller, otherAccount.address)
|
||||
)
|
||||
.to.emit(contract, 'CollectionRoleRevoked')
|
||||
.withArgs(Roles.Controller, otherAccount.address, owner.address);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
|
||||
import { expect } from 'chai';
|
||||
import { TestConstants, Fixtures } from './helpers';
|
||||
|
||||
describe('FleekERC721.Deployment', () => {
|
||||
let fixture: Awaited<ReturnType<typeof Fixtures.default>>;
|
||||
|
||||
beforeEach(async () => {
|
||||
fixture = await loadFixture(Fixtures.default);
|
||||
});
|
||||
|
||||
it('should assign the name and the symbol of the ERC721 contract', async () => {
|
||||
const { contract } = fixture;
|
||||
|
||||
expect(await contract.name()).to.equal(TestConstants.CollectionParams.name);
|
||||
expect(await contract.symbol()).to.equal(
|
||||
TestConstants.CollectionParams.symbol
|
||||
);
|
||||
});
|
||||
|
||||
it('should support ERC721 interface', async () => {
|
||||
const { contract } = fixture;
|
||||
|
||||
expect(await contract.supportsInterface('0x80ac58cd')).to.equal(true);
|
||||
});
|
||||
});
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,49 @@
|
|||
import { ethers, upgrades } from 'hardhat';
|
||||
import { TestConstants } from './constants';
|
||||
|
||||
export abstract class Fixtures {
|
||||
static async default() {
|
||||
// Contracts are deployed using the first signer/account by default
|
||||
const [owner, otherAccount] = await ethers.getSigners();
|
||||
|
||||
const libraries = {
|
||||
FleekSVG: (await (await ethers.getContractFactory('FleekSVG')).deploy())
|
||||
.address,
|
||||
};
|
||||
|
||||
const Contract = await ethers.getContractFactory('FleekERC721', {
|
||||
libraries,
|
||||
});
|
||||
const contract = await upgrades.deployProxy(
|
||||
Contract,
|
||||
[
|
||||
TestConstants.CollectionParams.name,
|
||||
TestConstants.CollectionParams.symbol,
|
||||
],
|
||||
{
|
||||
unsafeAllow: ['external-library-linking'],
|
||||
}
|
||||
);
|
||||
|
||||
return { owner, otherAccount, contract };
|
||||
}
|
||||
|
||||
static async withMint() {
|
||||
const fromDefault = await Fixtures.default();
|
||||
|
||||
const response = await fromDefault.contract.mint(
|
||||
fromDefault.owner.address,
|
||||
TestConstants.MintParams.name,
|
||||
TestConstants.MintParams.description,
|
||||
TestConstants.MintParams.externalUrl,
|
||||
TestConstants.MintParams.ens,
|
||||
TestConstants.MintParams.commitHash,
|
||||
TestConstants.MintParams.gitRepository,
|
||||
TestConstants.MintParams.logo,
|
||||
TestConstants.MintParams.color
|
||||
);
|
||||
|
||||
const tokenId = response.value.toNumber();
|
||||
return { ...fromDefault, tokenId };
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
export * from './constants';
|
||||
export * from './fixture';
|
||||
export * from './utils';
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
export const parseTokenURI = (tokenURI: string) => {
|
||||
const tokenURIDecoded = Buffer.from(
|
||||
tokenURI.replace('data:application/json;base64,', ''),
|
||||
'base64'
|
||||
).toString('ascii');
|
||||
|
||||
return JSON.parse(tokenURIDecoded);
|
||||
};
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
|
||||
import { expect } from 'chai';
|
||||
import { TestConstants, Fixtures } from './helpers';
|
||||
import { ethers } from 'hardhat';
|
||||
|
||||
const { MintParams, Roles } = TestConstants;
|
||||
|
||||
describe('FleekERC721.Minting', () => {
|
||||
it('should be able to mint a new token', async () => {
|
||||
const { owner, contract } = await loadFixture(Fixtures.default);
|
||||
|
||||
const response = await contract.mint(
|
||||
owner.address,
|
||||
MintParams.name,
|
||||
MintParams.description,
|
||||
MintParams.externalUrl,
|
||||
MintParams.ens,
|
||||
MintParams.commitHash,
|
||||
MintParams.gitRepository,
|
||||
MintParams.logo,
|
||||
MintParams.color
|
||||
);
|
||||
|
||||
expect(response.value).to.be.instanceOf(ethers.BigNumber);
|
||||
expect(response.value.toNumber()).to.equal(0);
|
||||
});
|
||||
|
||||
it('should not be able to mint a new token if not the owner', async () => {
|
||||
const { otherAccount, contract } = await loadFixture(Fixtures.default);
|
||||
|
||||
await expect(
|
||||
contract
|
||||
.connect(otherAccount)
|
||||
.mint(
|
||||
otherAccount.address,
|
||||
MintParams.name,
|
||||
MintParams.description,
|
||||
MintParams.externalUrl,
|
||||
MintParams.ens,
|
||||
MintParams.commitHash,
|
||||
MintParams.gitRepository,
|
||||
MintParams.logo,
|
||||
MintParams.color
|
||||
)
|
||||
).to.be.revertedWith('FleekAccessControl: must have collection role');
|
||||
});
|
||||
|
||||
it('should have address to as owner', async () => {
|
||||
const { owner, otherAccount, contract } = await loadFixture(
|
||||
Fixtures.default
|
||||
);
|
||||
|
||||
const response = await contract.mint(
|
||||
owner.address,
|
||||
MintParams.name,
|
||||
MintParams.description,
|
||||
MintParams.externalUrl,
|
||||
MintParams.ens,
|
||||
MintParams.commitHash,
|
||||
MintParams.gitRepository,
|
||||
MintParams.logo,
|
||||
MintParams.color
|
||||
);
|
||||
|
||||
const tokenId = response.value.toNumber();
|
||||
|
||||
expect(await contract.ownerOf(tokenId)).to.equal(owner.address);
|
||||
expect(await contract.hasTokenRole(tokenId, Roles.Owner, owner.address)).to
|
||||
.be.true;
|
||||
|
||||
expect(await contract.ownerOf(tokenId)).not.to.equal(otherAccount.address);
|
||||
expect(
|
||||
await contract.hasTokenRole(tokenId, Roles.Owner, otherAccount.address)
|
||||
).to.be.false;
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,209 @@
|
|||
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
|
||||
import { expect } from 'chai';
|
||||
import { TestConstants, Fixtures, parseTokenURI } from './helpers';
|
||||
|
||||
const { Roles } = TestConstants;
|
||||
|
||||
describe('FleekERC721.TokenRoles', () => {
|
||||
let fixture: Awaited<ReturnType<typeof Fixtures.withMint>>;
|
||||
|
||||
beforeEach(async () => {
|
||||
fixture = await loadFixture(Fixtures.withMint);
|
||||
});
|
||||
|
||||
it('should match the token owner', async () => {
|
||||
const { contract, owner, tokenId } = fixture;
|
||||
const tokenOwner = await contract.ownerOf(tokenId);
|
||||
expect(tokenOwner).to.equal(owner.address);
|
||||
});
|
||||
|
||||
it('should match the owner role for minter', async () => {
|
||||
const { contract, owner, tokenId } = fixture;
|
||||
const hasRole = await contract.hasTokenRole(
|
||||
tokenId,
|
||||
Roles.Owner,
|
||||
owner.address
|
||||
);
|
||||
|
||||
expect(hasRole).to.be.true;
|
||||
});
|
||||
|
||||
it('should add a new controller', async () => {
|
||||
const { contract, owner, otherAccount, tokenId } = fixture;
|
||||
await contract.grantTokenRole(
|
||||
tokenId,
|
||||
Roles.Controller,
|
||||
otherAccount.address
|
||||
);
|
||||
|
||||
expect(
|
||||
await contract.hasTokenRole(
|
||||
tokenId,
|
||||
Roles.Controller,
|
||||
otherAccount.address
|
||||
)
|
||||
).to.be.true;
|
||||
});
|
||||
|
||||
it('should add a list of controllers', async () => {
|
||||
const { contract, tokenId } = fixture;
|
||||
await contract.grantTokenRole(
|
||||
tokenId,
|
||||
Roles.Controller,
|
||||
'0x7ED735b7095C05d78dF169F991f2b7f1A1F1A049'
|
||||
);
|
||||
await contract.grantTokenRole(
|
||||
tokenId,
|
||||
Roles.Controller,
|
||||
'0x2FEd6Ef3c495922263B403319FA6DDB323DD49E3'
|
||||
);
|
||||
|
||||
expect(
|
||||
await contract.getTokenRoleMembers(tokenId, Roles.Controller)
|
||||
).to.eql([
|
||||
'0x7ED735b7095C05d78dF169F991f2b7f1A1F1A049',
|
||||
'0x2FEd6Ef3c495922263B403319FA6DDB323DD49E3',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should add a list of owners', async () => {
|
||||
const { contract, owner, tokenId } = fixture;
|
||||
await contract.grantTokenRole(
|
||||
tokenId,
|
||||
Roles.Owner,
|
||||
'0x7ED735b7095C05d78dF169F991f2b7f1A1F1A049'
|
||||
);
|
||||
await contract.grantTokenRole(
|
||||
tokenId,
|
||||
Roles.Owner,
|
||||
'0x2FEd6Ef3c495922263B403319FA6DDB323DD49E3'
|
||||
);
|
||||
|
||||
expect(await contract.getTokenRoleMembers(tokenId, Roles.Owner)).to.eql([
|
||||
owner.address,
|
||||
'0x7ED735b7095C05d78dF169F991f2b7f1A1F1A049',
|
||||
'0x2FEd6Ef3c495922263B403319FA6DDB323DD49E3',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should not match the owner role for other account', async () => {
|
||||
const { contract, otherAccount, tokenId } = fixture;
|
||||
const hasRole = await contract.hasTokenRole(
|
||||
tokenId,
|
||||
Roles.Owner,
|
||||
otherAccount.address
|
||||
);
|
||||
|
||||
expect(hasRole).to.be.false;
|
||||
});
|
||||
|
||||
it('should remove an added controller', async () => {
|
||||
const { contract, owner, otherAccount, tokenId } = fixture;
|
||||
await contract.grantTokenRole(
|
||||
tokenId,
|
||||
Roles.Controller,
|
||||
otherAccount.address
|
||||
);
|
||||
await contract.revokeTokenRole(
|
||||
tokenId,
|
||||
Roles.Controller,
|
||||
otherAccount.address
|
||||
);
|
||||
|
||||
expect(
|
||||
await contract.hasTokenRole(
|
||||
tokenId,
|
||||
Roles.Controller,
|
||||
otherAccount.address
|
||||
)
|
||||
).to.be.false;
|
||||
});
|
||||
|
||||
it('should transfer the token owner role', async () => {
|
||||
const { contract, owner, otherAccount, tokenId } = fixture;
|
||||
await contract.transferFrom(owner.address, otherAccount.address, tokenId);
|
||||
|
||||
expect(await contract.ownerOf(tokenId)).to.equal(otherAccount.address);
|
||||
expect(
|
||||
await contract.hasTokenRole(tokenId, Roles.Owner, otherAccount.address)
|
||||
).to.be.true;
|
||||
expect(await contract.hasTokenRole(tokenId, Roles.Owner, owner.address)).to
|
||||
.be.false;
|
||||
});
|
||||
|
||||
it('should clean the token controller list after transfer', async () => {
|
||||
const { contract, owner, otherAccount, tokenId } = fixture;
|
||||
await contract.grantTokenRole(
|
||||
tokenId,
|
||||
Roles.Controller,
|
||||
otherAccount.address
|
||||
);
|
||||
await contract.transferFrom(owner.address, otherAccount.address, tokenId);
|
||||
|
||||
expect(await contract.getTokenRoleMembers(tokenId, 1)).to.eql([]);
|
||||
});
|
||||
|
||||
it('should not be able to add address role', async () => {
|
||||
const { contract, owner, otherAccount, tokenId } = fixture;
|
||||
await expect(
|
||||
contract
|
||||
.connect(otherAccount)
|
||||
.grantTokenRole(tokenId, Roles.Owner, otherAccount.address)
|
||||
).to.be.revertedWith('FleekAccessControl: must have token role');
|
||||
|
||||
await expect(
|
||||
contract
|
||||
.connect(otherAccount)
|
||||
.grantTokenRole(tokenId, Roles.Controller, otherAccount.address)
|
||||
).to.be.revertedWith('FleekAccessControl: must have token role');
|
||||
});
|
||||
|
||||
it('should not be able to remove address role', async () => {
|
||||
const { contract, owner, otherAccount, tokenId } = fixture;
|
||||
await expect(
|
||||
contract
|
||||
.connect(otherAccount)
|
||||
.revokeTokenRole(tokenId, Roles.Owner, otherAccount.address)
|
||||
).to.be.revertedWith('FleekAccessControl: must have token role');
|
||||
|
||||
await expect(
|
||||
contract
|
||||
.connect(otherAccount)
|
||||
.revokeTokenRole(tokenId, Roles.Controller, otherAccount.address)
|
||||
).to.be.revertedWith('FleekAccessControl: must have token role');
|
||||
});
|
||||
|
||||
it('should be able to add token role after owner role granted', async () => {
|
||||
const { contract, owner, otherAccount, tokenId } = fixture;
|
||||
await contract.grantTokenRole(tokenId, Roles.Owner, otherAccount.address);
|
||||
|
||||
expect(
|
||||
await contract
|
||||
.connect(otherAccount)
|
||||
.grantTokenRole(tokenId, Roles.Controller, otherAccount.address)
|
||||
).to.not.be.reverted;
|
||||
});
|
||||
|
||||
it('should emit event when token role is granted', async () => {
|
||||
const { contract, owner, otherAccount, tokenId } = fixture;
|
||||
await expect(
|
||||
contract.grantTokenRole(tokenId, Roles.Controller, otherAccount.address)
|
||||
)
|
||||
.to.emit(contract, 'TokenRoleGranted')
|
||||
.withArgs(tokenId, Roles.Controller, otherAccount.address, owner.address);
|
||||
});
|
||||
|
||||
it('should emit event when token role is revoked', async () => {
|
||||
const { contract, owner, otherAccount, tokenId } = fixture;
|
||||
await contract.grantTokenRole(
|
||||
tokenId,
|
||||
Roles.Controller,
|
||||
otherAccount.address
|
||||
);
|
||||
await expect(
|
||||
contract.revokeTokenRole(tokenId, Roles.Controller, otherAccount.address)
|
||||
)
|
||||
.to.emit(contract, 'TokenRoleRevoked')
|
||||
.withArgs(tokenId, Roles.Controller, otherAccount.address, owner.address);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
|
||||
import { expect } from 'chai';
|
||||
import { TestConstants, Fixtures, parseTokenURI } from './helpers';
|
||||
|
||||
describe('FleekERC721.TokenURI', () => {
|
||||
let fixture: Awaited<ReturnType<typeof Fixtures.withMint>>;
|
||||
|
||||
before(async () => {
|
||||
fixture = await loadFixture(Fixtures.withMint);
|
||||
});
|
||||
|
||||
it('should return the token URI', async () => {
|
||||
const { contract, tokenId } = fixture;
|
||||
const tokenURI = await contract.tokenURI(tokenId);
|
||||
|
||||
const parsedURI = parseTokenURI(tokenURI);
|
||||
|
||||
expect(parsedURI).to.eql({
|
||||
owner: fixture.owner.address.toLowerCase(),
|
||||
name: TestConstants.MintParams.name,
|
||||
description: TestConstants.MintParams.description,
|
||||
image: TestConstants.ResultantImage.Default,
|
||||
external_url: TestConstants.MintParams.externalUrl,
|
||||
attributes: [
|
||||
{
|
||||
trait_type: 'ENS',
|
||||
value: TestConstants.MintParams.ens,
|
||||
},
|
||||
{
|
||||
trait_type: 'Commit Hash',
|
||||
value: TestConstants.MintParams.commitHash,
|
||||
},
|
||||
{
|
||||
trait_type: 'Repository',
|
||||
value: TestConstants.MintParams.gitRepository,
|
||||
},
|
||||
{
|
||||
trait_type: 'Version',
|
||||
value: '0',
|
||||
},
|
||||
{
|
||||
trait_type: 'Color',
|
||||
value: `#${TestConstants.MintParams.color.toString(16)}`,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
import { loadFixture } from '@nomicfoundation/hardhat-network-helpers';
|
||||
import { expect } from 'chai';
|
||||
import { TestConstants, Fixtures } from './helpers';
|
||||
|
||||
const {
|
||||
Logos: { 1: Logo1 },
|
||||
Colors: { 1: Color1 },
|
||||
} = TestConstants;
|
||||
|
||||
describe('FleekERC721.UpdateProperties', () => {
|
||||
let fixture: Awaited<ReturnType<typeof Fixtures.withMint>>;
|
||||
|
||||
beforeEach(async () => {
|
||||
fixture = await loadFixture(Fixtures.withMint);
|
||||
});
|
||||
|
||||
it('should update token logo', async () => {
|
||||
const { contract, tokenId } = fixture;
|
||||
await contract.setTokenLogo(tokenId, Logo1);
|
||||
|
||||
const tokenURI = await contract.tokenURI(tokenId);
|
||||
|
||||
const tokenURIDecoded = Buffer.from(
|
||||
tokenURI.replace('data:application/json;base64,', ''),
|
||||
'base64'
|
||||
).toString('ascii');
|
||||
|
||||
const parsedURI = JSON.parse(tokenURIDecoded);
|
||||
expect(parsedURI).to.have.property(
|
||||
'image',
|
||||
TestConstants.ResultantImage['Logo1+Default']
|
||||
);
|
||||
});
|
||||
|
||||
it('should update token color', async () => {
|
||||
const { contract, tokenId } = fixture;
|
||||
await contract.setTokenColor(tokenId, Color1);
|
||||
|
||||
const tokenURI = await contract.tokenURI(tokenId);
|
||||
|
||||
const tokenURIDecoded = Buffer.from(
|
||||
tokenURI.replace('data:application/json;base64,', ''),
|
||||
'base64'
|
||||
).toString('ascii');
|
||||
|
||||
const parsedURI = JSON.parse(tokenURIDecoded);
|
||||
|
||||
expect(parsedURI.attributes).to.have.deep.contain({
|
||||
trait_type: 'Color',
|
||||
value: '#123456',
|
||||
});
|
||||
expect(parsedURI).to.have.property(
|
||||
'image',
|
||||
TestConstants.ResultantImage['Default+Color1']
|
||||
);
|
||||
});
|
||||
|
||||
it('should update the token logo and color', async () => {
|
||||
const { contract, tokenId } = fixture;
|
||||
await contract.setTokenLogoAndColor(tokenId, Logo1, Color1);
|
||||
|
||||
const tokenURI = await contract.tokenURI(tokenId);
|
||||
|
||||
const tokenURIDecoded = Buffer.from(
|
||||
tokenURI.replace('data:application/json;base64,', ''),
|
||||
'base64'
|
||||
).toString('ascii');
|
||||
|
||||
const parsedURI = JSON.parse(tokenURIDecoded);
|
||||
|
||||
expect(parsedURI.attributes).to.have.deep.contain({
|
||||
trait_type: 'Color',
|
||||
value: '#123456',
|
||||
});
|
||||
|
||||
expect(parsedURI).to.have.property(
|
||||
'image',
|
||||
TestConstants.ResultantImage['Logo1+Color1']
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -1,5 +1,8 @@
|
|||
import { expect } from 'chai';
|
||||
import { proxyStore, getProxyFilePath } from '../../scripts/utils/proxy-store';
|
||||
import {
|
||||
proxyStore,
|
||||
getProxyFilePath,
|
||||
} from '../../../scripts/utils/proxy-store';
|
||||
import fs from 'fs/promises';
|
||||
|
||||
describe('Proxy Store', () => {
|
||||
Loading…
Reference in New Issue