Truffle Chai Assertion Error with Truffle Unit Cases - solidity

Problem: facing an issue with the below Truffle test case while trying to Implement the ERC20 token in my contract.
contract("Token Test", async(accounts) => {
const[deployerAccount, recipient, anotherAccount] = accounts;
it("All tokens should be in deployer's account", async() => {
let instance = await Token.deployed();
let totalSupply = await instance.totalSupply();
// let balance = await instance.balanceOf(accounts[0]);
// assert.equal(balance.valueOf(), totalSupply.valueOf(), "The Balance Was not same");
expect(instance.balanceOf(deployerAccount)).to.eventually.be.a.bignumber.equal(totalSupply);
});
it("Is possible to send tokens between accounts", async() => {
const sendToken = 1;
let instance = await Token.deployed();
let totalSupply = await instance.totalSupply();
expect(instance.balanceOf(deployerAccount)).to.eventually.be.a.bignumber.equal(totalSupply);
expect(instance.transfer(recipient, sendToken)).to.eventually.be.fulfilled;
expect(instance.balanceOf(deployerAccount)).to.eventually.be.a.bignumber.equal(totalSupply.sub(new BN(sendToken)));
expect(instance.balanceOf(recipient)).to.eventually.be.a.bignumber.equal(new BN(sendToken));
});
it("Should not be able to send more token than available with owner", async() => {
let instance = await Token.deployed();
let balanceOfDeployer = await instance.balanceOf(deployerAccount);
console.log(balanceOfDeployer+ " : " + await instance.balanceOf(deployerAccount));
// expect(instance.transfer(recipient, new BN(balanceOfDeployer+3))).to.eventually.be.rejected;
expect(instance.balanceOf(deployerAccount)).to.eventually.be.a.bignumber.equal(balanceOfDeployer);
});
});
Description: When I am trying to execute test cases 2 and 3 at the same time it is failing with the below error:
"before all" hook: prepare suite for "Should not be able to send more token than available with owner":
Uncaught AssertionError: expected '1000000000' to equal '999999999'
+ expected - actual
-1000000000
+999999999
at /project_dir/node_modules/chai-as-promised/lib/chai-as-promised.js:302:22
at processTicksAndRejections (internal/process/task_queues.js:95:5)
UnhandledRejections detected
Promise {
<rejected> AssertionError: expected '1000000000' to equal '999999999'
at /project_dir/node_modules/chai-as-promised/lib/chai-as-promised.js:302:22
at processTicksAndRejections (internal/process/task_queues.js:95:5) {
showDiff: true,
actual: '1000000000',
expected: '999999999',
operator: 'strictEqual',
uncaught: true
}
However when I try to execute both test cases independently (commenting test case 2 keeping 3, and vice-versa). They work fine and are completed without any error.
Need help understanding what am I missing here and how to fix it.
Things I have tried:
Initially, I thought that this is might be happening due to state change in the variable in test case 2. So I moved test case 3 to a new contract(). But I was still facing the same issue. However, this should not be happening as contract() provides a clean room environment before executing every contract test.
P.S.: I am initiating the value of totalSupply to 1000000000 in the constructor of Contract.

Added await before every expect() where I was trying to communicate with the contract. This helped in resolving the issue.

Related

How to write the assert format for msg.value > 0.01 ether in truffle test

In card.sol contract, I have a function 'add' which allows a user to create a poker card with any number. To use this 'add' function, it requires at least 0.01 eth.
I have written the following truffle test scripts to ensure that at least 0.01 eth is used to create a card in the smart contract above.
var Web3 = require('web3');
const card = artifacts.require("card");
contract('card Test', async accounts => {
it("ensure > 0.01 eth is needed to create a card", async () => {
const instance = await Card.deployed();
const cardInstance = instance;
await cardInstance.add(5, 10, {from: accounts[0], value: Web3.utils.toWei('0.02')});
assert.isAbove(____________, 0.01, "> 0.01 eth is needed to create the card");
});
What is the correct code for ____________?
For the usual solidity test scripts, it will be 'msg.value'. What is the equivalence of 'msg.value' for the _________ above?
you have to send amount that less than 0.01 Assuming that created the instance correctly
try {
// this will throw error and you will catch it catch statement
await cardInstance.add(5, 10, {from: accounts[0], value:Web3.utils.toWei('0.00001')})
// if this line executed, your test will fail.
assert(false);
} catch (e) {
// to test this part of your code executed
console.log("errror is caught")
// this will confirm that we get an error object
assert(e);
}
If you send less than minimum requirement, if we are successfully catching the error in catch statement, test case will pass. If there was an error with require statement assert(false) would run and test case would fail

How can i use soft assertion in Cypress

I have configured soft assert from npm (npm i soft-assert) and now my package.josn has "soft-assert": "^0.2.3"
i want to use function of Soft assert
softAssert(actual, expected, msg, ignoreKeys)
But don't know, what is the exact steps to use it
Example:
When i use soft assertion function in my code, getting following error.
If i use like this
cy.softAssert(10, 12, "expected actual mismatch and will execute next line") : not supported
or if i use different way like
softAssert(10, 12, "expected actual mismatch and will execute next line") : SoftAssert not defined
Can any one tell me how to use this 'softAssert' function in cypress code with some small example?
Now the problem I am facing
it('asserts and logs and fails', () => {
Cypress.softAssert(10, 12, "expected actual mismatch...");
cy.log("text")
Cypress.softAssertAll();
})
I need my code after soft assertion as cy.log("text") to be executed in the same 'it' block but the current test failing the whole 'it' block, without executing 'cy.log("text")' statement.
The soft assertion concept is pretty cool, and you can add it with minimal implementation to Cypress
const jsonAssertion = require("soft-assert")
it('asserts several times and only fails at the end', () => {
jsonAssertion.softAssert(10, 12, "expected actual mismatch");
// some more assertions, not causing a failure
jsonAssertion.softAssertAll(); // Now fail the test if above fails
})
To me, it would be nicer to see each soft assertion failure in the log, so it's possible to add custom commands to wrap the soft-assert functions
const jsonAssertion = require("soft-assert")
Cypress.Commands.add('softAssert', (actual, expected, message) => {
jsonAssertion.softAssert(actual, expected, message)
if (jsonAssertion.jsonDiffArray.length) {
jsonAssertion.jsonDiffArray.forEach(diff => {
const log = Cypress.log({
name: 'Soft assertion error',
displayName: 'softAssert',
message: diff.error.message
})
})
}
});
Cypress.Commands.add('softAssertAll', () => jsonAssertion.softAssertAll())
//-- all above can go into /cypress/support/index.js
//-- to save adding it to every test (runs once each test session)
it('asserts and logs but does not fail', () => {
cy.softAssert(10, 12, "expected actual mismatch...");
cy.log('text'); // this will run
})
it('asserts and logs and fails', () => {
cy.softAssert(10, 12, "expected actual mismatch...");
cy.log('text'); // this will run
cy.softAssertAll();
})

React Native Expo Task Manager

Eventually, I would like to be able to run background tasks in my React Native app (Axios fetch to get some fresh data at least once a day). I am struggling to make this work:
https://docs.expo.io/versions/latest/sdk/task-manager/
import * as BackgroundFetch from 'expo-background-fetch';
import * as TaskManager from 'expo-task-manager';
const FETCH_TASKNAME = 'test_task'
const INTERVAL = 60
function test() {
console.log('function is running')
}
export async function registerFetchTask() {
TaskManager.defineTask(FETCH_TASKNAME, test());
const status = await BackgroundFetch.getStatusAsync();
switch (status) {
case BackgroundFetch.Status.Restricted:
case BackgroundFetch.Status.Denied:
console.log("Background execution is disabled");
return;
default: {
console.debug("Background execution allowed");
let tasks = await TaskManager.getRegisteredTasksAsync();
if (tasks.find(f => f.taskName === FETCH_TASKNAME) == null) {
console.log("Registering task");
await BackgroundFetch.registerTaskAsync(FETCH_TASKNAME);
tasks = await TaskManager.getRegisteredTasksAsync();
console.debug("Registered tasks", tasks);
} else {
console.log(`Task ${FETCH_TASKNAME} already registered, skipping`);
}
console.log("Setting interval to", INTERVAL);
await BackgroundFetch.setMinimumIntervalAsync(INTERVAL);
}
}
}
and calling this in App.js
import { registerFetchTask } from './helpers/backgroundFetch'
registerFetchTask();
I am getting a console logs up to this point:
function is running
Background execution allowed
Registering task
But I am unfortunately also getting following errors:
TaskManager.defineTask must be called during the initialization phase!
I read also in the documentation and as per example code, I am running in App.js directly and not in the component class.
And I am getting the following warning:
[Unhandled promise rejection: Error: Task 'test_task' is not defined. You must define a task using TaskManager.defineTask before registering.]
Which I don't understand since it is defined at the very top and before registering.
It is only unfortunate there is no proper working example anywhere to be found. An example would save countless hours for people struggling with this. Is there maybe an easier way of making background tasks running in react native apps?
Thanks so much for your kind help.
I can spot a couple of problems:
When you define the task, pass in a reference to the function rather than calling it:
TaskManager.defineTask(FETCH_TASKNAME, test); // no parentheses
registerFetchTask() is async which means it returns a promise when called in App.js. That probably doesn't count as the "initialization phase" of the app so try removing async
I don't know whether these changes will solve the problem but they should help.
change the line TaskManager.defineTask(FETCH_TASKNAME, test()); to
TaskManager.defineTask(FETCH_TASKNAME, test);
instead of passing the return value of the function pass the function reference.

promise chaining vs promise.all

i have a task to enter the notification date using protractor
where i need to clear contents before entering so i have came up with this code
this.Then(/^I should enter "Notification Date"$/, () => {
const d = new Date();
return orderCheckOutPage.pageElements.recipientNotificationDateMonth.clear().then(() => {
return orderCheckOutPage.pageElements.recipientNotificationDateMonth.sendKeys(d.getMonth() + 1).then(() => {
return orderCheckOutPage.pageElements.recipientNotificationDateDay.clear().then(() => {
return orderCheckOutPage.pageElements.recipientNotificationDateDay.sendKeys(d.getDate()).then(() => {
return orderCheckOutPage.pageElements.recipientNotificationDateYear.clear().then(() => {
return orderCheckOutPage.pageElements.recipientNotificationDateYear.sendKeys(d.getFullYear())
})
})
})
})
})
});
my friend told me the above code be can refactored as
const promises = [];
promises.push(orderCheckOutPage.pageElements.recipientNotificationDateMonth.clear());
promises.push(orderCheckOutPage.pageElements.recipientNotificationDateMonth.sendKeys(d.getMonth() + 1));
promises.push(orderCheckOutPage.pageElements.recipientNotificationDateDay.clear());
promises.push(orderCheckOutPage.pageElements.recipientNotificationDateDay.sendKeys(d.getDate()));
promises.push(orderCheckOutPage.pageElements.recipientNotificationDateYear.clear());
promises.push(orderCheckOutPage.pageElements.recipientNotificationDateYear.sendKeys(d.getFullYear()));
return promise.all(promises);
I heard promise.all will start resolving promises one by one
first it would go to first statement and try to resolve if it [here in the above case is clear month] if is asynch the it would jump to second one and try to execute the statement [sending keys to month]
here both the tasks of clearing and entering will be run parallely
and tasks are executed based on the time promises get resolved
if it is that case will there be chances of sendkeys being exeuted before clearing
correct me if i am wrong...!!!!!
Protractor has its own promise manage mechanism called control flow, To understand control flow simply, you can think it is a queue.
When nodejs execute your Protractor script line by line, if the expression in the line return a promise, control flow will add the promise into the queue.
After all lines execute done, you will get a promise queue, at this time point your testing had not finish yet, because control flow will make your testing to wait all promise in the queue be executed. Now control flow will pop a promise from the queue and execute and wait it complete, then next promise.
So with such mechanism, your script can be executed as the order as you write
down in file. Actually what control flow did is more complex than I said here.
You no need to use nested then chain in your case, your code like the callback pyramid, not represent the advantage of promise (promise is to resolve callback pyramid). Your code can be simple as below:
const d = new Date();
//input month
orderCheckOutPage.pageElements.recipientNotificationDateMonth.clear();
orderCheckOutPage.pageElements.recipientNotificationDateMonth.sendKeys(d.getMonth() + 1);
//input day
orderCheckOutPage.pageElements.recipientNotificationDateDay.clear();
orderCheckOutPage.pageElements.recipientNotificationDateDay.sendKeys(d.getDate());
//input year
orderCheckOutPage.pageElements.recipientNotificationDateYear.clear();
orderCheckOutPage.pageElements.recipientNotificationDateYear.sendKeys(d.getFullYear());
For your case, no need to use promise.all(), because all interaction of your code not to get some value from page. I will give an example to help you learn in which case it's better to use promise.all():
Assume i have a page and it display a price and a amount. I need to calculate the fee by price * amount.
Use nested then chain:
var fee = ele_price.getText().then(function(price){
return ele_amount.getText().then(function(amount){
return price * amount;
});
});
fee.then(function(fee){
console.log(fee);
});
Use promise.all():
var fee = promise.all([
ele_price.getText(),
ele_amount.getText()
])
.then(function(datas){
var price = datas[0];
var amount = datas[1];
return price * amount;
});
fee.then(function(fee){
console.log(fee);
});
So use promise.all(), one then() is enough. This makes your code more readable than nested then chain.
Hope you now understand why no need to use promise.all() in your case.

Chai-As-Promised is eating assertion errors

I'm using chai-as-promised + mocha for writing some selenium-webdriver tests. Since webdriver extensively uses promises, I imagined it would be better if I used chai-as-promised for those type of tests.
The problem is that when the tests fail, the error is not being caught properly by mocha, and it just fails without outputting anything.
Sample code:
it 'tests log', (next) ->
log = #client.findElement(By.css("..."))
Q.all([
expect(log.getText()).to.eventually.equal("My Text")
expect(log.findElement(By.css(".image")).getAttribute('src'))
.to.eventually.equal("/test.png")
]).should.notify(next)
According to documented behaviour, chai-as-promised should pass the errors along to mocha when the expectation fails. Right?
As a variation,
I've also tried these, but to no avail:
#2
# same, no error on failure
it 'tests log', (next) ->
log = #client.findElement(By.css("..."))
Q.all([
expect(log.getText()).to.eventually.equal("My Text")
expect(log.findElement(By.css(".image")).getAttribute('src'))
.to.eventually.equal("/test.png")
]).should.notify(next)
#3
# same, no error shown on failure
it 'tests log', (next) ->
log = #client.findElement(By.css("..."))
expect(log.getText()).to.eventually.equal("My Text")
.then ->
expect(log.findElement(By.css(".image")).getAttribute('src'))
.to.eventually.equal("/test.png").should.notify(next)
#4
## DOES NOT EVEN PASS
it 'tests log', (next) ->
log = #client.findElement(By.css("..."))
Q.all([
expect(log.getText()).to.eventually.equal("My Text")
expect(log.findElement(By.css(".image")).getAttribute('src'))
.to.eventually.equal("/test.png")
])
.then ->
next()
.fail (err) ->
console.log(err)
.done()
I think you're having two different issues:
First, you need to return a promise at the end of your tests (e.g. Q.all([...]); in your first test should be return Q.all([...]).
Second, I found that chai-as-promised doesn't seem to work unless used with mocha-as-promised.
Here's an example of mocha-as-promised with two assertions that will cause the test to fail.
/* jshint node:true */
/* global describe:false */
/* global it:false */
'use strict';
var Q = require('q');
require('mocha-as-promised')();
var chai = require('chai');
var chaiAsPromised = require('chai-as-promised');
chai.use(chaiAsPromised);
var expect = chai.expect;
describe('the test suite', function() {
it('uses promises properly', function() {
var defer = Q.defer();
setTimeout(function() {
defer.resolve(2);
}, 1000);
return Q.all([
expect(0).equals(0),
// the next line will fail
expect(1).equals(0),
expect(defer.promise).to.eventually.equal(2),
// the next line will fail
expect(defer.promise).to.eventually.equal(0)
]);
});
});