0

The issue is probably here: const { interface, bytecode } = require('../compile');.

interface in the test file is undefined.

inbox/contracts/Inbox.sol:

pragma solidity ^0.7.0;

contract Inbox {
    string public message;

    constructor(string memory initialMessage) {
        message = initialMessage;
    }

    function setMessage(string memory newMessage) public {
        message = newMessage;
    }
}

inbox/compile.js:

const path = require('path');
const fs = require('fs');
const solc = require('solc');

const inboxPath = path.resolve(__dirname, 'contracts', 'Inbox.sol');
const source = fs.readFileSync(inboxPath, 'utf8');

var input = {
    language: 'Solidity',
    sources: {
        'Inbox.sol' : {
            content: source
        }
    },
    settings: {
        outputSelection: {
            '*': {
                '*': [ "abi", "evm.bytecode" ]
            }
        }
    }
};

module.exports = solc.compile(JSON.stringify(input));

inbox/test/Inbox.test.js:

const assert = require('assert');
const ganache = require('ganache-cli');
const Web3 = require('web3');
const web3 = new Web3(ganache.provider());
const { interface, bytecode } = require('../compile');

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);
    })
})

when running npm run test it throws:

  Inbox
    1) "before each" hook for "deploys a contract"


  0 passing (366ms)
  1 failing

  1) "before each" hook for "deploys a contract":
     SyntaxError: Unexpected token u in JSON at position 0
      at JSON.parse (<anonymous>)
      at Context.<anonymous> (test\Inbox.test.js:15:46)
      at processTicksAndRejections (internal/process/task_queues.js:97:5)
2
  • Your problem is at JSON.parse(interface). Check what the value of the interface variable is. Since it is not a string which represents a JSON object, you cannot pass it to JSON.parse. Aug 7 '20 at 13:11
  • it's undefined but i don't get why
    – Donnoh
    Aug 7 '20 at 13:17
1

solved this way:

const compile = require('../compile');
const interface = JSON.parse(compile).contracts["Inbox.sol"].Inbox.abi;
const bytecode = JSON.parse(compile).contracts["Inbox.sol"].Inbox.evm.bytecode.object;
1

I renamed interface variable "abi" and removed the Parse from beforeEach in the test file because that's being done in the compiler.

Compile.JS file

// build path from compiler to solidity file
const path = require('path');
const fs = require('fs');
const solc = require('solc');

//for unix and windows
//take you from root dir to this inbox folder and both files
const inboxPath = path.resolve(__dirname, 'contracts', 'inbox.sol');

// read contents of file with encoding
const source = fs.readFileSync(inboxPath, 'utf-8');

var input = {
    language: 'Solidity',
    sources: {
        'inbox.sol' : {
            content: source
        }
    },
    settings: {
        outputSelection: {
            '*': {
                '*': [ '*' ]
            }
        }
    }
};


// parses solidity to English and strings 
var output = JSON.parse(solc.compile(JSON.stringify(input)));

var outputContracts = output.contracts['inbox.sol']['Inbox']

// exports ABI interface
module.exports.abi = outputContracts.abi;

// exports bytecode from smart contract
module.exports.bytecode = outputContracts.evm.bytecode.object;

inbox.test.js

const assert = require('assert');
const ganache = require('ganache-cli');
// constructor
const Web3 = require('web3');
// new instance and to connect it to ganache
const web3 = new Web3(ganache.provider());

const {abi, bytecode} = require('../compile');


// set global variables
let accounts;
let inbox;

beforeEach(async () =>  {
    // get list of all accounts
    accounts = await web3.eth.getAccounts()

    // use account to deploy contract
    inbox = await new web3.eth.Contract((abi))
        .deploy({ data: bytecode, arguments: ['Hi there!']})
        .send({ from: accounts[0], gas: '1000000'});

});

describe('Inbox', () => {
    it('deploys a contract', () => {
        console.log(inbox)
    });
});

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.