How to access the data stored in events and public variables while testing #2113
-
I tried to code the test myself meanwhile this happened const { assert, expect } = require('chai')
const { network, deployments, ethers, getNamedAccounts } = require('hardhat')
const {
developmentChains,
networkConfig,
} = require('../../helper-hardhat-config')
!developmentChains.includes(network.name)
? describe.skip
: describe('random Nft unit tests', function () {
let randomNft,
vrfCoordinatorV2Mock,
deployer,
subscriptionId,
chainId = network.config.chainId
beforeEach(async () => {
deployer = (await getNamedAccounts()).deployer
await deployments.fixture(['mocks', 'randomipfs', 'main'])
vrfCoordinatorV2Mock = await ethers.getContract('VRFCoordinatorV2Mock')
randomNft = await ethers.getContract('RandomIpfsNft')
})
describe('contructor test', function () {
it('initialises the raffle correctly', async () => {
const tx = await vrfCoordinatorV2Mock.createSubscription()
const txReceipt = await tx.wait(1)
subscriptionId = txReceipt.events[0].args.subId
// assert.equal(randomNft. , vrfCoordinatorV2Mock.address )
// assert.equal(randomNft.subscriptionId,subscriptionId)
// assert.equal(randomNft.gasLane,networkConfig[chainId].gasLane)
const tokenUri = await randomNft.getDogTokenUris(2)
let tokenUris2 = [
'ipfs://QmQwtEYTPccQ5WNVJFmFRq33oktMZk1i8Zi7sbTxhucNqT',
'ipfs://QmT6oHqpr6e2Xt25Nm2hFqQa6uAnYgpYELu3KLc2Kt6XKt',
'ipfs://QmZeVhmwN3yNR4xKfRBKn6qiNZQMbQi3JxEJgqCr8emvXc',
]
const mintFee = await randomNft.getMintFee()
assert.equal(mintFee, networkConfig[chainId].mintFee)
assert.equal(tokenUri, tokenUris2[2])
})
})
describe('requesting and minting nft', function () {
it('reverts if you dont pass the required amount while requesting nft', async () => {
await expect(randomNft.requestNft()).to.be.revertedWith(
'NeedMoreETHSent'
)
})
it('requests an nft once the correct amount was paid minting', async () => {
let requestId = await randomNft.requestNft({
value: networkConfig[chainId].mintFee,
})
await new Promise(async (resolve, reject) => {
randomNft.once('NftRequested', async (res) => {
try {
const requestIds = await randomNft.s_requestIdToSender
assert(requestIds[requestId], deployer)
assert(res.minter, deployer)
resolve()
} catch (error) {
reject(error)
}
})
})
})
})
})
Here is the error
here is the contract code // SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol";
import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol";
import "hardhat/console.sol";
error AlreadyInitialized();
error NeedMoreETHSent();
error RangeOutOfBounds();
contract RandomIpfsNft is ERC721URIStorage, VRFConsumerBaseV2, Ownable {
// Types
enum Breed {
PUG,
SHIBA_INU,
ST_BERNARD
}
// Chainlink VRF Variables
VRFCoordinatorV2Interface private immutable i_vrfCoordinator;
uint64 private immutable i_subscriptionId;
bytes32 private immutable i_gasLane;
uint32 private immutable i_callbackGasLimit;
uint16 private constant REQUEST_CONFIRMATIONS = 3;
uint32 private constant NUM_WORDS = 1;
// NFT Variables
uint256 private immutable i_mintFee;
uint256 private s_tokenCounter;
mapping(uint256 => Breed) private s_tokenIdToBreed;
uint256 internal constant MAX_CHANCE_VALUE = 100;
string[] internal s_dogTokenUris;
bool private s_initialized;
// VRF Helpers
mapping(uint256 => address) public s_requestIdToSender;
// Events
event NftRequested(uint256 indexed requestId, address requester);
event NftMinted(Breed breed, address minter);
constructor(
address vrfCoordinatorV2,
uint64 subscriptionId,
bytes32 gasLane, // keyHash
uint256 mintFee,
uint32 callbackGasLimit,
string[3] memory dogTokenUris
) VRFConsumerBaseV2(vrfCoordinatorV2) ERC721("Random IPFS NFT", "RIN") {
i_vrfCoordinator = VRFCoordinatorV2Interface(vrfCoordinatorV2);
i_gasLane = gasLane;
i_subscriptionId = subscriptionId;
i_mintFee = mintFee;
i_callbackGasLimit = callbackGasLimit;
_initializeContract(dogTokenUris);
}
function requestNft() public payable returns (uint256 requestId) {
if (msg.value < i_mintFee) {
revert NeedMoreETHSent();
}
requestId = i_vrfCoordinator.requestRandomWords(
i_gasLane,
i_subscriptionId,
REQUEST_CONFIRMATIONS,
i_callbackGasLimit,
NUM_WORDS
);
s_requestIdToSender[requestId] = msg.sender;
emit NftRequested(requestId, msg.sender);
}
function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords)
internal
override
{
address dogOwner = s_requestIdToSender[requestId];
uint256 newItemId = s_tokenCounter;
s_tokenCounter = s_tokenCounter + 1;
uint256 moddedRng = randomWords[0] % MAX_CHANCE_VALUE;
Breed dogBreed = getBreedFromModdedRng(moddedRng);
_safeMint(dogOwner, newItemId);
_setTokenURI(newItemId, s_dogTokenUris[uint256(dogBreed)]);
emit NftMinted(dogBreed, dogOwner);
}
function getChanceArray() public pure returns (uint256[3] memory) {
return [10, 30, MAX_CHANCE_VALUE];
}
function _initializeContract(string[3] memory dogTokenUris) private {
if (s_initialized) {
revert AlreadyInitialized();
}
s_dogTokenUris = dogTokenUris;
s_initialized = true;
}
function getBreedFromModdedRng(uint256 moddedRng)
public
pure
returns (Breed)
{
uint256 cumulativeSum = 0;
uint256[3] memory chanceArray = getChanceArray();
for (uint256 i = 0; i < chanceArray.length; i++) {
// if (moddedRng >= cumulativeSum && moddedRng < cumulativeSum + chanceArray[i]) {
if (moddedRng >= cumulativeSum && moddedRng < chanceArray[i]) {
return Breed(i);
}
// cumulativeSum = cumulativeSum + chanceArray[i];
cumulativeSum = chanceArray[i];
}
revert RangeOutOfBounds();
}
function withdraw() public onlyOwner {
uint256 amount = address(this).balance;
(bool success, ) = payable(msg.sender).call{value: amount}("");
require(success, "Transfer failed");
}
function getMintFee() public view returns (uint256) {
return i_mintFee;
}
function getDogTokenUris(uint256 index)
public
view
returns (string memory)
{
return s_dogTokenUris[index];
}
function getInitialized() public view returns (bool) {
return s_initialized;
}
function getTokenCounter() public view returns (uint256) {
return s_tokenCounter;
}
}
you can see that the 3rd test is failing , The ways i tried out were
Both were unsuccesfull could someone please say where im wrong |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 16 replies
-
@sadath-12 Here are my test for describe("requestNFT", () => {
it("should revert if amount is less than mintFee.", async () => {
await expect(randomIpfsNft.requestNFT()).to.be.revertedWith(
"RandomIpfsNFT__NotEnoughETHSent"
);
});
});
describe("fulfillRandomWords", () => {
it("should emit an event on nft mined.", async () => {
await new Promise(async (resolve, reject) => {
randomIpfsNft.once("NftMinted", async () => {
try {
const tokenUri = await randomIpfsNft.getDogTokenUris(0);
const tokenCounts = await randomIpfsNft.getTokenCounter();
assert.equal(tokenUri, tokenUriAtIndexZero);
assert.equal(tokenCounts, 1);
resolve();
} catch (error) {
console.log(error);
reject(error);
}
});
try {
const fee = await randomIpfsNft.getMintFee();
const requestNftResponse = await randomIpfsNft.requestNFT({
value: fee.toString(),
});
const requestNftReceipt = await requestNftResponse.wait(1);
await vrfCoordinatorV2Mock.fulfillRandomWords(
requestNftReceipt.events[1].args.requestId,
randomIpfsNft.address
);
} catch (e) {
console.log(e);
reject(e);
}
});
});
}); |
Beta Was this translation helpful? Give feedback.
-
can i access s_requestIdToSender variable since its public ?? while testing |
Beta Was this translation helpful? Give feedback.
@sadath-12 Here are my test for
requestNFT
andfulfillRandomWords
functions. It covers all lines you can check with coverage tool, but if you are more specifically wants to write test like this way then you can check the tests that we did on Lesson 9 for events. The way you are using for testing requestNFT, for that you need to wait and then check either the returned id from event is greater than 0 or not. Like this we did in lesson 9const requestId = await txReceipt.events[1].args.requestId;
,assert(requestId.toNumber() > 0);