<?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: Sagar Gurung</title>
    <description>The latest articles on DEV Community by Sagar Gurung (@sagargi).</description>
    <link>https://dev.to/sagargi</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%2F509380%2F5ad8fd8f-d543-41d7-b2e1-5b578125c1c2.png</url>
      <title>DEV Community: Sagar Gurung</title>
      <link>https://dev.to/sagargi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sagargi"/>
    <language>en</language>
    <item>
      <title>Options Vs Composition API in Vue JS</title>
      <dc:creator>Sagar Gurung</dc:creator>
      <pubDate>Tue, 12 Mar 2024 09:37:48 +0000</pubDate>
      <link>https://dev.to/jankaritech/options-vs-composition-api-in-vue-js-4659</link>
      <guid>https://dev.to/jankaritech/options-vs-composition-api-in-vue-js-4659</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;When it comes to defining or creating a component in &lt;code&gt;Vue.js&lt;/code&gt;, we probably have heard about the &lt;code&gt;Options API&lt;/code&gt;. Using &lt;code&gt;Options API&lt;/code&gt; not only we can create specific aspects or behaviors of a component but also allows us how we want to build components.&lt;br&gt;
It provides different properties (or options) such as &lt;code&gt;data&lt;/code&gt;, &lt;code&gt;methods&lt;/code&gt;, &lt;code&gt;computed&lt;/code&gt;, and &lt;code&gt;watch&lt;/code&gt; through which we can organize the behavior of a component systematically. But since &lt;code&gt;Vue 3&lt;/code&gt;, we have another API called &lt;code&gt;Composition API&lt;/code&gt; through which we can achieve the same thing. The &lt;code&gt;Composition API&lt;/code&gt; is a new highlight for many Vue developers, but both approaches to define components have their unique pros and cons. So debating which among these two is better would be a difficult one.&lt;/p&gt;

&lt;p&gt;In this blog, we will learn how we can convert a component defined in &lt;code&gt;Options API&lt;/code&gt; to &lt;code&gt;Composition API&lt;/code&gt; and we will also discuss the comparison of both APIs. Also at the end, we will know how we can define the component with &lt;code&gt;Composition API&lt;/code&gt;.&lt;br&gt;
To demonstrate this, I have created a simple application called &lt;a href="https://github.com/SagarGi/OptionsVsCompositionVue"&gt;&lt;code&gt;Voting Details&lt;/code&gt;&lt;/a&gt;, which we will be examining together in this blog.&lt;/p&gt;
&lt;h2&gt;
  
  
  Play around with &lt;code&gt;Voting Details&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;I have put this section in this blog since it's better to know some information about what we are building. The &lt;code&gt;Voting Details&lt;/code&gt; demo application stores the user's details and checks whether a user is eligible to vote or not.&lt;br&gt;
I have implemented two separate components with the same functionalities, one is using &lt;code&gt;Options API&lt;/code&gt; and the other is using &lt;code&gt;Composition API&lt;/code&gt;. We will go through a bit in brief how we can change the functionality of a component same as in &lt;code&gt;Options API&lt;/code&gt; with &lt;code&gt;Composition API&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: To get the application up and running, make sure &lt;a href="https://nodejs.org/en/download"&gt;Node.js&lt;/a&gt; version 16 or above is installed into your system.&lt;br&gt;
&lt;/p&gt;


