<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: DApps Dev Club</title>
    <description>The latest articles on DEV Community by DApps Dev Club (@dappsdev).</description>
    <link>https://dev.to/dappsdev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F460333%2F2b17f119-4979-4ebd-a9d1-d2828ed49e8d.jpg</url>
      <title>DEV Community: DApps Dev Club</title>
      <link>https://dev.to/dappsdev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dappsdev"/>
    <language>en</language>
    <item>
      <title>How to configure Truffle to connect to RSK</title>
      <dc:creator>DApps Dev Club</dc:creator>
      <pubDate>Thu, 25 Feb 2021 03:23:24 +0000</pubDate>
      <link>https://dev.to/dappsdev/how-to-configure-truffle-to-connect-to-rsk-33an</link>
      <guid>https://dev.to/dappsdev/how-to-configure-truffle-to-connect-to-rsk-33an</guid>
      <description>&lt;p&gt;Understanding Truffle's default configuration values&lt;br&gt;
(based on Ethereum),&lt;br&gt;
in particular surrounding polling intervals;&lt;br&gt;
and using 2 relatively new config options&lt;br&gt;
allows one to config Truffle to better connect to an RSK node.&lt;/p&gt;


&lt;h3&gt;
  
  
  Public Nodes
&lt;/h3&gt;

&lt;p&gt;When connecting to &lt;strong&gt;public nodes&lt;/strong&gt;,&lt;br&gt;
it is crucial to understand that you are interacting with the nodes &lt;strong&gt;indirectly&lt;/strong&gt;.&lt;br&gt;
Each RPC request goes through a series of hops through other infrastructure,&lt;br&gt;
such as authentication gateways, load balancers, rate limiters, et cetera.&lt;br&gt;
Each of these other layers contains its own logic that may be more restrictive than the node itself.&lt;/p&gt;

&lt;p&gt;You may opt to work around this by running your own node on &lt;code&gt;localhost&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  Ethereum Defaults
&lt;/h3&gt;

&lt;p&gt;Truffle's &lt;strong&gt;default configuration&lt;/strong&gt; is optimised for the Ethereum network.&lt;br&gt;
However, some of these values are incompatible with the RSK network,&lt;br&gt;
and need to be &lt;strong&gt;overridden&lt;/strong&gt; accordingly.&lt;br&gt;
Remember that while RSK is compatible with Ethereum&lt;br&gt;
both at the RPC level and at the VM level;&lt;br&gt;
its internal implementation can be quite different.&lt;/p&gt;

&lt;p&gt;The main difference lies in the relationship&lt;br&gt;
between &lt;em&gt;block interval&lt;/em&gt; and &lt;em&gt;polling interval&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;block interval&lt;/strong&gt; is the duration of time between&lt;br&gt;
a block being added to the blockchain and the next one being added.&lt;br&gt;
Note that all transactions must be in a block&lt;br&gt;
in order to be added to the blockchain&lt;br&gt;
(AKA "has been mined").&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RSK's block interval is currently approximately 30 seconds, whereas&lt;/li&gt;
&lt;li&gt;Ethereum's block interval is currently approximately 15 seconds.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Client applications, such as decentralised applications,&lt;br&gt;
or in this case Truffle (a developer tool),&lt;br&gt;
need to periodically check if blocks, and therefore transactions,&lt;br&gt;
that have been submitted have since been added to the blockchain.&lt;br&gt;
The &lt;strong&gt;polling interval&lt;/strong&gt; is the duration of time between&lt;br&gt;
one such check and the next.&lt;/p&gt;

