status-im / dappcon-workshop-dapp

DApp to be used in Dappcon
4 stars 3 forks source link

TypeError: Cannot destructure property `createAccount` of 'undefined' or 'null' #8

Closed dotnetspec closed 5 years ago

dotnetspec commented 5 years ago

Overview: Working through the instructions/5 Contract tests.md

Extra Detail: At console I get: embark test /home/linuxuser/Downloads/embark-3.1.7/dappcon-workshop-dapp/test/dtwitter_spec.js:6 const { createAccount, users, owners, userExists, editAccount, tweet } = DTwitter.methods; ^ TypeError: Cannot destructure property createAccount of 'undefined' or 'null'.

Steps to reproduce (use embark framework)

  1. As per 'extra detail' above

The code in dtwitter_spec.js is: // our DTwitter contract object to test const DTwitter = require('Embark/contracts/DTwitter');

// contract methods we'll be testing const { createAccount, users, owners, userExists, editAccount, tweet } = DTwitter.methods;

Screenshots: N/A

Logs: using: --loglevel trace --nodashboard constantly scrolls with blockchain data. Currently not sure how obtain the log data.

Context (Environment) OS: LinuxMint 18.3 Embark Version: 3.2.3 Node Version: 10.7.0 NPM Version: 6.1.0

Questions? Why do I get the TypeError: Cannot destructure property createAccount of 'undefined' or 'null' in the console error and what can I do to fix it? thx

0x-r4bbit commented 5 years ago

Hi @dotnetspec !

So the reason you're running into this error is because we're doing some magic behind the scenes that's not very well documented (as a matter of fact, I believe we should change those APIs to behave more predictable).

The line that causes this is

const { createAccount, users, owners, userExists, editAccount, tweet } = DTwitter.methods;

The reason is that, at the time that line is executed, DTwitter.methods is actually not defined yet. This is due to a hack where all imports from EmbarkJS/contracts/* synchronously return an empty object {}, which then later on, once tests start executing and Smart Contracts have been compiled and web3 instances have been created, gets updated with that instance reference.

So bottom line: there's this tiny window between

config({
  ...
})

And

contract('DTwitter', () => {
 ...
});

Where your DTwitter reference is just an empty object.

This can be "fixed" by either not destructing the methods in the first place and call them directly from the reference when they are needed (as seen here: https://github.com/status-im/embark-dtwitter-workshop/blob/solutions/test/dtwitter_spec.js#L33), or by destructing the methods within contract(), at which point the web3 instances should be created.

I'm sorry you ran into this and it's definitely not ideal. As I said, I personally believe this API potentially causes more confusion than good, so I hope we will change this in the near future.

BTW: The code line that i've linked is also from an updated repository, so you might want to use that instead. Have a look at the solutions branch there.

Let us know if you have any more questions!