&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;git clone https://github.com/SagarGi/OptionsVsCompositionVue
cd OptionsVsCompositionVue
npm install
npm run dev
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can access it through URL &lt;a href="http://localhost:8000"&gt;http://localhost:8000&lt;/a&gt; and the application looks something like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6lrgly7ndzmi85yv52yk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6lrgly7ndzmi85yv52yk.png" alt="Sample Voting User Interface" width="800" height="886"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What's in &lt;code&gt;Options API&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;For the demo application, in &lt;code&gt;Voting Details&lt;/code&gt; I have defined a component using &lt;code&gt;Options API&lt;/code&gt; as:&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;data&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="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sagar Gurung&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;bornYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2005&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;votingStatus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Eligible!&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="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;increaseAge&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="nf"&gt;decreaseAge&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="o"&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;computed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;getVotingStatus&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="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&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;Eligible&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;Not Eligible&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="na"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;age&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;oldAge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newAge&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="nx"&gt;oldAge&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;newAge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bornYear&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bornYear&lt;/span&gt;&lt;span class="o"&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="p"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this demo app the properties &lt;code&gt;data&lt;/code&gt;, &lt;code&gt;methods&lt;/code&gt;, &lt;code&gt;computed&lt;/code&gt;, and &lt;code&gt;watch&lt;/code&gt; have been defined using &lt;code&gt;Options API&lt;/code&gt;. I will explain the meaning of each of them in the &lt;code&gt;Composition API&lt;/code&gt; section since we are converting component defined in &lt;code&gt;Options API&lt;/code&gt; with &lt;code&gt;Composition API&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Converting to &lt;strong&gt;&lt;em&gt;Composition API&lt;/em&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Defining &lt;code&gt;data&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;When defining the data necessary for a component, in &lt;code&gt;Composition API&lt;/code&gt;, we have to make it reactive to mutate or change values with &lt;code&gt;ref&lt;/code&gt; or &lt;code&gt;reactive&lt;/code&gt; provided by Vue.js.&lt;br&gt;
So data property can be defined as:&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="c1"&gt;// data&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sagar Gurung&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;votingStatus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Eligible&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;bornYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2005&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Defining &lt;code&gt;methods&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Defining the methods is very simple. It is just as easy as defining functions in JavaScript.&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="c1"&gt;// methods&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;increaseAge&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;decreaseAge&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="o"&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 above function changes the &lt;code&gt;age&lt;/code&gt; property of the data defined in &lt;code&gt;data&lt;/code&gt; which is reactive.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Defining &lt;code&gt;computed&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;To define the computed property Vue provides the method called &lt;code&gt;computed&lt;/code&gt; through which we can explicitly define the computed function.&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="c1"&gt;//computed&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getVotingStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&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;Eligible&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;Not Eligible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here the operation &lt;code&gt;getVotingStatus&lt;/code&gt; returns the voting status based on value of age.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Defining &lt;code&gt;watch&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Similarly, Vue has provided a &lt;code&gt;watch&lt;/code&gt; function to watch the change in any data properties defined.&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="c1"&gt;//watcher&lt;/span&gt;
    &lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mainData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;oldAge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newAge&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="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;oldAge&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;newAge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bornYear&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;
      &lt;span class="p"&gt;}&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bornYear&lt;/span&gt;&lt;span class="o"&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 have watched data &lt;code&gt;age&lt;/code&gt; in such a way that when age is increased the data &lt;code&gt;bornYear&lt;/code&gt; will decrease and vice-versa.&lt;/p&gt;

&lt;p&gt;The whole script code snippet looks like this at last for the &lt;code&gt;Composition API&lt;/code&gt;:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toRefs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;computed&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// data&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;reactive&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Sagar Gurung&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;votingStatus&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Eligible&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;bornYear&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;2005&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;mainData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;toRefs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// methods&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;increaseAge&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;decreaseAge&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;//computed&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getVotingStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;computed&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&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;Eligible&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;Not Eligible&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="c1"&gt;//watcher&lt;/span&gt;
    &lt;span class="nf"&gt;watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;mainData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;oldAge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newAge&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="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;oldAge&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;newAge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bornYear&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;
      &lt;span class="p"&gt;}&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bornYear&lt;/span&gt;&lt;span class="o"&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;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;mainData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;increaseAge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;decreaseAge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;getVotingStatus&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;In the final code, we have imported &lt;code&gt;reactive&lt;/code&gt;, &lt;code&gt;toRefs&lt;/code&gt;, &lt;code&gt;computed&lt;/code&gt;, and &lt;code&gt;watch&lt;/code&gt; which are needed for building components with the &lt;code&gt;Composition API&lt;/code&gt;. &lt;code&gt;toRefs&lt;/code&gt; is used to convert the data created with &lt;code&gt;reactive&lt;/code&gt; to plain objects. Also, when using &lt;code&gt;Composition API&lt;/code&gt; we need to define all those &lt;code&gt;data&lt;/code&gt;, &lt;code&gt;computed&lt;/code&gt;, &lt;code&gt;watch&lt;/code&gt;, and &lt;code&gt;methods&lt;/code&gt; inside of function &lt;code&gt;setup()&lt;/code&gt; as done above.&lt;br&gt;
At last, all the things that have been defined such as &lt;code&gt;data&lt;/code&gt;, &lt;code&gt;computed&lt;/code&gt;, and &lt;code&gt;methods&lt;/code&gt; need to be returned to be exposed to the template.&lt;/p&gt;

