Testing errors, unit and staging - javascript

I got two problems, 1) I am not being able to test the it("picks a winner , resest the lottery , and sends money" test. It wont run, it passes the time limit on the chain no matter how much I set it
const { inputToConfig } = require("#ethereum-waffle/compiler")
const { assert, expect } = require("chai")
const { network, getNamedAccounts, deployments, ethers } = require("hardhat")
const { developmentChains, networkConfig } = require("../../helper-hardhat-config")
!developmentChains.includes(network.name)
? describe.skip
: describe("Raffle Unit Tests", function () {
let raffle, vrfCoordinatorV2Mock, raffleEntranceFee, deployer, interval
const chainId = network.config.chainId
beforeEach(async function () {
deployer = (await getNamedAccounts()).deployer
await deployments.fixture(["all"])
raffle = await ethers.getContract("Raffle", deployer)
vrfCoordinatorV2Mock = await ethers.getContract("VRFCoordinatorV2Mock", deployer)
raffleEntranceFee = await raffle.getEntranceFee()
interval = await raffle.getInterval()
})
describe("constructor", function () {
it("initializes the raffle correctly", async function () {
// ideally we make our tests have 1 assert per "it"
const raffleState = await raffle.getRaffleState()
assert.equal(raffleState.toString(), "0")
assert.equal(interval.toString(), networkConfig[chainId]["interval"])
})
})
describe("enterRaffle", function () {
it("reverts when you dont pay enough", async function () {
await expect(raffle.enterRaffle()).to.be.revertedWith(
"Raffle__NotEnoughETHEntered"
)
})
it("records players when they enter", async function () {
await raffle.enterRaffle({ value: raffleEntranceFee })
const playerFromContract = await raffle.getPlayer(0)
assert.equal(playerFromContract, deployer)
})
it("emits event on enter", async function () {
await expect(raffle.enterRaffle({ value: raffleEntranceFee })).to.emit(
raffle,
"RaffleEnter"
)
})
it("doesnt allow entrance when raffle is calculating", async function () {
await raffle.enterRaffle({ value: raffleEntranceFee })
await network.provider.send("evm_increaseTime", [interval.toNumber() + 1])
await network.provider.send("evm_mine", [])
// we pretend to be chainlink keeper
await raffle.performUpkeep([])
await expect(raffle.enterRaffle({ value: raffleEntranceFee })).to.be.revertedWith(
"Raffle__NotOpen"
)
})
})
describe("checkUpkeep", function () {
it("returns falseif people havent send any ETH", async function () {
await network.provider.send("evm_increaseTime", [interval.toNumber() + 1])
await network.provider.send("evm_mine", [])
const { upkeepNeeded } = await raffle.callStatic.checkUpkeep([])
assert(!upkeepNeeded)
})
it("returns false if raffle isn't open", async () => {
await raffle.enterRaffle({ value: raffleEntranceFee })
await network.provider.send("evm_increaseTime", [interval.toNumber() + 1])
await network.provider.send("evm_mine", [])
await raffle.performUpkeep([]) // changes the state to calculating
const raffleState = await raffle.getRaffleState() // stores the new state
const { upkeepNeeded } = await raffle.callStatic.checkUpkeep("0x") // upkeepNeeded = (timePassed && isOpen && hasBalance && hasPlayers)
assert.equal(raffleState.toString() == "0", upkeepNeeded == false)
})
it("returns false if enough time hasn't passed", async () => {
await raffle.enterRaffle({ value: raffleEntranceFee })
await network.provider.send("evm_increaseTime", [interval.toNumber() - 5]) // use a higher number here if this test fails
await network.provider.request({ method: "evm_mine", params: [] })
const { upkeepNeeded } = await raffle.callStatic.checkUpkeep("0x") // upkeepNeeded = (timePassed && isOpen && hasBalance && hasPlayers)
assert(!upkeepNeeded)
})
it("returns true if enough time has passed, has players, eth, and is open", async () => {
await raffle.enterRaffle({ value: raffleEntranceFee })
await network.provider.send("evm_increaseTime", [interval.toNumber() + 1])
await network.provider.request({ method: "evm_mine", params: [] })
const { upkeepNeeded } = await raffle.callStatic.checkUpkeep("0x") // upkeepNeeded = (timePassed && isOpen && hasBalance && hasPlayers)
assert(!upkeepNeeded)
})
})
describe("performUpkeep", function () {
it("it casn only run if checkUpkeep is true", async function () {
await raffle.enterRaffle({ value: raffleEntranceFee })
await network.provider.send("evm_increaseTime", [interval.toNumber() + 1])
await network.provider.send("evm_mine", [])
const tx = await raffle.performUpkeep([])
assert(tx)
})
it("reverts when checkUpkeep is false", async function () {
await expect(raffle.performUpkeep("0x")).to.be.revertedWith(
"Raffle_UpkeepNotNeeded"
)
})
it("updates the raffle state and emits a requestId", async () => {
// Too many asserts in this test!
await raffle.enterRaffle({ value: raffleEntranceFee })
await network.provider.send("evm_increaseTime", [interval.toNumber() + 1])
await network.provider.send("evm_mine", [])
const txResponse = await raffle.performUpkeep("0x") // emits requestId
const txReceipt = await txResponse.wait(1) // waits 1 block
const raffleState = await raffle.getRaffleState() // updates state
const requestId = txReceipt.events[1].args.requestId
assert(requestId.toNumber() > 0)
assert(raffleState == 1) // 0 = open, 1 = calculating
})
})
beforeEach(async function () {
await raffle.enterRaffle({ value: raffleEntranceFee })
await network.provider.send("evm_increaseTime", [interval.toNumber() + 1])
await network.provider.send("evm_mine", [])
})
it("can only be called after performUpkeep", async function () {
await expect(
vrfCoordinatorV2Mock.fulfillRandomWords(0, raffle.address)
).to.be.revertedWith("nonexistent request")
await expect(
vrfCoordinatorV2Mock.fulfillRandomWords(1, raffle.address)
).to.be.revertedWith("nonexistent request")
})
// WAY TOO BIG
it("picks a winner , resest the lottery , and sends money", async () => {
const additonalEnternace = 3
const startingAccountIndex = 2 // deployer = 0
const accounts = await ethers.getSigners()
// connecting 3 extra people to the rafffle , not including the deployer which makes it 4
for (
let i = startingAccountIndex;
i < startingAccountIndex + additonalEnternace;
i++
) {
const accountConnectedRaffle = raffle.connect(accounts[i])
await accountConnectedRaffle.enterRaffle({ value: raffleEntranceFee })
}
const startingTimeStamp = await raffle.getLatestTimeStamp()
// performUpKeep {mock being chainLink keepers}
// fullfillRandomWords {mock being the chainLink VRF}
// IF WE ON TESTNET : we have to wait for the fullfillRandomWords
await new Promise(async (resolve, reject) => {
// Listening for the winnerPicked Event
raffle.once("WinnerPicked", async () => {
console.log("Found the event")
try {
const recentWinner = await raffle.getRecentWinner()
console.log(`the Last winner was : ${recentWinner}`)
console.log(
"------------------------All Accounts------------------------"
)
console.log(accounts[0].address)
console.log(accounts[1].address)
console.log(accounts[2].address)
console.log(accounts[3].address)
const raffleState = await raffle.getRaffleState()
const endingTimeStamp = await raffle.getLatestTimeStamp()
const numPlayers = await raffle.getNumberOfPlayer()
const winnerEndingBalance = await accounts[2].getBalance()
// asserts
assert.equal(numPlayers.toString(), "0")
assert.equal(raffleState.toString(), "0")
assert(endingTimeStamp > startingTimeStamp)
// doing the math to make sure the winner gets the right amount
assert.equal(
winnerEndingBalance.toString(),
winnerStartingBalace
.add(
raffleEntranceFee
.mul(additonalEnternace)
.add(raffleEntranceFee)
)
.toString()
)
} catch (error) {
reject(error)
}
resolve()
})
// setting up a listener
// below , we will fire the event , and the listner will pick it up , and resolve
const tx = await raffle.performUpkeep([])
const txReceipt = await tx.wait(1)
const winnerStartingBalace = await accounts[2].getBalance()
await vrfCoordinatorV2Mock.fulfillRandomWords(
txReceipt.events[1].args.requestId,
raffle.address
)
})
})
})
The second problem is that when I test my tests on GOERLI network, it shows an Error that reads: 1) Raffle Unit Tests
"before each" hook for "works with live Chainlink Keepers and Chainlink VRF, we get a random winner":
Error: No Contract deployed with name VRFCoordinatorV2Mock
at Object.getContract (node_modules/#nomiclabs/hardhat-ethers/src/internal/helpers.ts:447:11)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at Context. (test/staging/Raffle.staging.test.js:15:38)
const { inputToConfig } = require("#ethereum-waffle/compiler")
const { assert, expect } = require("chai")
const { network, getNamedAccounts, deployments, ethers } = require("hardhat")
const { developmentChains, networkConfig } = require("../../helper-hardhat-config")
developmentChains.includes(network.name)
? describe.skip
: describe("Raffle Unit Tests", function () {
let raffle, raffleEntranceFee, deployer
beforeEach(async function () {
deployer = (await getNamedAccounts()).deployer
await deployments.fixture(["all"])
raffle = await ethers.getContract("Raffle", deployer)
vrfCoordinatorV2Mock = await ethers.getContract("VRFCoordinatorV2Mock", deployer)
raffleEntranceFee = await raffle.getEntranceFee()
})
describe("fulfillRandomWords", function () {
it("works with live Chainlink Keepers and Chainlink VRF, we get a random winner", async function () {
// enter the raffle
console.log("Setting up test...")
await deployments.fixture(["mocks"])
const startingTimeStamp = await raffle.getLastTimeStamp()
const accounts = await ethers.getSigners()
console.log("Setting up Listener...")
await new Promise(async (resolve, reject) => {
// setup listener before we enter the raffle
// Just in case the blockchain moves REALLY fast
raffle.once("WinnerPicked", async () => {
console.log("WinnerPicked event fired!")
try {
const recentWinner = await raffle.getRecentWinner()
const raffleState = await raffle.getRaffleState()
const winnerEndingBalance = await accounts[0].getBalance()
const endingTimeStamp = await raffle.getLastTimeStamp()
await expect(raffle.getPlayer(0)).to.be.reverted
assert.equal(recentWinner.toString(), accounts[0].address)
assert.equal(raffleState, 0)
assert.equal(
winnerEndingBalance.toString(),
winnerStartingBalance.add(raffleEntranceFee).toString()
)
assert(endingTimeStamp > startingTimeStamp)
resolve()
} catch (error) {
console.log(error)
reject(error)
}
})
// Then entering the raffle
console.log("Entering Raffle...")
const tx = await raffle.enterRaffle({ value: raffleEntranceFee })
await tx.wait(1)
console.log("Ok, time to wait...")
const winnerStartingBalance = await accounts[0].getBalance()
// and this code WONT complete until our listener has finished listening!
})
})
})
})
Can anyone help me out with these, here's the link to my repo: https://github.com/anooj1/hardhat-raffle

Related

skip detox tests on api failure

I was trying to skip the tests based on API failure for detox tests in which I am using jest as test runner
const itif = (condition) => condition ? it : it.skip;
const itif = (condition) => condition ? it : it.skip;
describe('Example', () => {
let condition1;
let condition2;
beforeEach(async () => {
condition1 = await getResponseverifyArticles() ? true :false
condition2 = await getNumberOfFollowers() ? true :false
await device.launchApp();
});
console.log(condtion1) // --> giving undefined
//so first test always skips
itif(condition1)('should verify articles1' ,async() => {
await expect(element(by.text('Articles:'))).toBeVisible()
await getResponseverifyArticles()
await expect(element(by.text('Articles:'))).toBeVisible()
});
//same as aboue
itif(condition2)('should see Articles screen2', async () => {
await expect(element(by.text('Articles:'))).toBeVisible()
await getNumberOfFollowers()
});
});
async function getArticles() {
let articles;
await axios
.get('https://raw.githubusercontent.com/adhithiravi/React-Hooks-Examples/master/testAPI.json')
.then(response => {
if (response.status === 200 || response.status === 201) {
articles = response.data.articles
}
})
.catch(error => {
console.error("error Message :",error.response.data)
});
return articles
}
const getResponseverifyArticles = async()=>{
const res = await getArticles();
for (let item of res) {
await expect(element(by.text(item.title))).toBeVisible()
}
}
async function getNumberOfFollowers() {
let nOfFollowers
await axios
.get('https://api.github.com/users/janbodnar')
.then(response => {
if (response.status === 200 || response.status === 201) {
nOfFollowers = response.data.followers;
}
})
.catch(error => {
console.warn("Requested URL :",error.response)
});
return nOfFollowers
}
getNumberOfFollowers()
In this way, I was trying to skip the tests...but not able to access the condions from beforeAll block.
Is there any way to access those conditions dynamically.

how to call to api once a hour with react

i would like to know how can i get the api on first time reload the page and then call to api again once a hour to update my UI because that api update once a hour by default
here is my code
const [news, setNews] = useState([])
useEffect(() => {
setInterval(() => {
(async () => {
tryƏ {
const res = await fetch(`https://newsapi.org/v2/top-headlines?country=""""&apiKey=""""""""`)
const data = await res.json()
setNews(data)
console.log("yes")
} catch (error) {
console.log(error)
}
})()
}, 36000000);
}, [])
with that code i can't get result on first time page reload, only after a hour...
Move your API call to separate function. Call it on page load and on timeout:
let callApi = async () => {
try {
const res = await fetch(url)
const data = await res.json()
setNews(data)
} catch (error) {
console.log(error)
}
};
useEffect(() => {
callApi();
setInterval(callApi, 1000 * 60 * 60)
});
You can create another function and call from interval and outside both.
const [news, setNews] = useState([]);
useEffect(() => {
const fetchData = async () => {
try {
const res = await fetch(
`https://newsapi.org/v2/top-headlines?country=""""&apiKey=""""""""`
);
const data = await res.json();
setNews(data);
console.log("yes");
} catch (error) {
console.log(error);
}
};
fetchData();
const interval = setInterval(() => {
fetchData();
}, 36000000);
return () => clearInterval(interval);
}, []);
You can try this code:
const [news, setNews] = useState([]);
const [timer, setTimer] = useState(null);
const APIResponse = async (url) => {
try {
const response = await fetch(url);
const data = await response.json();
setNews(data);
} catch (e) {
console.error(e);
}
};
useEffect(() => {
APIResponse("https://newsapi.org/v2/top-headlines?country=""""&apiKey=""""""""");
setTimer(
setInterval(async () => {
APIResponse("https://newsapi.org/v2/top-headlines?country=""""&apiKey=""""""""");
}, 5000)
);
return () => clearInterval(timer);
}, []);

Asynchronous function recognizes function is done when really it still has more to do

The page.on is reconized by the async for loop at the bottom as finished and ready to run the function again, but its not actually done. It still needs to run everything up to page.close. How do I let the async function know that it is done after page.close, not page.on? Let me know if you need anymore info, thanks.
const puppeteer = require('puppeteer');
const fs = require('fs');
const req = require('request');
const got = require('got');
const NodeID3 = require('node-id3');
const readline = require('readline');
const selectors = require('./selectors');
const getDownloadUrl = async (url, browser) => {
const page = await browser.newPage();
await page.goto(url);
page.setRequestInterception(true);
await page._client.send('Page.setDownloadBehavior', {behavior: 'allow', downloadPath: './Songs'})
const baseUrl = 'https://cf-hls-media.sndcdn.com/media/';
await page.on('request', async (request) => {
if(request.url().includes(baseUrl)){
const downloadUrl = fixUrl(request.url());
const info = await getSongInfo(page);
downloadSong(downloadUrl, info.title);
await tagSong(info);
await request.abort();
await page.close();
} else {
request.continue();
}
});
};
const fixUrl = (url) => {
...
};
const downloadSong = (url, title) => {
...
};
const getSongInfo = async (page) => {
...
};
const tagSong = async (info) => {
...
};
(() => {
const readInterface = readline.createInterface({
input: fs.createReadStream('../Song Urls.csv'),
output: process.stdout,
console: false,
terminal: false,
});
let urls = [];
readInterface.on('line', function(line) {
urls.push(line);
}).on('close', async () => {
const browser = await puppeteer.launch({headless: false});
for (let i = 0; i < urls.length; i++) {
const url = urls[i];
await getDownloadUrl(url, browser);
}
});
})();
/*
Issue: The loop recognizes that the getDownloadUrl function is done even though it's
not and continues anyways.
*/
await only works with promises, and page.on looks to be a callback-based event listener, not something that returns a promise. If you want to be able to await it, you will need to create a promise around it.
await new Promise((resolve) => {
page.on('request', async (request) => {
if(request.url().includes(baseUrl)){
const downloadUrl = fixUrl(request.url());
const info = await getSongInfo(page);
downloadSong(downloadUrl, info.title);
await tagSong(info);
await request.abort();
await page.close();
resolve();
} else {
request.continue();
}
});
})

Chain of async calls where the last call compares something from the first

I need to complete a number of fetch requests where each relies on the successful completion of the last. For the final request, I need to compare a value from the first request.
Here's what I've got, and it appears to work, but I'm not sure if I have this 100% correct.
const getData = async ( id ) => {
return await fetch(`https://jsonplaceholder.typicode.com/todos/${id}`)
.then( json => json.json() )
.then( res => res )
}
const res_1 = await getData( 1 ).then( res => res )
const res_2 = await getData( res_1.id + 1 ).then( res => res )
const res_3 = await getData( res_2.id + 1 ).then( res => res )
const res_4 = await getData( res_3.id + 1 ).then( res => res )
console.log(`RES_1: \n${JSON.stringify(res_1)}`)
console.log(`RES_2: \n${JSON.stringify(res_2)}`)
console.log(`RES_3: \n${JSON.stringify(res_3)}`)
console.log(`RES_4: \n${JSON.stringify(res_4)}`)
if ( res_1.id !== res_4.id ) {
console.log("Id's don't match")
} else {
console.log("Id's match")
}
You may ignore the logging, it's simply to visualize what's happening.
You don't need additional .then( res => res ) as it just returning the same object back again. Also, as you are using async/await you can remove .then(...) and just await on the result of the promise. Also, we can use await inside an async function only, so you can put all your logic inside an async function fn like:
const getData = async(id) => {
const res = await fetch(`https://jsonplaceholder.typicode.com/todos/${id}`)
return res.json();
}
async function fn() {
const res_1 = await getData(1)
const res_2 = await getData(res_1.id + 1)
const res_3 = await getData(res_2.id + 1)
const res_4 = await getData(res_3.id + 1)
console.log('res_1.id: ', res_1.id);
console.log('res_4.id: ', res_4.id);
if (res_1.id !== res_4.id) {
console.log("Id's don't match")
} else {
console.log("Id's match")
}
}
fn();
Or, you can also use immediately-invoked async function expressions for this purpose like:
const getData = async(id) => {
const res = await fetch(`https://jsonplaceholder.typicode.com/todos/${id}`)
return res.json();
}
(async function() {
const res_1 = await getData(1)
const res_2 = await getData(res_1.id + 1)
const res_3 = await getData(res_2.id + 1)
const res_4 = await getData(res_3.id + 1)
console.log('res_1.id: ', res_1.id);
console.log('res_4.id: ', res_4.id);
if (res_1.id !== res_4.id) {
console.log("Id's don't match")
} else {
console.log("Id's match")
}
}());

Problems with async code in Jest tests

I am having problem with getting the code into the beforeAll function finish and wait for the promise that resolves the storyLinks. The console log at the end of the snippet returns undefined but I need it to return the hrefs of the stories in my storybook. I cannot wrap this into an async function because of the testing pipeline being clogged on fail.
const puppeteer = require('puppeteer');
const { toMatchImageSnapshot } = require('jest-image-snapshot');
expect.extend({ toMatchImageSnapshot });
const timeout = 5000;
describe('visual tests', () => {
let page, browser, storyLinks;
const selector = `a[href*="selectedStory="]`;
beforeAll(async() => {
browser = await puppeteer.connect({browserWSEndpoint});
page = await browser.newPage();
await page.goto('http://localhost:8080');
await page.evaluate(() => {
const components = Array.from(document.querySelectorAll('div[data-name]'));
for(let i = 1; i < components.length; i++) {
components[i].addEventListener('click',() => {});
components[i].click();
}
});
storyLinks = await page.evaluate((selector) => {
const stories = Array.from(document.querySelectorAll(selector));
const links = stories.map(story => {
let href = story.href;
let name = story.text.replace(/[^A-Z0-9]/ig, '-').replace(/-{2,}/,'-');
let component = href.match(/selectedKind=(.*?)\&/).pop();
return {href: href, name: component + '-' + name};
});
return links;
}, selector);
}, timeout);
afterAll(async () => {
await page.close();
await browser.disconnect();
})
console.log(storyLinks);
}, timeout);
There's a few things I notice might be causing your issues. You need to add async to your describe block. Also, "describe" groups together multiple tests so you're missing an it or test block. Jest docs also note adding the expect.assertions(NUM_OF_ASSERTIONS); I'd do something like:
const puppeteer = require('puppeteer');
const { toMatchImageSnapshot } = require('jest-image-snapshot');
expect.extend({ toMatchImageSnapshot });
const timeout = 5000;
async function myStoryLinkTest(page) {
const selector = `a[href*="selectedStory="]`;
await page.goto('http://localhost:8080');
await page.evaluate(() => {
Array.from(document.querySelectorAll('div[data-name]'), item => {
item.addEventListener('click', () => {});
item.click();
});
});
const storyLinks = await page.evaluate(selector => {
return Array.from(document.querySelectorAll(selector), story => {
let href = story.href;
let name = story.text.replace(/[^A-Z0-9]/gi, '-').replace(/-{2,}/, '-');
let component = href.match(/selectedKind=(.*?)\&/).pop();
return { href: href, name: component + '-' + name };
});
});
return storyLinks;
}
describe('visual tests', async () => {
let page, browser;
beforeAll(async () => {
browser = await puppeteer.connect({ browserWSEndpoint });
page = await browser.newPage();
});
afterAll(async () => {
await page.close();
await browser.disconnect();
});
it('should do something with storyLinks', async () => {
expect.assertions(1);
const storyLinkResult = await myStoryLinkTest(page);
expect(storyLinkResult).toEqual('Some value you expect');
}, timeout);
});

Categories