&lt;p&gt;It thus makes sense to optimise the efficiency of the client application&lt;br&gt;
by configuring a polling interval that is &lt;em&gt;commensurate&lt;/em&gt;&lt;br&gt;
with the anticipated block interval.&lt;br&gt;
Drawing upon the concept of&lt;br&gt;
&lt;a href="https://en.wikipedia.org/wiki/Nyquist%E2%80%93Shannon_sampling_theorem#Critical_frequency"&gt;critical frequency&lt;/a&gt;&lt;br&gt;
(in Nyquist–Shannon sampling theorem),&lt;br&gt;
it makes sense to pick a 15 second polling interval&lt;br&gt;
when anticipating a 30 second block interval from RSK.&lt;br&gt;
Manual testing appears to indicate that this works well.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that Truffle's default is a 4 second polling&lt;br&gt;
for an anticipated 15 second block interval on Ethereum.&lt;br&gt;
This is still "allowed", as critical frequency&lt;br&gt;
as that specifies the &lt;em&gt;upper bound&lt;/em&gt; of the sampling&lt;br&gt;
to be &lt;em&gt;half&lt;/em&gt;.&lt;br&gt;
Configuration values should be picked carefully&lt;br&gt;
by weighing the pros and cons of performance against resource intensity.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Note that Truffle's implementation has 2 separate polling intervals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;one for &lt;code&gt;provider.pollingInterval&lt;/code&gt;,
which is for "regular" usage, and&lt;/li&gt;
&lt;li&gt;another for &lt;code&gt;deploymentPollingInterval&lt;/code&gt;,
which is used exclusively for deployments (&lt;code&gt;truffle migrate&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These configuration options were originally not implemented,&lt;br&gt;
and were set to hard coded defaults.&lt;br&gt;
These were added specifically top be able to support networks&lt;br&gt;
with a different block interval!&lt;br&gt;
See:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://twitter.com/DAppsDev/status/1324929409158012929"&gt;DApps Dev Club's tweet about adding &lt;code&gt;provider.pollingInterval&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://twitter.com/DAppsDev/status/1328695467081756673"&gt;DApps Dev Club's tweet about adding &lt;code&gt;deploymentPollingInterval&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Configuring Truffle
&lt;/h3&gt;

&lt;p&gt;With all the above in mind,&lt;br&gt;
let's now see how to implement this in a Truffle project.&lt;/p&gt;

&lt;p&gt;In your &lt;code&gt;truffle-config.js&lt;/code&gt; file:&lt;/p&gt;

&lt;p&gt;(1) Set a variable &lt;code&gt;testnetSeedPhrase&lt;/code&gt; to&lt;br&gt;
  contain a valid BIP-39 mnemonic phrase&lt;/p&gt;

&lt;p&gt;(2) Set a variable &lt;code&gt;gasPriceTestnet&lt;/code&gt; to&lt;br&gt;
  contain the gas price you wish to use denominated in Wei.&lt;/p&gt;

&lt;p&gt;(3) In the exported &lt;code&gt;config&lt;/code&gt; object,&lt;br&gt;
  set the value of &lt;code&gt;config.networks.testnet&lt;/code&gt; to be the following.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;    &lt;span class="nx"&gt;testnet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;HDWalletProvider&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;mnemonic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;phrase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;testnetSeedPhrase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="na"&gt;providerOrUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://public-node.testnet.rsk.co/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// Higher polling interval to check for blocks less frequently&lt;/span&gt;
        &lt;span class="na"&gt;pollingInterval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="nx"&gt;e3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="c1"&gt;// Ref: http://developers.rsk.co/rsk/architecture/account-based/#chainid&lt;/span&gt;
      &lt;span class="nx"&gt;network_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;31&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;gasPrice&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;gasPriceTestnet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;networkCheckTimeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;e6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;timeoutBlocks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="c1"&gt;// Higher polling interval to check for blocks less frequently&lt;/span&gt;
      &lt;span class="c1"&gt;// during deployment&lt;/span&gt;
      &lt;span class="nx"&gt;deploymentPollingInterval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="nx"&gt;e3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(4) Now you can run &lt;code&gt;truffle&lt;/code&gt; sub-commands with this network selected,&lt;br&gt;
  for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;truffle migrate &lt;span class="nt"&gt;--network&lt;/span&gt; testnet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;This article was originally published on &lt;a href="https://dappsdev.org/blog/2021-02-24-how-to-configure-truffle-to-connect-to-rsk/"&gt;dappsdev.org&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>truffle</category>
      <category>rsk</category>
    </item>
    <item>
      <title>How to init a DApp with web3.js using MetaMask 8</title>
      <dc:creator>DApps Dev Club</dc:creator>
      <pubDate>Thu, 08 Oct 2020 02:59:19 +0000</pubDate>
      <link>https://dev.to/dappsdev/how-to-init-a-dapp-with-web3-js-using-metamask-8-4363</link>
      <guid>https://dev.to/dappsdev/how-to-init-a-dapp-with-web3-js-using-metamask-8-4363</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;in a manner that is compliant with both&lt;br&gt;
EIP1102 and EIP1193, and moves away from&lt;br&gt;
deprecated Web3 provider APIs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;MetaMask 8 &lt;a href="https://medium.com/metamask/announcing-metamask-version-8-9126dc2df98"&gt;was released&lt;/a&gt; a few months ago - and it even included a &lt;a href="https://github.com/MetaMask/metamask-extension/pull/8592"&gt;tiny contribution&lt;/a&gt; of mine!&lt;/p&gt;

&lt;p&gt;One of the less talked about "features" of this release is not about something that was added, but rather something that was removed. A key part of what MetaMask does is to inject a "Web3 provider" into the &lt;code&gt;window&lt;/code&gt; global of the browser. This is not to be confused with a "Web3 instance", which is what &lt;code&gt;web3.js&lt;/code&gt; or other similar libraries would give you. (Somewhat confusingly the "Web3 provider" that was injected was accessible through the variable &lt;code&gt;window.web3&lt;/code&gt;.)&lt;/p&gt;

&lt;p&gt;In any case, this is no more, and this way to do so has been deprecated by MetaMask.&lt;br&gt;
Instead, the "Web3 provider" is now injected under a different variable name, &lt;code&gt;window.ethereum&lt;/code&gt;.&lt;br&gt;
This can be confusing for a different reason than the one stated above, if you happen to be using the "Web3 Provider" to interact with a non-Ethereum network, such as &lt;a href="https://developers.rsk.co/"&gt;RSK&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  The differences
&lt;/h3&gt;

&lt;p&gt;This is not a simple naming change, however: This new "Web3 provider" has a different API. There are many changes, but the &lt;strong&gt;short version&lt;/strong&gt; of it is that it is now compliant with these Ethereum Improvement Proposals (EIPs):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://eips.ethereum.org/EIPS/eip-1102"&gt;EIP-1102&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://eips.ethereum.org/EIPS/eip-1193"&gt;EIP-1193&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The longer version of this is that it is now compulsory:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;To ask for users' permission to read their address

&lt;ul&gt;
&lt;li&gt;This implies that it is asynchronous, where it was previously synchronous&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;To not longer rely on automatic page refreshes when a user switches between accounts

&lt;ul&gt;
&lt;li&gt;This implies that we need to handle this explicitly in our code&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Apart from these two changes, almost everything else works the same as it did before.&lt;/p&gt;
&lt;h3&gt;
  
  
  Show me the code!
&lt;/h3&gt;

&lt;p&gt;The following code is a sample DApp whose front end is built using webpack and vanilla Javascript - look ma, no frameworks!&lt;/p&gt;

&lt;p&gt;It also assumes that &lt;code&gt;../build/contracts/MySmartContract.json&lt;/code&gt; contains a compiled smart contract conforming to the Truffle format. Note that this is not necessary, or even relevant, to this example. It is merely included to to mark &lt;strong&gt;where&lt;/strong&gt; within the code one would insert the code dealing with smart contracts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Web3&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;web3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;mySmartContractArtefact&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../build/contracts/MySmartContract.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DOMContentLoaded&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onDocumentLoad&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;onDocumentLoad&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;DApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;init&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DApp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;web3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;contracts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="na"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;

  &lt;span class="na"&gt;init&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;DApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;initWeb3&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="na"&gt;initWeb3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ethereum&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// New web3 provider&lt;/span&gt;
      &lt;span class="c1"&gt;// As per EIP1102 and EIP1193&lt;/span&gt;
      &lt;span class="c1"&gt;// Ref: https://eips.ethereum.org/EIPS/eip-1102&lt;/span&gt;
      &lt;span class="c1"&gt;// Ref: https://eips.ethereum.org/EIPS/eip-1193&lt;/span&gt;
      &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Request account access if needed&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;accounts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ethereum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;eth_requestAccounts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="c1"&gt;// Accounts now exposed, use them&lt;/span&gt;
        &lt;span class="nx"&gt;DApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updateAccounts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="c1"&gt;// Opt out of refresh page on network change&lt;/span&gt;
        &lt;span class="c1"&gt;// Ref: https://docs.metamask.io/guide/ethereum-provider.html#properties&lt;/span&gt;
        &lt;span class="nx"&gt;ethereum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;autoRefreshOnNetworkChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// When user changes to another account,&lt;/span&gt;
        &lt;span class="c1"&gt;// trigger necessary updates within DApp&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ethereum&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;accountsChanged&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;DApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updateAccounts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// User denied account access&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User denied web3 access&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;DApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;web3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Web3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ethereum&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;web3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Deprecated web3 provider&lt;/span&gt;
      &lt;span class="nx"&gt;DApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;web3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Web3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;currentProvider&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="c1"&gt;// no need to ask for permission&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;// No web3 provider&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No web3 provider detected&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;DApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;initContract&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="na"&gt;updateAccounts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;firstUpdate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;DApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;accounts&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;DApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="nx"&gt;DApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;accounts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;accounts&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;DApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAccounts&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;updateAccounts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;firstUpdate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;DApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="na"&gt;initContract&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;networkId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;DApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;net&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getId&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;networkId&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;networkId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;deployedNetwork&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;mySmartContractArtefact&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;networks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;networkId&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;deployedNetwork&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No contract deployed on the network that you are connected. Please switch networks.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;deployedNetwork&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;deployedNetwork&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;DApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contracts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MySmartContract&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;DApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Contract&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;mySmartContractArtefact&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;abi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;deployedNetwork&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Election&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;DApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contracts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MySmartContract&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;DApp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;render&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// show spinner before loading data from smart contract&lt;/span&gt;
    &lt;span class="c1"&gt;// TODO&lt;/span&gt;

    &lt;span class="c1"&gt;// set or refresh any event listeners&lt;/span&gt;

    &lt;span class="c1"&gt;// update DOM to render account address where relevant&lt;/span&gt;
    &lt;span class="c1"&gt;// TODO using DApp.accounts[0]&lt;/span&gt;

    &lt;span class="c1"&gt;// retrieve data from smart contract and render it&lt;/span&gt;
    &lt;span class="c1"&gt;// TODO using DApp.contracts.MySmartContract&lt;/span&gt;

    &lt;span class="c1"&gt;// Hide spinner after loading and rendering data from smart contract&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As alluded to above, the real work happens in &lt;code&gt;DApp.initWeb3()&lt;/code&gt; and &lt;code&gt;DApp.updateAccounts()&lt;/code&gt;; whereas &lt;code&gt;DApp.initContract()&lt;/code&gt; and &lt;code&gt;DApp.render()&lt;/code&gt; are included to illustrate positions within the code that common smart contract related code would occur.&lt;/p&gt;

&lt;p&gt;Happy DApp developing!&lt;/p&gt;

</description>
      <category>web3</category>
      <category>metamask</category>
    </item>
    <item>
      <title>RSK Workshop: Smart Contract Testing using OpenZeppelin CLI</title>
      <dc:creator>DApps Dev Club</dc:creator>
      <pubDate>Sun, 30 Aug 2020 06:31:08 +0000</pubDate>
      <link>https://dev.to/dappsdev/rsk-workshop-smart-contract-testing-using-openzeppelin-cli-30h7</link>
      <guid>https://dev.to/dappsdev/rsk-workshop-smart-contract-testing-using-openzeppelin-cli-30h7</guid>
      <description>&lt;h2&gt;
  
  
  Video
&lt;/h2&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Bw6bHgiUEiI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-requisites
&lt;/h2&gt;

&lt;p&gt;Prior to commencing this tutorial,&lt;br&gt;
please ensure that you have installed the following&lt;br&gt;
RSK workshop pre-requisites on your system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/bguiz/workshop-rsk-prereqs/blob/master/walkthru.md#posix-compliant-shell"&gt;POSIX compliant shell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/bguiz/workshop-rsk-prereqs/blob/master/walkthru.md#nodejs"&gt;NodeJs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/bguiz/workshop-rsk-prereqs/blob/master/walkthru.md#openzeppelin-cli"&gt;OpenZeppelin CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/bguiz/workshop-rsk-prereqs/blob/master/walkthru.md#java"&gt;Java&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/bguiz/workshop-rsk-prereqs/blob/master/walkthru.md#curl"&gt;curl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/bguiz/workshop-rsk-prereqs/blob/master/walkthru.md#code-editor"&gt;Code editor&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/bguiz/workshop-rsk-prereqs/blob/master/walkthru.md#rskj"&gt;RSKj&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Project setup
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;git&lt;/code&gt; to make a copy of this repo,&lt;br&gt;
and use &lt;code&gt;npm&lt;/code&gt; to install dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone git@github.com:bguiz/workshop-rsk-smart-contract-testing-ozcli.git
&lt;span class="nb"&gt;cd &lt;/span&gt;workshop-rsk-smart-contract-testing-ozcli
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then open up this directory in your code editor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Explore the files
&lt;/h2&gt;

&lt;p&gt;If you happen to have &lt;code&gt;tree&lt;/code&gt; installed,&lt;br&gt;
you can use that to view the directory structure using the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;tree &lt;span class="nt"&gt;-aI&lt;/span&gt; &lt;span class="s1"&gt;'node_modules|*.md|package*.json|.git*'&lt;/span&gt;
&lt;span class="nb"&gt;.&lt;/span&gt;
├── contracts
│   └── Cars.sol
├── networks.js
├── .openzeppelin
│   └── project.json
├── scripts
│   ├── clean.sh
│   └── setup.sh
└── &lt;span class="nb"&gt;test&lt;/span&gt;
    └── Cars.spec.js

4 directories, 6 files

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;(Otherwise use your choice of GUI to explore this folder.)&lt;/p&gt;

&lt;p&gt;Observe that we have the following files:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.openzeppelin/project.json&lt;/code&gt;:
OZ CLI has already been pre-configured to work with the structure
for this project.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;networks.js&lt;/code&gt;:
OZ CLI has already been pre-configured to connect to your choice of
RSK Regtest, RSK Testnet, or RSK Mainnet.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;scripts/clean.sh&lt;/code&gt; and &lt;code&gt;scripts/setup.sh&lt;/code&gt;:
These are custom scripts which generate keys and configuration that
will be used by OZ CLI when connecting to RSK networks.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;contracts/Cars.sol&lt;/code&gt;:
This is the smart contract.
The solidity file is the implementation, and has been completed for you.

&lt;ul&gt;
&lt;li&gt;If you are familiar will Truffle, you may notice that there is no
corresponding deployment script (also known as migration contract)&lt;/li&gt;
&lt;li&gt;OZ ClI takes a different approach, instead persisting migration
status within JSON files within the &lt;code&gt;.openzeppelin&lt;/code&gt; directory.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;test/Cars.spec.js&lt;/code&gt;
This is the specification, and is only partially complete.
This workshop is focused on completing the specification.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ensure that you have a copy of RSKj running in Regtest locally,&lt;br&gt;
and then run the set up script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;bash ./scripts/setup.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will set up the RSK specific files for this project&lt;br&gt;
which are specific to you at this time.&lt;br&gt;
Observe the output in your terminal for more details.&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;Look at &lt;code&gt;contracts/Cars.sol&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We have a smart contract implementation&lt;br&gt;
that involves manipulating several car objects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight solidity"&gt;&lt;code&gt;&lt;span class="k"&gt;pragma&lt;/span&gt; &lt;span class="n"&gt;solidity&lt;/span&gt; &lt;span class="o"&gt;^&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;contract&lt;/span&gt; &lt;span class="n"&gt;Cars&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;enum&lt;/span&gt; &lt;span class="n"&gt;CarStatus&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;driving&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parked&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;event&lt;/span&gt; &lt;span class="n"&gt;CarHonk&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="k"&gt;indexed&lt;/span&gt; &lt;span class="n"&gt;fromCar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="k"&gt;indexed&lt;/span&gt; &lt;span class="n"&gt;atCar&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;Car&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;bytes3&lt;/span&gt; &lt;span class="n"&gt;colour&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;uint8&lt;/span&gt; &lt;span class="n"&gt;doors&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;uint16&lt;/span&gt; &lt;span class="n"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;uint16&lt;/span&gt; &lt;span class="n"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;CarStatus&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;address&lt;/span&gt; &lt;span class="n"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;numCars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;mapping&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;cars&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

    &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;addCar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="kt"&gt;bytes3&lt;/span&gt; &lt;span class="n"&gt;colour&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;uint8&lt;/span&gt; &lt;span class="n"&gt;doors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;uint16&lt;/span&gt; &lt;span class="n"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="kt"&gt;uint16&lt;/span&gt; &lt;span class="n"&gt;lon&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;payable&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt; &lt;span class="kc"&gt;ether&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="s"&gt;"You need at least 0.1 ETH to get a car"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;carId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="n"&gt;numCars&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;Car&lt;/span&gt; &lt;span class="k"&gt;memory&lt;/span&gt; &lt;span class="n"&gt;newCar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Car&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;colour&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;doors&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;CarStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parked&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;cars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newCar&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;modifier&lt;/span&gt; &lt;span class="n"&gt;onlyCarOwner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;owner&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"you need to own this car"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;modifier&lt;/span&gt; &lt;span class="n"&gt;onlyCarStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CarStatus&lt;/span&gt; &lt;span class="n"&gt;expectedStatus&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;expectedStatus&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"car is not in the required status"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;driveCar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt;
        &lt;span class="n"&gt;onlyCarOwner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;onlyCarStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CarStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;cars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CarStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driving&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;parkCar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint16&lt;/span&gt; &lt;span class="n"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint16&lt;/span&gt; &lt;span class="n"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt;
        &lt;span class="n"&gt;onlyCarOwner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;onlyCarStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CarStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;driving&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;cars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;CarStatus&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parked&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;cars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;lat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;cars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;lon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;honkCar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;otherCarId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt;
        &lt;span class="n"&gt;onlyCarOwner&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cars&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;otherCarId&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;owner&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kt"&gt;address&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mh"&gt;0x00&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
          &lt;span class="s"&gt;"other car must exist"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kt"&gt;uint256&lt;/span&gt; &lt;span class="n"&gt;timeOfDay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;86400&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nb"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeOfDay&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;21600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s"&gt;"cannot honk between midnight and 6am"&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;emit&lt;/span&gt; &lt;span class="n"&gt;CarHonk&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;carId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;otherCarId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;internal&lt;/span&gt; &lt;span class="k"&gt;view&lt;/span&gt; &lt;span class="k"&gt;returns&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;uint256&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// current block timestamp as seconds since unix epoch
&lt;/span&gt;        &lt;span class="c1"&gt;// ref: https://solidity.readthedocs.io/en/v0.5.7/units-and-global-variables.html#block-and-transaction-properties
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We are not really concerned about how to write this implementation&lt;br&gt;
for this workshop, but we do need to know what the implementation does&lt;br&gt;
in order to be able to write tests for it.&lt;/p&gt;
&lt;h2&gt;
  
  
  Specification, incomplete
&lt;/h2&gt;

&lt;p&gt;Look at &lt;code&gt;test/Cars.spec.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here, we have an incomplete specification.&lt;br&gt;
We obtain the &lt;code&gt;Cars&lt;/code&gt; smart contract&lt;br&gt;
defined in our implementation earlier,&lt;br&gt;
using &lt;code&gt;contract.fromArtifact()&lt;/code&gt;.&lt;br&gt;
This is OZ CLI's analogue of using NodeJs &lt;code&gt;require()&lt;/code&gt;&lt;br&gt;
to obtain the implementation when testing Javascript using Mocha.&lt;br&gt;
Those of you familiar with Truffle might recognise this&lt;br&gt;
as being the equivalent of &lt;code&gt;artifacts.require()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Unlike Truffle, where we make use of &lt;code&gt;contract&lt;/code&gt; blocks to group tests,&lt;br&gt;
in OZ CLI tests, we use &lt;code&gt;describe&lt;/code&gt; blocks to group our tests;&lt;br&gt;
exactly as how we would do so when using Mocha.&lt;br&gt;
We can do this because OZ CLI's test environment -&lt;br&gt;
&lt;code&gt;@openzeppelin/test-environment&lt;/code&gt; -&lt;br&gt;
enables us to access the list of &lt;code&gt;accounts&lt;/code&gt; up-front.&lt;br&gt;
Thus there is no need to obtain the &lt;code&gt;accounts&lt;/code&gt; via&lt;br&gt;
the &lt;code&gt;describe&lt;/code&gt; block's callback function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@openzeppelin/test-environment&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;assert&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;assert&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;web3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;web3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;BN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Cars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;contract&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromArtifact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cars&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cars - initial state&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;before&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Cars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;owner&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Initialised with zero cars&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialNumCars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;numCars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// TODO perform assertions&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cars - state transitions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;before&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Cars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;owner&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Adds a new car&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// preview the return value without modifying the state&lt;/span&gt;
    &lt;span class="c1"&gt;// ... (redacted for brevity) ...&lt;/span&gt;

    &lt;span class="c1"&gt;// TODO perform the assertions&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cars - events&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="nx"&gt;before&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;instance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Cars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;owner&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="c1"&gt;// set up contract with relevant initial state&lt;/span&gt;
    &lt;span class="c1"&gt;// ... (redacted for brevity) ...&lt;/span&gt;

    &lt;span class="c1"&gt;// just a sanity check, we do not really need to do assertions&lt;/span&gt;
    &lt;span class="c1"&gt;// within the set up, as this should be for "known working state"&lt;/span&gt;
    &lt;span class="c1"&gt;// only&lt;/span&gt;
    &lt;span class="c1"&gt;// ... (redacted for brevity) ...&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Honks a car at another car&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// perform the state transition&lt;/span&gt;
    &lt;span class="c1"&gt;// ... (redacted for brevity) ...&lt;/span&gt;

    &lt;span class="c1"&gt;// TODO perform assertions&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Honking a car that you do not own is not allowed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// perform the state transition&lt;/span&gt;
    &lt;span class="c1"&gt;// ... (redacted for brevity) ...&lt;/span&gt;

    &lt;span class="c1"&gt;// TODO perform assertions&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="p"&gt;});&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Note that we have several instances of &lt;code&gt;// ... (redacted for brevity) ...&lt;/code&gt;&lt;br&gt;
as comments. In these cases, there is test code set up&lt;br&gt;
and already available in the demo repo,&lt;br&gt;
but it has been omitted here to keep this document short.&lt;br&gt;
The intent here is to show the overall structure.&lt;br&gt;
These parts indicate code that performs the steps within the test specifications.&lt;br&gt;
When writing specifications for your smart contracts,&lt;br&gt;
you will need to do this from scratch,&lt;br&gt;
but for the sake of demonstration it is already there in full.&lt;/p&gt;

&lt;p&gt;Note that we have four occurrences of &lt;code&gt;// TODO perform assertions&lt;/code&gt; in the test code,&lt;br&gt;
and in this workshop we will be writing those assertions.&lt;/p&gt;

&lt;p&gt;Also note that within the &lt;code&gt;contract&lt;/code&gt; block for &lt;code&gt;'Cars - events'&lt;/code&gt;,&lt;br&gt;
we have a &lt;code&gt;before&lt;/code&gt; block.&lt;br&gt;
This is used to set up the state of the contract by adding a couple of&lt;br&gt;
car objects,&lt;br&gt;
because these particular tests only make sense if there&lt;br&gt;
already are car objects stored within the smart contract.&lt;br&gt;
This has already been done for you,&lt;br&gt;
so that you may focus on writing the tests.&lt;/p&gt;
&lt;h2&gt;
  
  
  Initial test run
&lt;/h2&gt;

&lt;p&gt;At this point, we are all set to let Truffle Test, our test runner,&lt;br&gt;
do its thing, which will execute out specification,&lt;br&gt;
which in turn will execute our implementation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You should see output similar to the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm run &lt;span class="nb"&gt;test&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; workshop-rsk-smart-contract-testing-ozcli@0.0.0 &lt;span class="nb"&gt;test&lt;/span&gt; /home/bguiz/code/rsk/workshop-rsk-smart-contract-testing-ozcli
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; oz compile &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; mocha &lt;span class="nt"&gt;--exit&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; ./test/&lt;span class="k"&gt;**&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.spec.js

✓ Compiled contracts with solc 0.5.17 &lt;span class="o"&gt;(&lt;/span&gt;commit.d19bba13&lt;span class="o"&gt;)&lt;/span&gt;


  Cars - initial state
    ✓ Initialised with zero cars

  Cars - state transitions
    ✓ Adds a new car &lt;span class="o"&gt;(&lt;/span&gt;124ms&lt;span class="o"&gt;)&lt;/span&gt;

  Cars - events
    ✓ Honks a car at another car
    ✓ Honking a car that you &lt;span class="k"&gt;do &lt;/span&gt;not own is not allowed &lt;span class="o"&gt;(&lt;/span&gt;44ms&lt;span class="o"&gt;)&lt;/span&gt;


  4 passing &lt;span class="o"&gt;(&lt;/span&gt;608ms&lt;span class="o"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Great! Our test runner (OZ CLI test) has run successfully! 🎉 🎉 🎉&lt;/p&gt;

&lt;p&gt;Our test runner has done the above,&lt;br&gt;
listening for which tests have passed or failed,&lt;br&gt;
and if there were any errors thrown.&lt;/p&gt;

&lt;p&gt;However, note that since we have &lt;strong&gt;four&lt;/strong&gt; tests in our specification,&lt;br&gt;
and they are indeed interacting with the smart contract (implementation),&lt;br&gt;
but none of them are performing any assertions,&lt;br&gt;
so we don't know whether the implementation is correct or not.&lt;/p&gt;

&lt;p&gt;That means that it is time to write our first assertions!&lt;/p&gt;
&lt;h2&gt;
  
  
  Writing a test for initial state
&lt;/h2&gt;

&lt;p&gt;Edit &lt;code&gt;test/Cars.spec.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Replace the line that says &lt;code&gt;// TODO perform assertions&lt;/code&gt;&lt;br&gt;
with an assertion.&lt;br&gt;
It should now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Initialised with zero cars&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;initialNumCars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;numCars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialNumCars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This test is grouped within a &lt;code&gt;contract&lt;/code&gt; block.&lt;br&gt;
When there are multiple tests within the same &lt;code&gt;contract&lt;/code&gt; block,&lt;br&gt;
the state of the smart contract&lt;br&gt;
is not reset between one test and the next.&lt;br&gt;
However, when there are multiple tests in different &lt;code&gt;describe&lt;/code&gt; blocks,&lt;br&gt;
the state of the smart contract&lt;br&gt;
is indeed reset between one &lt;code&gt;describe&lt;/code&gt; block and the next,&lt;br&gt;
as we are doing this explicitly by setting up a new &lt;code&gt;instance&lt;/code&gt; variable in each one.&lt;/p&gt;

&lt;p&gt;For those accustomed to working with Truffle,&lt;br&gt;
this is analogous to doing &lt;code&gt;const instance = await Cars.deployed();&lt;/code&gt;&lt;br&gt;
within &lt;strong&gt;each&lt;/strong&gt; &lt;code&gt;it&lt;/code&gt; block.&lt;br&gt;
In OZ CLI, instead of doing this, we use the method described above.&lt;br&gt;
This might take a bit of getting used to,&lt;br&gt;
but is indeed exactly how one would do this&lt;br&gt;
in "regular" Javascript testing with Mocha.&lt;/p&gt;

&lt;p&gt;In this case, this is the first (and only) &lt;code&gt;it&lt;/code&gt; block within this &lt;code&gt;describe&lt;/code&gt; block,&lt;br&gt;
so it is perfect for testing the initial state of the smart contract.&lt;/p&gt;

&lt;p&gt;The line &lt;code&gt;const initialNumCars = await instance.numCars.call();&lt;/code&gt;&lt;br&gt;
retrieves the value of the &lt;code&gt;numCars&lt;/code&gt; variable in the smart contract.&lt;/p&gt;

&lt;p&gt;The line &lt;code&gt;assert.equal(initialNumCars.toString(), '0');&lt;/code&gt;&lt;br&gt;
passes the test if this value is zero,&lt;br&gt;
and fails the test if this value is anything other than zero.&lt;/p&gt;
&lt;h2&gt;
  
  
  Test run for initial state
&lt;/h2&gt;

&lt;p&gt;Now we are going to let OZ CLI Test, our test runner,&lt;br&gt;
do its thing again.&lt;/p&gt;

&lt;p&gt;This time we have a test defined in our specification,&lt;br&gt;
so when mocha executes our specification,&lt;br&gt;
it will indeed execute out implementation in turn.&lt;/p&gt;

&lt;p&gt;(Previously, when we had zero tests,&lt;br&gt;
the implementation was not executed at all.)&lt;/p&gt;

&lt;p&gt;Run OZ CLI Test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You should see some output similar to the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm run &lt;span class="nb"&gt;test&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; workshop-rsk-smart-contract-testing-ozcli@0.0.0 &lt;span class="nb"&gt;test&lt;/span&gt; /home/bguiz/code/rsk/workshop-rsk-smart-contract-testing-ozcli
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; oz compile &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; mocha &lt;span class="nt"&gt;--exit&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; ./test/&lt;span class="k"&gt;**&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.spec.js

Nothing to compile, all contracts are up to date.


  Cars - initial state
    ✓ Initialised with zero cars &lt;span class="o"&gt;(&lt;/span&gt;59ms&lt;span class="o"&gt;)&lt;/span&gt;

  Cars - state transitions
    ✓ Adds a new car &lt;span class="o"&gt;(&lt;/span&gt;122ms&lt;span class="o"&gt;)&lt;/span&gt;

  Cars - events
    ✓ Honks a car at another car
    ✓ Honking a car that you &lt;span class="k"&gt;do &lt;/span&gt;not own is not allowed &lt;span class="o"&gt;(&lt;/span&gt;45ms&lt;span class="o"&gt;)&lt;/span&gt;


  4 passing &lt;span class="o"&gt;(&lt;/span&gt;693ms&lt;span class="o"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Great! 🎉 🎉 🎉&lt;/p&gt;

&lt;p&gt;OZ CLI Test, our test runner has worked as promised,&lt;br&gt;
listening for which tests have passed or failed,&lt;br&gt;
and if there were any errors thrown.&lt;br&gt;
This time we have verification not only that&lt;br&gt;
our implementation has been executed,&lt;br&gt;
but also that it is correct&lt;br&gt;
(at least according to how we have written our tests).&lt;/p&gt;

&lt;p&gt;The output is almost identical to the output before,&lt;br&gt;
except that it takes a (marginally) longer time to execute.&lt;br&gt;
The main thing that we need to look out for here is&lt;br&gt;
whether we have gone from having 4 tests passing to less than 4 tests passing,&lt;br&gt;
which would indicate that there is either&lt;br&gt;
a problem with our specification (a false negative),&lt;br&gt;
or a problem with our implementation (a true negative).&lt;/p&gt;

&lt;p&gt;Testing the initial state of a smart contract is the simplest possible&lt;br&gt;
type of test we can write.&lt;br&gt;
Now let's move on to &lt;strong&gt;more complex tests&lt;/strong&gt; for state transitions and events.&lt;/p&gt;
&lt;h2&gt;
  
  
  Writing a test for state transition
&lt;/h2&gt;

&lt;p&gt;Edit &lt;code&gt;test/Cars.spec.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Replace the two lines that say &lt;code&gt;// TODO perform assertions&lt;/code&gt;&lt;br&gt;
with assertions.&lt;br&gt;
It should now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Adds a new car&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// preview the return value without modifying the state&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;returnValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addCar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0xff00ff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// colour: purple&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// doors: 4&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// distance: 0&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// lat: 0&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// lon: 0&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toWei&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.11&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ether&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;returnValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// perform the state transition&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;addCar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0xff00ff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// colour: purple&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// doors: 4&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// distance: 0&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// lat: 0&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// lon: 0&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;web3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;utils&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toWei&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0.11&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ether&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// retrieve the updated state&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;numCars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;numCars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;car1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;BN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="c1"&gt;// perform the assertions&lt;/span&gt;
    &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numCars&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;car1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;colour&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0xff00ff&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;car1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;doors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;car1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;car1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;car1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;car1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// parked&lt;/span&gt;
    &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;car1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The line &lt;code&gt;const returnValue = await instance.addCar.call(/* ... */);&lt;/code&gt;&lt;br&gt;
retrieves the return value of the &lt;code&gt;addCar&lt;/code&gt; function.&lt;br&gt;
Some participants in this workshop may have noticed something&lt;br&gt;
that is perhaps a little strange:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;addCar&lt;/code&gt; is a function that causes a state transition,
as it updates the values stored in the smart contract.
In fact it has neither the &lt;code&gt;view&lt;/code&gt; nor &lt;code&gt;pure&lt;/code&gt; function modifiers.&lt;/li&gt;
&lt;li&gt;In our smart contract invocation, we are executing &lt;code&gt;.addCar.call()&lt;/code&gt;
and not &lt;code&gt;.addCar()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Usually we use &lt;code&gt;.call()&lt;/code&gt; when invoking &lt;code&gt;view&lt;/code&gt; or &lt;code&gt;pure&lt;/code&gt; functions,&lt;br&gt;
so why are we using &lt;code&gt;.call()&lt;/code&gt; here on a function which&lt;br&gt;
explicitly causes a state transition?&lt;/p&gt;

&lt;p&gt;The answer to that is not exactly straightforward:&lt;br&gt;
We are doing so to "emulate" what the return value&lt;br&gt;
of this particular call to the smart contract would be, &lt;strong&gt;without&lt;/strong&gt;&lt;br&gt;
actually causing the state transition.&lt;br&gt;
Think of this as "previewing" the function invocation.&lt;br&gt;
The reason we need to do this is because if it were a true function invocation&lt;br&gt;
that resulted in a state transition on the smart contract,&lt;br&gt;
we don't have access to the return value.&lt;/p&gt;

&lt;p&gt;The line &lt;code&gt;assert.equal(returnValue.toString(), '1');&lt;/code&gt; is the first assertion,&lt;br&gt;
and will fail this test if the new &lt;code&gt;carId&lt;/code&gt; is any value other than one.&lt;/p&gt;

&lt;p&gt;The line &lt;code&gt;const tx = await instance.addCar(/* ... */);&lt;/code&gt;&lt;br&gt;
is where the actual state transition occurs.&lt;br&gt;
This is a "true" invocation of the &lt;code&gt;addCar&lt;/code&gt; function,&lt;br&gt;
unlike the previous "preview" invocation of the &lt;code&gt;addCar&lt;/code&gt; function.&lt;br&gt;
When this line has been executed, a transaction has been added to a block,&lt;br&gt;
and that block to the blockchain.&lt;br&gt;
This test, and any other test that involves a smart contract state transition,&lt;br&gt;
will be significantly slower than tests that do not,&lt;br&gt;
such as the one that we wrote earlier for the initial state.&lt;/p&gt;

&lt;p&gt;The lines &lt;code&gt;const numCars = await instance.numCars.call();&lt;/code&gt;&lt;br&gt;
and &lt;code&gt;const car1 = await instance.cars.call(new BN(1));&lt;/code&gt;&lt;br&gt;
retrieve the new/ updated state from the smart contract.&lt;/p&gt;

&lt;p&gt;The remaining lines are many &lt;code&gt;assert.equal()&lt;/code&gt; statements,&lt;br&gt;
which will fail this test is the new/ updated state does not match the expected values.&lt;/p&gt;
&lt;h2&gt;
  
  
  Test run for state transition
&lt;/h2&gt;

&lt;p&gt;Now we are going to run our tests again.&lt;/p&gt;

&lt;p&gt;This time we have two tests.&lt;/p&gt;

&lt;p&gt;Run Truffle Test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You should see output similar to the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm run &lt;span class="nb"&gt;test&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; workshop-rsk-smart-contract-testing-ozcli@0.0.0 &lt;span class="nb"&gt;test&lt;/span&gt; /home/bguiz/code/rsk/workshop-rsk-smart-contract-testing-ozcli
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; oz compile &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; mocha &lt;span class="nt"&gt;--exit&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; ./test/&lt;span class="k"&gt;**&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.spec.js

Nothing to compile, all contracts are up to date.


  Cars - initial state
    ✓ Initialised with zero cars

  Cars - state transitions
    ✓ Adds a new car &lt;span class="o"&gt;(&lt;/span&gt;176ms&lt;span class="o"&gt;)&lt;/span&gt;

  Cars - events
    ✓ Honks a car at another car
    ✓ Honking a car that you &lt;span class="k"&gt;do &lt;/span&gt;not own is not allowed &lt;span class="o"&gt;(&lt;/span&gt;45ms&lt;span class="o"&gt;)&lt;/span&gt;


  4 passing &lt;span class="o"&gt;(&lt;/span&gt;654ms&lt;span class="o"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;All four tests continue passing. Great! 🎉 🎉 🎉&lt;/p&gt;

&lt;p&gt;Again, the main thing that we are looking out for here is&lt;br&gt;
that the tests continue passing.&lt;br&gt;
If one of the tests began to fail,&lt;br&gt;
we know that there is either a problem with the implementation (a true negative),&lt;br&gt;
or a problem with our specification (a false negative).&lt;/p&gt;
&lt;h2&gt;
  
  
  Test run with false negative for state transition
&lt;/h2&gt;

&lt;p&gt;If you are feeling in an exploratory mood,&lt;br&gt;
you can try the following out:&lt;/p&gt;

&lt;p&gt;Replace &lt;code&gt;assert.equal(car1.colour, '0xff00ff');&lt;/code&gt;,&lt;br&gt;
the on of the assertions in this test,&lt;br&gt;
with &lt;code&gt;assert.equal(car1.colour, '0xff00aa');&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Run the tests again, using &lt;code&gt;npm run test&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Observe that the output indicates an assertion error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;i&lt;span class="nv"&gt;$ &lt;/span&gt;npm run &lt;span class="nb"&gt;test&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; workshop-rsk-smart-contract-testing-ozcli@0.0.0 &lt;span class="nb"&gt;test&lt;/span&gt; /home/bguiz/code/rsk/workshop-rsk-smart-contract-testing-ozcli
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; oz compile &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; mocha &lt;span class="nt"&gt;--exit&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; ./test/&lt;span class="k"&gt;**&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.spec.js

Nothing to compile, all contracts are up to date.


  Cars - initial state
    ✓ Initialised with zero cars

  Cars - state transitions
    1&lt;span class="o"&gt;)&lt;/span&gt; Adds a new car

  Cars - events
    ✓ Honks a car at another car &lt;span class="o"&gt;(&lt;/span&gt;42ms&lt;span class="o"&gt;)&lt;/span&gt;
    ✓ Honking a car that you &lt;span class="k"&gt;do &lt;/span&gt;not own is not allowed &lt;span class="o"&gt;(&lt;/span&gt;46ms&lt;span class="o"&gt;)&lt;/span&gt;


  3 passing &lt;span class="o"&gt;(&lt;/span&gt;740ms&lt;span class="o"&gt;)&lt;/span&gt;
  1 failing

  1&lt;span class="o"&gt;)&lt;/span&gt; Cars - state transitions
       Adds a new car:

      AssertionError &lt;span class="o"&gt;[&lt;/span&gt;ERR_ASSERTION]: &lt;span class="s1"&gt;'0xff00ff'&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'0xff00aa'&lt;/span&gt;
      + expected - actual

      &lt;span class="nt"&gt;-0xff00ff&lt;/span&gt;
      +0xff00aa

      at Context.&amp;lt;anonymous&amp;gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;/Cars.spec.js:74:12&lt;span class="o"&gt;)&lt;/span&gt;
      at processTicksAndRejections &lt;span class="o"&gt;(&lt;/span&gt;internal/process/task_queues.js:97:5&lt;span class="o"&gt;)&lt;/span&gt;



npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! workshop-rsk-smart-contract-testing-ozcli@0.0.0 &lt;span class="nb"&gt;test&lt;/span&gt;: &lt;span class="sb"&gt;`&lt;/span&gt;oz compile &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; mocha &lt;span class="nt"&gt;--exit&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; ./test/&lt;span class="k"&gt;**&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.spec.js&lt;span class="sb"&gt;`&lt;/span&gt;
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the workshop-rsk-smart-contract-testing-ozcli@0.0.0 &lt;span class="nb"&gt;test &lt;/span&gt;script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Of course in this case, we were expecting it,&lt;br&gt;
and already know that the problem lies in the specification,&lt;br&gt;
in particular, an incorrect assertion.&lt;/p&gt;

&lt;p&gt;However, in a real (non-demo) scenario, when we encounter this,&lt;br&gt;
we would know that we have encountered a test failure,&lt;br&gt;
and would require investigation to determine whether this was due to&lt;br&gt;
a problem in the implementation,&lt;br&gt;
causing a true negative;&lt;br&gt;
or conversely whether there was a problem with the specification,&lt;br&gt;
causing a false negative.&lt;/p&gt;

&lt;p&gt;If you have chosen to do this additional step,&lt;br&gt;
do remember to revert the change before continuing&lt;br&gt;
with the rest of this workshop.&lt;/p&gt;
&lt;h2&gt;
  
  
  Writing a test for events
&lt;/h2&gt;

&lt;p&gt;Edit &lt;code&gt;test/Cars.spec.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As mentioned previously, this &lt;code&gt;contract&lt;/code&gt; block contains&lt;br&gt;
a &lt;code&gt;before&lt;/code&gt; block which sets up the smart contract instance&lt;br&gt;
to contain two cars prior to running any tests.&lt;br&gt;
This has been done for you, so you may skim over it,&lt;br&gt;
and get right to writing some tests.&lt;/p&gt;

&lt;p&gt;Replace the first line that says &lt;code&gt;// TODO perform assertions&lt;/code&gt;&lt;br&gt;
with assertions.&lt;br&gt;
The &lt;code&gt;it&lt;/code&gt; block should now look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Honks a car at another car&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// perform the state transition&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;honkCar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;// account #2 owns car #2&lt;/span&gt;
          &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="c1"&gt;// inspect the transaction &amp;amp; perform assertions on the logs&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;logs&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;logs&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
      &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;logs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;logs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
      &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CarHonk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fromCar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;atCar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In our previous test, where we invoked &lt;code&gt;addCar&lt;/code&gt;,&lt;br&gt;
we did not use the return value (&lt;code&gt;tx&lt;/code&gt;)&lt;br&gt;
in the remainder of the test.&lt;br&gt;
In this test, we will.&lt;/p&gt;

&lt;p&gt;The line &lt;code&gt;const tx = await instance.honkCar(/* ... */);&lt;/code&gt;&lt;br&gt;
invokes the &lt;code&gt;honkCar&lt;/code&gt; function,&lt;br&gt;
and saves the transaction in &lt;code&gt;tx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The next three lines, beginning with &lt;code&gt;const { logs } = tx;&lt;/code&gt;,&lt;br&gt;
extract &lt;code&gt;tx.logs&lt;/code&gt;.&lt;br&gt;
The assertion statements will fail this test if&lt;br&gt;
there is no &lt;code&gt;tx.logs&lt;/code&gt; array,&lt;br&gt;
or if it has a number of logs that is anything other than one.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that in RSK, transaction logs are generated when&lt;br&gt;
an event is emitted within that transaction.&lt;br&gt;
This is equivalent to the behaviour of transaction logs in Ethereum.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The next four lines, beginning with &lt;code&gt;const log = logs[0];&lt;/code&gt;,&lt;br&gt;
extract the first (and only) event from this transaction.&lt;br&gt;
The assertion statements will fail this test is the&lt;br&gt;
event is not of the expected type or contain unexpected parameters.&lt;/p&gt;

&lt;p&gt;So far, in each &lt;code&gt;describe&lt;/code&gt; block we have had only one test,&lt;br&gt;
but this time we'll be doing something different,&lt;br&gt;
with two tests sharing the same &lt;code&gt;describe&lt;/code&gt; block.&lt;/p&gt;

&lt;p&gt;Replace the second line that says &lt;code&gt;// TODO perform assertions&lt;/code&gt;&lt;br&gt;
with assertions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Honking a car that you do not own is not allowed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// perform the state transition&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;tx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;honkCar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// account #3 does not own any cars, only account #1 and #2 do&lt;/span&gt;
            &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;accounts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// should not get a result, but an error should have been thrown&lt;/span&gt;
    &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;assert&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The line &lt;code&gt;const tx = await instance.honkCar(/* ... */);&lt;/code&gt;&lt;br&gt;
is similar to the &lt;code&gt;honkCar&lt;/code&gt; invocation from before.&lt;br&gt;
However, if you take a look at the parameters,&lt;br&gt;
you will notice that we attempt to operate a car&lt;br&gt;
using an account that does not own it.&lt;/p&gt;

&lt;p&gt;Also, unlike the invocation in the previous test,&lt;br&gt;
this statement has been surrounded by a &lt;code&gt;try ... catch&lt;/code&gt; block,&lt;br&gt;
because we are expecting this invocation to throw an error.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note that in the implementation, &lt;code&gt;contracts/Cars.sol&lt;/code&gt;,&lt;br&gt;
the &lt;code&gt;honkCar(carId,otherCarId)&lt;/code&gt; function has a function modifier&lt;br&gt;
for &lt;code&gt;onlyCarOwner(carId)&lt;/code&gt;, which contains this statement:&lt;br&gt;
&lt;code&gt;require(cars[carId].owner == msg.sender, "you need to own this car");&lt;/code&gt;.&lt;br&gt;
The purpose of this is that only a car's owner is allowed to honk it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Thus far, all of our tests have been "happy path" cases,&lt;br&gt;
where the smart contract functions are always called in the expected way.&lt;br&gt;
These tests ensure that the smart contract behaves as it is supposed to,&lt;br&gt;
when those interacting with it do the "right thing".&lt;/p&gt;

&lt;p&gt;However, external behaviour is something that is &lt;strong&gt;not&lt;/strong&gt;&lt;br&gt;
within the locus of our control,&lt;br&gt;
and therefore by definition we need to ensure that our smart contract&lt;br&gt;
is able to handle these "failure path" cases too.&lt;br&gt;
In this case our implementation appears to have handled it,&lt;br&gt;
and we are writing a test within the specification to verify the handling.&lt;/p&gt;

&lt;p&gt;The final two lines, &lt;code&gt;assert.ok(err);&lt;/code&gt; and &lt;code&gt;assert.ok(!tx);&lt;/code&gt;,&lt;br&gt;
will fail this test if the &lt;code&gt;honkCar&lt;/code&gt; invocation succeeded,&lt;br&gt;
when it was not supposed.&lt;br&gt;
Remember: We are &lt;strong&gt;not&lt;/strong&gt; testing the "happy path" here.&lt;br&gt;
Instead we are testing the "failure path".&lt;/p&gt;
&lt;h2&gt;
  
  
  Test run for events
&lt;/h2&gt;

&lt;p&gt;Now we are going to run our tests again.&lt;/p&gt;

&lt;p&gt;This time we have four tests.&lt;/p&gt;

&lt;p&gt;Run Truffle Test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You should see output similar to the following&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm run &lt;span class="nb"&gt;test&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; workshop-rsk-smart-contract-testing-ozcli@0.0.0 &lt;span class="nb"&gt;test&lt;/span&gt; /home/bguiz/code/rsk/workshop-rsk-smart-contract-testing-ozcli
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; oz compile &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; mocha &lt;span class="nt"&gt;--exit&lt;/span&gt; &lt;span class="nt"&gt;--recursive&lt;/span&gt; ./test/&lt;span class="k"&gt;**&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;.spec.js

Nothing to compile, all contracts are up to date.


  Cars - initial state
    ✓ Initialised with zero cars

  Cars - state transitions
    ✓ Adds a new car &lt;span class="o"&gt;(&lt;/span&gt;124ms&lt;span class="o"&gt;)&lt;/span&gt;

  Cars - events
    ✓ Honks a car at another car
    ✓ Honking a car that you &lt;span class="k"&gt;do &lt;/span&gt;not own is not allowed &lt;span class="o"&gt;(&lt;/span&gt;87ms&lt;span class="o"&gt;)&lt;/span&gt;


  4 passing &lt;span class="o"&gt;(&lt;/span&gt;718ms&lt;span class="o"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;All four are still passing. Great! 🎉 🎉 🎉&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We have now created specifications for testing initial state,&lt;br&gt;
state transitions, and events in a smart contract written in Solidity.&lt;/p&gt;

&lt;p&gt;We have also configure the OpenZeppelin CLI to connect to RSK networks,&lt;br&gt;
and used it as a test runner to execute our specifications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Going further
&lt;/h2&gt;

&lt;p&gt;We have now completed this workshop.&lt;br&gt;
Congratulations on making it to the end! 🎉 🎉 🎉&lt;/p&gt;

&lt;p&gt;There is a lot more to explore with regards to Smart contract testing.&lt;/p&gt;

&lt;p&gt;For example, you may have noticed that in the&lt;br&gt;
implementation for &lt;code&gt;honkCar()&lt;/code&gt;,&lt;br&gt;
we have commented out a &lt;code&gt;require()&lt;/code&gt; statement&lt;br&gt;
that verifies the value of &lt;code&gt;getTime()&lt;/code&gt;.&lt;br&gt;
Writing a robust specification for this implementation is seemingly not possible,&lt;br&gt;
as it behaves differently depending on the time of day it is run.&lt;br&gt;
Mocking is a testing technique that will enable us to&lt;br&gt;
replace one (or sometimes more) functions within a smart contract&lt;br&gt;
in order to be able to test it in particular ways,&lt;br&gt;
and will help in this case.&lt;/p&gt;

&lt;p&gt;Check out&lt;br&gt;
&lt;a href="https://dappsdev.org/hands-on/testing/solidity-mocks/"&gt;DApps Dev Club's Mocking Solidity for Tests&lt;/a&gt;&lt;br&gt;
if you would like to try out &lt;strong&gt;smart contract mocking&lt;/strong&gt; as a continuation of this tutorial.&lt;br&gt;
(This workshop is a modified and shortened version from that original.)&lt;/p&gt;

</description>
      <category>rsk</category>
      <category>solidity</category>
      <category>testing</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