&lt;p&gt;In this demo application we have learnt the basics of how to convert a component defined with &lt;code&gt;Options API&lt;/code&gt; to &lt;code&gt;Composition API&lt;/code&gt;. However, there are lots of other things that we can perform using the &lt;code&gt;Composition API&lt;/code&gt;.&lt;br&gt;
I hope this blog gave you some insights on how to use the &lt;code&gt;Composition API&lt;/code&gt; and also how you can replace your component defined in &lt;code&gt;Options API&lt;/code&gt; with it.&lt;br&gt;
If you want to learn more about both &lt;code&gt;Options API&lt;/code&gt; and &lt;code&gt;Composition API&lt;/code&gt; then you can learn more from &lt;a href="https://vuejs.org/api/composition-api-setup.html"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But before finishing the blog I would like to highlight some points regarding both &lt;code&gt;Options API&lt;/code&gt; and &lt;code&gt;Composition API&lt;/code&gt; so that you can relate which one to prefer before building up your projects.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;Options API&lt;/code&gt; and &lt;code&gt;Composition API&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;You can find a lot of points regarding the comparison between these two APIs, both approaches for building up components have their benefits and drawbacks. I will only highlight five differences which I consider most relevant for choosing whether to use the &lt;code&gt;Options API&lt;/code&gt; or &lt;code&gt;Composition API&lt;/code&gt; in your own project:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;Composition API&lt;/code&gt; is new to Vue which can be called a modern way to define components whereas on the other hand &lt;code&gt;Options API&lt;/code&gt; is a proven, traditional way to build up components in Vue.&lt;/li&gt;
&lt;li&gt;Also, the structure and syntax for the &lt;code&gt;Options API&lt;/code&gt; seems a bit simpler and easier to understand than that of the &lt;code&gt;Composition API&lt;/code&gt;. It's a good choice for small projects and also for beginners. But for large and more complex projects, a better choice would be &lt;code&gt;Composition API&lt;/code&gt; since it has a more flexible and modular structure that enhances better code maintainability.&lt;/li&gt;
&lt;li&gt;In addition to this, since &lt;code&gt;Composition API&lt;/code&gt; is fully based on functional, reactive programming it can be difficult for learners who are not familiar with this approach. In this case, &lt;code&gt;Options API&lt;/code&gt; could be a suitable choice.&lt;/li&gt;
&lt;li&gt;Moreover, &lt;code&gt;Composition API&lt;/code&gt; having a function based structure with better type inference, &lt;code&gt;Typescript&lt;/code&gt; support is better than that of &lt;code&gt;Options API&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Composition API&lt;/code&gt; supports better code reusability as it has functions and modular composition preventing complex code, which ultimately leads to more intuitive code.&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>vue</category>
      <category>frontend</category>
      <category>optionsapi</category>
      <category>compositionapi</category>
    </item>
    <item>
      <title>Containerize a Web Application using docker compose</title>
      <dc:creator>Sagar Gurung</dc:creator>
      <pubDate>Mon, 04 Dec 2023 04:30:56 +0000</pubDate>
      <link>https://dev.to/jankaritech/containerize-a-web-application-using-docker-compose-255a</link>
      <guid>https://dev.to/jankaritech/containerize-a-web-application-using-docker-compose-255a</guid>
      <description>&lt;p&gt;In this blog we will basically be containerizing a web application consisting of &lt;code&gt;MySQL&lt;/code&gt;, &lt;code&gt;phpmyadmin&lt;/code&gt;, &lt;code&gt;frontend&lt;/code&gt; and &lt;code&gt;backend&lt;/code&gt; as services using docker compose.&lt;br&gt;
Also, we briefly get into how all those services are running and how multiple services make up an application running in multiple containers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: This article does not provide concepts of docker. To know concepts of docker &lt;a href="https://blog.jankaritech.com/#/blog/How%20to%20use%20selenium%20in%20docker%3F"&gt;visit here.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Brief About Docker Compose
&lt;/h2&gt;

&lt;p&gt;In short, docker compose helps to define and run docker applications in multiple containers. With docker compose we can define a &lt;code&gt;yml&lt;/code&gt; file where we can define our services, networks, and the volumes required for our application to get it running. Basically, configuring, defining and managing all the necessary things required for our application becomes easy with docker compose.&lt;/p&gt;

