I am currently learning Solidity and trying to build a simple contract. I am also trying to use the Mocha framework to test the smart contract before deploying. The test code is per below:
const assert = require("assert");
const ganache = require("ganache-cli");
const Web3 = require("web3");
const { interface, bytecode } = require("../compile");
const provider = ganache.provider();
const web3 = new Web3(provider);
let accounts;
let inbox;
beforeEach(async () => {
// Get a list of all accounts
accounts = await web3.eth.getAccounts();
// Use one of those accounts to deploy the contract
inbox = await new web3.eth.Contract(JSON.parse(interface))
.deploy({
data: bytecode,
arguments: ["Hi there!"]
})
.send({
from: accounts[0],
gas: "1000000"
});
});
describe("Inbox", () => {
it("deploys a contract", () => {
console.log(inbox);
});
});
The test fails and timeouts:
> mocha
Inbox
1) "before each" hook for "deploys a contract"
0 passing (2s)
1 failing
1) "before each" hook for "deploys a contract":
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.
I noticed that the test passes if I comment out the send() argument:
// .send({
// from: accounts[0],
// gas: "1000000"
// });
So the issue must be with using this method. Not sure if it is an async issue.
I solved this by downgrading web3 to 1.0.0-beta.37. Seems like version 1.0.0-beta.51 is buggy.
Related
I would like to get the response of an intercept cypress call while running an e2e test:
const registerUser = async (username, password)=>{
cy.visit('<user_registration_url');
cy.intercept('/registration').as('registration');
cy.get('input#username').type(username);
cy.get('input#password').type(password);
cy.get('button#submit').click()
// Expected response:
//{statusCode: 200, body: {userId: <string>}}
const result = await cy.wait('#registration');
const userId = result.response.body.userId;
return userId
it('should test something with a newly registered user', ()=>{
const userId = registerUser('foobar', 'password');
// ... keep testing using the userId which was generated on the backend.
});
No, this won't work.
Cypress is asynchronous, so the commands won't return any data that you can assign to variables. You can read more on then in Cypress docs.
You can get to the response like so:
cy
.wait('#registration')
.then(response => {
// some other code
});
or you can check e.g. a status code like so:
cy
.wait('#registration')
.its('response.statusCode')
.should('eq', 201);
You can see many examples on the page for cy.intercept command.
So indeed as #pavelsman mentioned there is no async/await syntax for cypress. In order to make utility functions one can return a chainable as in this example:
const registerUser = (username, password)=>{
cy.visit('<user_registration_url');
cy.intercept('/registration').as('registration');
cy.get('input#username').type(username);
cy.get('input#password').type(password);
cy.get('button#submit').click()
// Expected response:
//{statusCode: 200, body: {userId: <string>}}
return cy.wait('#registration');
it('should test something with a newly registered user', ()=>{
registerUser('foobar', 'password').then(result=>{
const userId = result.response.body.userId;
// ... keep testing using the userId which was generated on the backend.
});
});
I am not using redux-thunk. this keeps error-ing and I am not sure how to fix it. The examples I see online use redux-thunk which I am not using
my repo is here and the file I am trying to test is in tests\actions\...
My action that is being called in the test
import axios from "axios";
var CancelToken = axios.CancelToken;
let fetch_cancel;
export const FETCH_CATEGORIES = "fetch_categories";
export async function fetchCategories() {
fetch_cancel && fetch_cancel();
const request = await axios.get(
`https://d1i9eedhsgvpdh.cloudfront.net/production-plentific-static/api-cache/find-a-pro/api/v1/categories/all.json`,
{
cancelToken: new CancelToken(function executor(c) {
// An executor function receives a cancel function as a parameter
fetch_cancel = c;
})
}
);
return {
type: FETCH_CATEGORIES,
payload: request
};
}
The error message means that your actions must be plain objects. For example:
store.dispatch({
type: 'ADD_TODO',
text: 'Understand the middleware'
})
If you make an async request, you can't just return an object, because you need to wait for the request to finish. If you return too early, you return a Promise.
However, I cannot reproduce your error in your sandbox.
I am trying to cover redux-saga that gets data from RxDB with Jest tests.
export function* checkUnsavedData(action) {
const { tab } = action;
try {
const db = yield getDB().catch(e => {
throw new Error(e);
});
const currentUser = yield select(makeSelectCurrentUser());
const unsavedData = yield db[USER_COLLECTION].findOne(currentUser)
.exec()
.then(data => data && data.unsavedData)
.catch(e => {
throw new Error(e);
});
} catch (error) {
yield showError(error);
}
}
Everything is fine in live run. But testing the generator I get:
UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: Error: RxError:
RxDatabase.create(): Adapter not added. Use RxDB.plugin(require('pouchdb-adapter-[adaptername]');
Given parameters: {
adapter:"idb"}
If anyone has done this, please, tell me how to test such cases with RxDB in redux-saga with Jest.
It looks like you did non add the adapter to RxDB. Can you paste the code where you create the database? This would help more in finding the error.
When running tests, you should not use the idb-adapter. Use the in-memory-adapter, it's faster and also you can be sure that you start on a clean state on each testrun.
I am learning sinon currently. My codes:
const bluebird = require('bluebird');
const sinon = require('sinon');
const sinonTest = require('sinon-test')(sinon);
sinon.test = sinonTest;
describe('xxx', function _test() {
this.timeout(2000);
it('should', sinon.test(function() {
return new bluebird.Promise( (resolve, reject) => {
try {
console.log('123');
resolve();
} catch ( err ) {
reject(err);
};
})
.then( () => console.log('456') )
.delay(100)
.then( () => console.log('789') )
.then(function() {
})
}));
});
output:
xxx
123
456
Why the above code times out and stuck in delay? Thanks
UPDATE
const bluebird = require('bluebird');
const sinon = require('sinon');
const sinonTest = require('sinon-test')(sinon);
sinon.test = sinonTest;
describe('xxx', function _test() {
this.timeout(2000);
it('should', sinon.test(function() {
return bluebird
.delay(100)
.then( () => console.log('789') );
}));
});
Output:
Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves
UPDATE
Thanks #Louis. Setting useFakeTimers works fine.
But I am just confused. Why in my project, there are no problems with the existing tests where useFakeTimers set to true by default? If useFakeTimers set true, promise delay cannot be used in sinonTest()?
By the way, I had this problem when upgrading sinon from 1.17.6 to 2.4.1.
Thanks
By default the sandboxes that Sinon creates have their configuration set so that the sandbox configuration option useFakeTimers is true. (Search for defaultConfig in this documentation page.)
This means that while the sandbox is in effect, the clock appears to be stopped, and Bluebird's delay never resolves. You tell sinon-test to create sandboxes without fake timers by passing a 2nd parameter when you configure it. This 2nd parameter is actually a configuration object for Sinon sandboxes:
const sinonTest = require('sinon-test')(sinon,
{ useFakeTimers: false });
I have not tried it, but from eyeballing the code, it looks like you could use multiple configurations at the same time if you need some tests to use fake timers and some to not use fake timers:
const sinonTest = require('sinon-test');
const wrapper = sinonTest(sinon, { useFakeTimers: false });
const wrapperWithTimers = sinonTest(sinon);
You just need to use the right wrapper for the needs of the test.
You added the question:
But I am just confused. Why in my project, there are no problems with the existing tests where useFakeTimers set to true by default? If useFakeTimers set true, promise delay cannot be used in sinonTest()?
By default useFakeTimers is true, but that won't cause a problem unless you have code that depends on the clock moving forward to work properly. I have many test suites where I use sandboxes and where I did not take care to turn off the fake timers and they work fine. Fake timers do not generally prevent asynchronous functions from running. If you do fs.readFile while the sandbox is in effect, for instance, it should work just fine. It just affects functions that depend on the clock, like setTimeout, setInterval and Date.
Bluebird's delay method is affected because it calls setTimeout.
I have some functions that accept an RxJS subject (backed to a socket) that I want to test. I'd like to mock the subject in a very request reply fashion. Since I'm unsure of a clean Rx way to do this, I'm tempted to use an EventEmitter to form my fake socket.
Generally, I want to:
check that the message received on my "socket" matches expectations
respond to that message on the same subject: observer.next(resp)
I do need to be able to use data from the message to form the response as well.
The code being tested is
export function acquireKernelInfo(sock) {
// set up our JSON payload
const message = createMessage('kernel_info_request');
const obs = shell
.childOf(message)
.ofMessageType('kernel_info_reply')
.first()
.pluck('content', 'language_info')
.map(setLanguageInfo)
.publishReplay(1)
.refCount();
sock.next(message);
return obs;
}
You could manually create two subjects and "glue them together" as one Subject with Subject.create:
const sent = new Rx.Subject();
const received = new Rx.Subject();
const mockWebSocketSubject = Subject.create(sent, received)
const s1 = sent.subscribe(
(msg) => sentMsgs.push({ next: msg }),
(err) => sentMsgs.push({ error: err }),
() => sendMsgs.push({ complete: true })
);
const s2 = recieved.subscribe(
(msg) => sentMsgs.push({ next: msg }),
(err) => sentMsgs.push({ error: err }),
() => sendMsgs.push({ complete: true })
);
// to send a message
// (presumably whatever system you're injecting this into is doing the sending)
sent.next('weee');
// to mock a received message
received.next('blarg');
s1.unsubscribe();
s2.unsubscribe();
That said, it's really a matter of what you're testing, how it's structured, and what the API is.
Ideally you'd be able to run your whole test synchronously. If you can't for some Rx-related reason, you should look into the TestScheduler, which has facilities to run tests in virtualized time.