&lt;p&gt;And in this blog, we will also be defining and configuring simple services for our application through a compose file and run it using docker compose.&lt;/p&gt;
&lt;h2&gt;
  
  
  What is the application about (to be run with docker compose)?
&lt;/h2&gt;

&lt;p&gt;The application we will be running with docker compose has 3 main services:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;frontend&lt;/code&gt; service&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;backend&lt;/code&gt; service&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mysql&lt;/code&gt; service (database service)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Also, we will be running the 4th service &lt;code&gt;phpmyadmin&lt;/code&gt; which is used for managing and administering MySQL with a GUI.&lt;br&gt;
This is a very simple application for demo, where in the &lt;code&gt;mysql&lt;/code&gt; database there are lists of user information and through the &lt;code&gt;frontend&lt;/code&gt; service we will request to the &lt;code&gt;backend&lt;/code&gt; service to get all those users and then list them in our application UI. Like this, all those application services are dependent and collaborating with each other. We will be configuring these through docker compose.&lt;/p&gt;
&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before we start, lets make sure following things get installed into your system.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;install &lt;a href="https://docs.docker.com/engine/install/debian/#install-using-the-repository"&gt;docker&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;install &lt;a href="https://docs.docker.com/compose/install/linux/#install-the-plugin-manually"&gt;docker compose&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: I will be doing the whole setup with Ubuntu 22.04 LTS. Things might differ if you have a different operating system.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Since we have enough information about the application and the prerequisites are fulfilled. We can now jump to the section for defining and configuring our application with docker compose.&lt;/p&gt;
&lt;h3&gt;
  
  
  Initiate file structure
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;create a directory &lt;code&gt;dockercompose&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;create a docker compose yml file &lt;code&gt;dockercompose/compose.yml&lt;/code&gt; inside it.&lt;/li&gt;
&lt;li&gt;Also create an empty &lt;code&gt;testdump.sql&lt;/code&gt; file (I will mention the use of it later)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It should look something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  📦dockercompose
      ┗ 📜compose.yml
      ┗ 📜testdump.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Defining and configuring services
&lt;/h3&gt;

&lt;p&gt;Now inside the &lt;code&gt;compose.yml&lt;/code&gt; let's define and configure the services for our application.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;database service (mysql)&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt; &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.8"&lt;/span&gt;

 &lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql&lt;/span&gt;
      &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
        &lt;span class="na"&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;demodb&lt;/span&gt;
      &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./testdump.sql:/docker-entrypoint-initdb.d/testdump.sql&lt;/span&gt;
      &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Here, defining services in docker compose we use the keyword &lt;code&gt;services&lt;/code&gt;. We have defined our service &lt;code&gt;database&lt;/code&gt; configured with &lt;code&gt;image:mysql&lt;/code&gt; and the &lt;code&gt;environment&lt;/code&gt; variables required for it.&lt;br&gt;
  We can see it has a &lt;code&gt;volumes&lt;/code&gt; keyword used here. We can mount local data to the docker container using the &lt;code&gt;volumes&lt;/code&gt; keyword. In this context, we have mapped &lt;code&gt;testdump.sql&lt;/code&gt; which is in our&lt;br&gt;
  local root directory which runs as an entrypoint when the container starts. It means when the &lt;code&gt;database&lt;/code&gt; service is started in a container, the &lt;code&gt;testdump.sql&lt;/code&gt; is the first thing which is run inside the container.&lt;br&gt;
  The entrypoint script will create 4 users in the database. Add some sql commands inside of &lt;code&gt;testdump.sql&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;    &lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;userid&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="n"&gt;AUTO_INCREMENT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fullname&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="nb"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Sagar Gurung'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'sagar@example.com'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Bob Johnson'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'bob@example.com'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Eva White'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'eva@example.com'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fullname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Michael Brown'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'michael@example.com'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;ALTER&lt;/span&gt; &lt;span class="k"&gt;USER&lt;/span&gt; &lt;span class="s1"&gt;'root'&lt;/span&gt; &lt;span class="n"&gt;IDENTIFIED&lt;/span&gt; &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;mysql_native_password&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="s1"&gt;'root'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;flush&lt;/span&gt; &lt;span class="k"&gt;privileges&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;backend service&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;backend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sagar4321/demo-server&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3001&lt;/span&gt;
      &lt;span class="na"&gt;DBHOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;database&lt;/span&gt;
      &lt;span class="na"&gt;DBPORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3306&lt;/span&gt;
      &lt;span class="na"&gt;DBUSER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
      &lt;span class="na"&gt;DBNAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;demodb&lt;/span&gt;
      &lt;span class="na"&gt;DBPASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3001:3001"&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;database&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Similarly, we define and configure our backend as above with the necessary &lt;code&gt;image:sagar4321/demo-server&lt;/code&gt; (this image is built and pushed to docker hub which I created), &lt;code&gt;environment&lt;/code&gt; and &lt;code&gt;port 3001&lt;/code&gt; (port where the server listens)&lt;br&gt;
  Here, we have another keyword &lt;code&gt;depends_on&lt;/code&gt; which has the value &lt;code&gt;database&lt;/code&gt; service. It sets the order in which services must start and stop. For the above case, the &lt;code&gt;database&lt;/code&gt; service starts before the &lt;code&gt;backend&lt;/code&gt; service starts.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;frontend service&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;frontend&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sagar4321/demo-web&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;SERVER_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://0.0.0.0:3001&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;8080:8080&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Use a similar style of definition and configuration for the &lt;code&gt;frontend&lt;/code&gt; service with &lt;code&gt;image: sagar4321/demo-web&lt;/code&gt; (which I built and pushed to docker hub), &lt;code&gt;environment&lt;/code&gt; and &lt;code&gt;port 8080&lt;/code&gt; (where the &lt;code&gt;frontend&lt;/code&gt; service listen).&lt;br&gt;
 But here the &lt;code&gt;frontend&lt;/code&gt; service depends on the &lt;code&gt;backend&lt;/code&gt; service since it needs to be started before the &lt;code&gt;frontend&lt;/code&gt; service.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;phpmyadmin service&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;phpmyadmin&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;phpmyadmin/phpmyadmin&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;PMA_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;database&lt;/span&gt;
      &lt;span class="na"&gt;PMA_PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3306&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8081:80"&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;database&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Also, the same thing applies to defining and configuring the &lt;code&gt;phpmyadmin&lt;/code&gt; service. It also depends on the &lt;code&gt;database&lt;/code&gt; service, and listens to &lt;code&gt;port:8081&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now the overall &lt;code&gt;compose.yml&lt;/code&gt; file after combining all the services together looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3.8"&lt;/span&gt;

&lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;database&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;mysql&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
      &lt;span class="na"&gt;MYSQL_DATABASE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;demodb&lt;/span&gt;
    &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;./testdump.sql:/docker-entrypoint-initdb.d/testdump.sql&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;

  &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sagar4321/demo-server&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3001&lt;/span&gt;
      &lt;span class="na"&gt;DBHOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;database&lt;/span&gt;
      &lt;span class="na"&gt;DBPORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3306&lt;/span&gt;
      &lt;span class="na"&gt;DBUSER&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
      &lt;span class="na"&gt;DBNAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;demodb&lt;/span&gt;
      &lt;span class="na"&gt;DBPASSWORD&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;root&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;3001:3001"&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;database&lt;/span&gt;

  &lt;span class="na"&gt;web&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sagar4321/demo-web&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;SERVER_URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://0.0.0.0:3001&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;8080:8080&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;server&lt;/span&gt;

  &lt;span class="na"&gt;phpmyadmin&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;depends_on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;database&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;phpmyadmin/phpmyadmin&lt;/span&gt;
    &lt;span class="na"&gt;restart&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;
    &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;PMA_HOST&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;database&lt;/span&gt;
      &lt;span class="na"&gt;PMA_PORT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3306&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8081:80"&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Yes, we have finally completed setting up our required services for our application through the compose file &lt;code&gt;compose.yml&lt;/code&gt;&lt;br&gt;
Now all it takes is the following command to run the whole group of services in multiple containers and get our application running.&lt;br&gt;
From the directory &lt;code&gt;dockercompose&lt;/code&gt; in the terminal just run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;docker compose -f compose.yml up
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command starts up all the services running together. Just wait a while so that all those services get up and running, then we can&lt;br&gt;
see our application running in the browser. You can see different logs provided by different services in the console.&lt;/p&gt;

&lt;p&gt;After a while we can access our &lt;code&gt;frontend&lt;/code&gt; in our localhost which is running in port &lt;code&gt;8080&lt;/code&gt;. Accessing the &lt;code&gt;frontend&lt;/code&gt; service shows the list of users&lt;br&gt;
that we created in the database. The &lt;code&gt;frontend&lt;/code&gt; service makes a request to the &lt;code&gt;backend&lt;/code&gt; service. The &lt;code&gt;backend&lt;/code&gt; service gets data from the &lt;code&gt;database&lt;/code&gt; and&lt;br&gt;
the data is returned to the &lt;code&gt;frontend&lt;/code&gt; service which is rendered in the User Interface. This is how multiple services running in different containers can collaborate&lt;br&gt;
with each other through configuration using docker compose. There are lots of thing we can do through docker compose but this is just the basics of it.&lt;/p&gt;

&lt;p&gt;The application page you get should be something like this in the browser &lt;a href="http://localhost:8080:"&gt;http://localhost:8080:&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4o0ufop8n6b54ut12qsc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4o0ufop8n6b54ut12qsc.png" alt="Image description" width="410" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that's all, I hope this blog was a useful for you on how we can run multiple services in multiple docker containers of an application using one docker compose file.&lt;/p&gt;

</description>
      <category>docker</category>
      <category>services</category>
      <category>containers</category>
      <category>dockercompose</category>
    </item>
    <item>
      <title>E2E Testing using TestCafe</title>
      <dc:creator>Sagar Gurung</dc:creator>
      <pubDate>Wed, 30 Nov 2022 04:18:32 +0000</pubDate>
      <link>https://dev.to/jankaritech/e2e-testing-using-testcafe-17if</link>
      <guid>https://dev.to/jankaritech/e2e-testing-using-testcafe-17if</guid>
      <description>&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;p&gt;Are you one of those who is still struggling to write your first End-to-End (E2E) test for your web application?&lt;/p&gt;

&lt;p&gt;So what may be the reasons that you are struggling?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;difficult to set up test framework with your web application?&lt;/li&gt;
&lt;li&gt;difficult to learn?&lt;/li&gt;
&lt;li&gt;lengthy implementation of code?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the above points are exactly of your concern then &lt;code&gt;test-cafe&lt;/code&gt; can be your go-to test automation framework for testing your web application.&lt;/p&gt;

&lt;p&gt;In this blog post, we will look into the concept of &lt;code&gt;test-cafe&lt;/code&gt;, a modern solution to sort out E2E testing for your web application. At the end of this blog hopefully, you will be able to set up &lt;code&gt;test-cafe&lt;/code&gt; for your web application and run your first end-to-end test.&lt;/p&gt;

&lt;h2&gt;
  
  
  Brief about TestCafe
&lt;/h2&gt;

&lt;p&gt;Let's start this blog with a brief understanding of &lt;code&gt;test-cafe&lt;/code&gt;. It is an open-source test automation framework or tool built with Node Js. This framework basically supports two programming languages i.e Javascript and Typescript. So you are required to have at least the basics of Javascript to use this tool. &lt;a href="https://www.devexpress.com/"&gt;DevExpress&lt;/a&gt; is in charge of managing TestCafe, which is made available under an open-source MIT license.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why to use TestCafe?
&lt;/h2&gt;

&lt;p&gt;Before moving to installation and set-up, lets understand some points why to use &lt;code&gt;test-cafe&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It is very easy to set up&lt;/li&gt;
&lt;li&gt;No dependencies (with other libraries)&lt;/li&gt;
&lt;li&gt;Writing tests is easy and with less code&lt;/li&gt;
&lt;li&gt;Cross-browser testing is made easy&lt;/li&gt;
&lt;li&gt;Free and Open Source&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Note: I will be doing the whole setup with Ubuntu 20.04.3 LTS, but it will be similar for other OS too&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;At first, we need &lt;code&gt;Node JS&lt;/code&gt; installed into our system. You can download &lt;code&gt;Node JS&lt;/code&gt; version 12 or above. &lt;a href="https://nodejs.org/en/download/"&gt;Download Node JS&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation and setup
&lt;/h2&gt;

&lt;p&gt;Now lets move into installing &lt;code&gt;test-cafe&lt;/code&gt; which is really easy. Follow the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a folder &lt;code&gt;E2EWithTestCafe&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Open the folder you created with a code editor. In my case I am using &lt;code&gt;Visual Studio Code&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Create a &lt;code&gt;package.json&lt;/code&gt; file with command &lt;code&gt;npm init&lt;/code&gt; through command line. (using terminal)&lt;/li&gt;
&lt;li&gt;Now use &lt;code&gt;npm install testcafe&lt;/code&gt; command to install TestCafe.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After this, your &lt;code&gt;package.json&lt;/code&gt; file should contain &lt;code&gt;dependencies&lt;/code&gt; as&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;file&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nl"&gt;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"testcafe"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^2.1.0"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What to test?
&lt;/h2&gt;

&lt;p&gt;For this blog, we will be writing an E2E test for this &lt;code&gt;https://devexpress.github.io/testcafe/example&lt;/code&gt; website (provided by devexpress). You can go to this website and check what it looks like. We will automate a simple form submit scenario using &lt;code&gt;test-cafe&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Writing Test
&lt;/h2&gt;

&lt;p&gt;At first inside &lt;code&gt;E2EWithTestCafe&lt;/code&gt; project, make your file structure as&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📦tests
┗ 📂e2e
  ┣ 📂fixtures
    ┗ 📜firste2etest.js

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

&lt;/div&gt;



&lt;p&gt;And then at the root level of your project which is &lt;code&gt;E2EWithTestCafe&lt;/code&gt; create a file &lt;code&gt;.testcaferc.json&lt;/code&gt;. This file includes all the configuration required to test the application.&lt;/p&gt;

&lt;p&gt;The configuration should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;testcaferc.json&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"browsers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chrome"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;means&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;will&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;be&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;automated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;chrome&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;browser&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"baseUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://devexpress.github.io/testcafe/example/"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;URL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;web&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;application&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;be&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;tested&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;automated&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tests/e2e/fixtures/firste2etest.js"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;test&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;code&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;execute&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I assume that you have checked &lt;code&gt;https://devexpress.github.io/testcafe/example&lt;/code&gt; website. On that website, if we fill up the username and submit the form, it redirects us to another page saying thank you. So this will be our simple test case, and we will be automating it with &lt;code&gt;test-cafe&lt;/code&gt;&lt;br&gt;
I have implemented the test code And it looks like this.&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="c1"&gt;// firste2etest.js&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Selector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;testcafe&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;fixture&lt;/span&gt;&lt;span class="s2"&gt;`My First E2E test with test-cafe`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;page&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;inputNameFieldSelector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Selector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#developer-name&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;submitButtonSelector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Selector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#submit-button&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;headingSelector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Selector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;#article-header&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Submitting a form should browse to thank you page&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="nx"&gt;t&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;yourName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;JankariTech&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c1"&gt;// fills name input field&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;typeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputNameFieldSelector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;yourName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// clicks the submit button&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;submitButtonSelector&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// check for the thankyou page after form has been submitted with name&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;actualThankyouMessage&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;headingSelector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Thank you, &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;yourName&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;eql&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;actualThankyouMessage&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;I will not be explaining the whole implementation but I have put comments on each action in the code. And probably the code is easy to understand which is exactly what &lt;code&gt;test-cafe&lt;/code&gt; has aimed for.&lt;/p&gt;

&lt;h2&gt;
  
  
  Running Test
&lt;/h2&gt;

&lt;p&gt;Huh, now finally the time has come to run our test script and see it magically running. To run our test we need some adjustments in the &lt;code&gt;package.json&lt;/code&gt; file. Put the test scripts as&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;package.json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;file&lt;/span&gt;&lt;span class="w"&gt;

 &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"test"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"testcafe"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now one final command needed to run our test i.e.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-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;With the above command being executed, you should see the browser (chrome) automating the actions that we have implemented. (submitting a form with a name that redirects to Thank You page)&lt;/p&gt;

&lt;p&gt;And your output in the console should look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;❯ npm run test

&lt;/span&gt;&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;e2ewithtestcafe@1.0.0 &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;span class="gp"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;testcafe
&lt;span class="go"&gt;
 Running tests in:
 - Chrome 105.0.0.0 / Ubuntu 20.04

 My First E2E test with test-cafe
 ✓ Submitting a form should browse to thank you page


 1 passed (8s)

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;So far I have used &lt;code&gt;test-cafe&lt;/code&gt;, it is definitely a go-to automation tool for modern web End-To-End testing.&lt;br&gt;
You can use it on your own project quickly with ease and less code. Also, it has many more features to explore. You can start exploring &lt;a href="https://testcafe.io/"&gt;test-cafe&lt;/a&gt; now.&lt;/p&gt;

</description>
      <category>testcafe</category>
      <category>testing</category>
      <category>javascript</category>
      <category>automation</category>
    </item>
  </channel>
</rss>
