Nigel  Uys

Nigel Uys

1652091240

Jet: Jet Template Engine

Jet Template Engine for Go  

Jet is a template engine developed to be easy to use, powerful, dynamic, yet secure and very fast.

  • simple and familiar syntax
  • supports template inheritance (extends) and composition (block/yield, import, include)
  • descriptive error messages with filename and line number
  • auto-escaping
  • simple C-like expressions
  • very fast execution – Jet can execute templates faster than some pre-compiled template engines
  • very light in terms of allocations and memory footprint

v6

Version 6 brings major improvements to the Go API. Make sure to read through the breaking changes before making the jump.

Docs

Example application

An example to-do application is available in examples/todos. Clone the repository, then (in the repository root) do:

  $ cd examples/todos; go run main.go

IntelliJ Plugin

If you use IntelliJ there is a plugin available at https://github.com/jhsx/GoJetPlugin. There is also a very good Go plugin for IntelliJ – see https://github.com/go-lang-plugin-org/go-lang-idea-plugin. GoJetPlugin + Go-lang-idea-plugin = happiness!

Contributing

All contributions are welcome – if you find a bug please report it.

Contributors

  • José Santos (@jhsx)
  • Daniel Lohse (@annismckenzie)
  • Alexander Willing (@sauerbraten)

Author: CloudyKit
Source Code: https://github.com/CloudyKit/jet 
License: Apache-2.0 license

#go #golang #jet 

Jet: Jet Template Engine

Jet Bridge: Admin Panel Framework for Your Application

For Jet Admin – Admin panel framework for your application

Preview

Description

Jet Admin is a SaaS service that automatically generates extendable back office for your application. 
Jet Bridge is a standalone app which generates REST API thought which your SQL database is connected to Jet Admin
This project has been designed to fit requirements of small startups and mature companies.

  • Data Privacy. Jet does not access your data: its transferred directly from browser to your application.
  • Customizable Interface. With WYSIWYG interface customization your can change almost every part of interface.
  • Extendable. Flex Features allows you to create your custom Actions, Views, Fields and other.
  • Works with any technology. The interface is generated automatically based on an analysis of the data and data structure of your database.
  • Quick installation. All you need is to install Jet Bridge and connect it to your database.

This is a complete remake of our popular Django Jet admin interface.

Features

CRUD (create, read, update, delete)

All common operations to view, create, update or delete data.

  • CRUD (create, read, update, delete)

Search and Filter

Filter data easily by any field with most common lookups and search them by text occurrence. For some specific cases you can create SQL Segment to filter with.

  • Search and Filter

Segments

Segments allow you to save applied set of filters as a Segment or create it from SQL query for quick use in future.

  • Segments

WYSIWYG Interface Customization

You can customize almost every part of interface visually – navigation menu, collection list views, record create/update forms.

  • WYSIWYG Interface Customization

List View layout

A number of out-of-the-box list layouts except default Table View like Kanban Board and Map with markers.

  • List View layout

Dashboards

Create different types of charts, tables and other widgets to visualize your KPIs or monitor data without programming – inside your visual interface. Complex data queries can be created with SQL.

  • Dashboards

Teams and Permissions

Invite users to collaborate on a project and assign access rights based on their team.

  • Teams and Permissions

Export

You can export all collection data or part of it into the most common formats like CSV or Excel.

  • Export

Responsive Layout

The interface is optimized for any device from phones to tablets to desktops.

Extendability

While we are trying to include most of important features out of the box sometimes its not enough. For any specific cases we offer Flex features to implement functionality not available with standard features:

Custom Views

For very specific pages you can create your own custom FlexView based on React, Angular or any other framework and integrate it in Jet Admin interface. Writing your own custom JS/CSS/HTML has no limits in implementing any page you need.

Custom Actions

If need to run some operations on records or any other business logic inside your Backend you can create FlexActions and run them directly from Jet Admin interface. Passing some additional parameters to your Backend is supported.

Custom Fields

Sometimes you may want custom fields that are a combination of multiple fields, use fields from related collections, or are the result of some calculation. In this case you can use FlexField and write a custom JavaScript function to format fields data in any way you want.

How It Works

Jet Admin is a SaaS frontend application hosted on Jet Admin side that works in your browser. It connects to your project SQL database through open source Jet Bridge backend application which you install on your side. So Integrating Jet Admin with your project requires installing only one component - Jet Bridge. Here how it should look like after installation:

Jet Admin architecture

Your App

Any of your applications which works with your Database. Jet Admin does not interact with it directly.

Database

Your database Jet Admin has no direct access to.

Jet Bridge

An open source application installed on your server's side and connected to your database. It automatically generates REST API based on your database structure. Jet Interface works with Database through Jet Bridge.

Jet Interface

Web application accessible from any browser. Maintaining and updating of this web application is on Jet Admin team side. Your application data is transmitted directly from Jet Bridge to Jet Interface in your browser and remain invisible for the Jet Admin service.

Requirements

Python 2.7 or 3.4+

Any of the following SQL Databases:

  • PostgreSQL
  • MySQL
  • SQLite
  • Oracle
  • Microsoft SQL Server
  • Firebird
  • Sybase

Installation

In order to install Jet Admin on your project please follow this guide:
https://app.jetadmin.io/projects/create

If you don't have Jet account yet you will be asked to create one and sign in with the existing account.

After registering your project you will be redirected to your project and can start working with Jet

Author: jet-admin
Source Code: https://github.com/jet-admin/jet-bridge
License: MIT License

#jet #python 

Jet Bridge: Admin Panel Framework for Your Application
Chris  Miller

Chris Miller

1638592080

How to Add Hotspot icons with any image in Elementor

In this tutorial I will show you how to add hotspot icon with any image in Elementor. For this tutorial I will use jet tricks plugin and Elementor.

Jettricks Plugin- https://farjana-rashid.com/jettricks
Check Crocoblock - https://farjana-rashid.com/crocoblockpeatewebsitelikeapro/

#elementor #jet 

How to Add Hotspot icons with any image in Elementor
Chris  Miller

Chris Miller

1638577380

Jet Tricks Tutorial: Unfold anything in Elementor

In this tutorial I will show you how to expand any text or any section with button click. For this tutorial I will use jettricks plugin and Elementor.

Jettricks Plugin- https://farjana-rashid.com/jettricks
Check Crocoblock - https://farjana-rashid.com/crocoblockp

#elementor #jet 

Jet Tricks Tutorial: Unfold anything in Elementor
Elyna Ezza

Elyna Ezza

1631514758

#GAMEJET 100X NFT $JET TOKEN PRESALE COMING SOON!

Don't Missed it Big opportunity Join the next #100x Gaming Coin #gamejet  $Jet Token
Listing: #justswap  and Other More Exchanges
Follow: https://twitter.com/gamejetpro
Register : https://gamejet.network/register/JET1625857428
Telegram: https://t.me/GamejetNetwork
#jet  #trx  #blockchain  #Tron  #bsc  #btt  #nft  #presale 

   #GAMEJET 100X NFT $JET TOKEN PRESALE COMING SOON!

sara jacob

1602826887

Mind Capital Opiniones 2020?

With the rise of cryptocurrencies, many people in 2020 have started investing these assets.
And the vast majority use platforms like Mind Capital to make their cryptocurrencies profitable.
Do you want to know what their opinions are about Mind Capital?
In this article we will talk about Mind Capital and the opinions it has generated in 2020.

To know more visit:https://www.jetmining.website/?referral=199561

Domain Name: Jetmining.website

Description: JetMining Bitcoin Mining Pool is trusted online Cloud Mining Company that provides bitcoin mining/Hashing service. The highest paying Bitcoin Cloud mining pool 2018 - jetmining.website

Investment Plan :

GET 0.01 BTC For
V 1.0
BTC / Minute: 0.0000020
BTC / Day: 0.00288
Affiliate Bonus: 30%

GET 0.01 BTC For
V 2.0
BTC / Minute: 0.0000210
BTC / Day: 0.03024
Affiliate Bonus: 40%

GET 0.05 BTC For
V 3.0
BTC / Minute: 0.0002100
BTC / Day: 0.30240
Affiliate Bonus: 50%

GET 2.99 BTC For
V 4.0
BTC / Minute: 0.0012600
BTC / Day: 1.8144
Affiliate Bonus: 100%

Features :
Min / Max: $ 1 / $ 250,000
Referral: 5-3-1%
Withdrawal: Manual

Legend (original):

We are a specialized team of experts involved in the sale of cryptocurrencies as we provide you with the best rate available. We make use of modern algorithms to offer you excellent service. Our professional brokers go out of their way to provide you with exceptional customer service. Personal information given on our site is 100% secure as we have devised an encrypted method to secure sensitive data. With several years of experience in the field of cryptocurrency and investments, you are rest assured of the best deals. We are available around 24/7, and your profit is accrued every hour!

Machine translate:

We are a dedicated team of cryptocurrency trading experts as we provide you with the best prices. We use state of the art algorithms to offer you a great service. Our professional brokers go out of their way to provide you with exceptional customer service. Personal information provided on our website is 100% secure, we have developed an encrypted way to protect confidential data. With years of experience in cryptocurrency and investment, you can be sure of the best deals. We are available 24/7 and your profits are calculated every hour!

I upgrade a mining plan to V2, Mostly participate in an affiliate program to boost my revenue. I suggest my friend, make youtube videos, post on my blog to get maximum referral. Here is am sharing my referral link, Keep in mind this is my hard work to find this legit bitcoin mining website

#jet #mining #bitcoin #cryptocurrency #cryptowallet

Mind Capital Opiniones 2020?
Wissam Muneer

Wissam Muneer

1584074884

Test React Apps with React Testing Library and Jest

Testing is often seen as a tedious process. It’s extra code you have to write, and in some cases, to be honest, it’s not needed. But every developer should know at least the basics of testing. It increases confidence in the products they build, and for most companies, it’s a requirement.

In the React world, there is an amazing library called the react-testing-library which helps you test your React Apps more efficiently. You use it with Jest.

In this article, we will see the 8 simple steps you can take to start testing your React Apps like a boss.

  • Prerequisites
  • Basics
  • What is React Testing Library?
  • 1. How to create a test snapshot?
  • 2. Testing DOM elements
  • 3. Testing events
  • 4. Testing asynchronous actions
  • 5. Testing React Redux
  • 6. Testing React Context
  • 7. Testing React Router
  • 8. Testing HTTP Request
  • Final Thoughts

Prerequisites

This tutorial assumes that you have at least a basic understanding of React. I will focus only on the testing part.

And to follow along, you have to clone the project by running in your terminal:

  git clone https://github.com/ibrahima92/prep-react-testing-library-guide

Next, run:

  yarn

Or, if you use NPM:

npm install

And that’s it! Now let’s dive into some basics.

Basics

Some key things will be used a lot in this article, and understanding their role can help you with your understanding.

it or test: describes the test itself. It takes as parameters the name of the test and a function that holds the tests.

expect: the condition that the test needs to pass. It will compare the received parameter to a matcher.

a matcher: a function that is applied to the expected condition.

render: the method used to render a given component.

import React from 'react'
import {render} from '@testing-library/react'
import App from './App'

 it('should take a snapshot', () => {
    const { asFragment } = render(<App />)

    expect(asFragment(<App />)).toMatchSnapshot()
   })
});

As you can see, we describe the test with it, then, use render to display the App component and expect that asFragment(<App />) matches toMatchSnapshot() (the matcher provided by jest-dom).

By the way, the render method returns several methods we can use to test our features. We also used destructuring to get the method.

That being said, let’s move on and learn more about the React Testing Library in the next section.

What is the React Testing Library?

The React Testing Library is a very light-weight package created by Kent C. Dodds. It’s a replacement for Enzyme and provides light utility functions on top of react-dom and react-dom/test-utils.

The React Testing Library is a DOM testing library, which means that instead of dealing with instances of rendered React components, it handles DOM elements and how they behave in front of real users.

It’s a great library, it’s (relatively) easy to start using, and it encourages good testing practices. Note – you can also use it without Jest.

“The more your tests resemble the way your software is used, the more confidence they can give you.”

So, let’s start using it in the next section. By the way, you don’t need to install any packages, since create-react-app comes with the library and its dependencies.

1. How to create a test snapshot

A snapshot, as the name suggests, allows us to save the snapshot of a given component. It helps a lot when you update or do some refactoring, and want to get or compare the changes.

Now, let’s take a snapshot of the App.js file.

  • App.test.js
import React from 'react'
import {render, cleanup} from '@testing-library/react'
import App from './App'

 afterEach(cleanup)

 it('should take a snapshot', () => {
    const { asFragment } = render(<App />)

    expect(asFragment(<App />)).toMatchSnapshot()
   })
});

To take a snapshot, we first have to import render and cleanup. These two methods will be used a lot throughout this article.

render, as you might guess, helps to render a React component. And cleanup is passed as a parameter to afterEach to just clean up everything after each test to avoid memory leaks.

Next, we can render the App component with render and get back asFragment as a returned value from the method. And finally, make sure that the fragment of the App component matches the snapshot.

Now, to run the test, open your terminal and navigate to the root of the project and run the following command:

  yarn test

Or, if you use npm:

  npm test

As a result, it will create a new folder __snapshots__ and a file App.test.js.snap in the src which will look like this:

  • App.test.js.snap
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Take a snapshot should take a snapshot 1`] = `
<DocumentFragment>
  <div class="App">
    <h1>Testing</h1>
  </div>
</DocumentFragment>
`;

And if you make another change in App.js, the test will fail, because the snapshot will no longer match the condition. To make it passes, just press u to update it. And you’ll have the updated snapshot in App.test.js.snap.

Now, let’s move on and start testing our elements.

2. Testing DOM elements

To test our DOM elements, we first have to look at the TestElements.js file.

  • TestElements.js
import React from 'react'

const TestElements = () => {
 const [counter, setCounter] = React.useState(0)

 return (
  <>
    <h1 data-testid="counter">{ counter }</h1>
    <button data-testid="button-up" onClick={() => setCounter(counter + 1)}> Up</button>
    <button disabled data-testid="button-down" onClick={() => setCounter(counter - 1)}>Down</button>
 </>
    )
  }

export default TestElements

Here, the only thing you have to retain is data-testid. It will be used to select these elements from the test file. Now, let’s write the unit test:

Test if the counter is equal to 0:

TestElements.test.js

import React from 'react';
import { render, cleanup } from '@testing-library/react';
import TestElements from './TestElements'

afterEach(cleanup);

  it('should equal to 0', () => {
    const { getByTestId } = render(<TestElements />); 
    expect(getByTestId('counter')).toHaveTextContent(0)
   });

As you can see, the syntax is quite similar to the previous test. The only difference is that we use getByTestId to select the necessary elements (remember the data-testid) and check if it passed the test. In others words, we check if the text content <h1 data-testid="counter">{ counter }</h1> is equal to 0.

Test if the buttons are enabled or disabled:

TestElements.test.js (add the following code block to the file)

   it('should be enabled', () => {
    const { getByTestId } = render(<TestElements />);
    expect(getByTestId('button-up')).not.toHaveAttribute('disabled')
  });

  it('should be disabled', () => {
    const { getByTestId } = render(<TestElements />); 
    expect(getByTestId('button-down')).toBeDisabled()
  });

Here, as usual, we use getByTestId to select elements and check for the first test if the button has a disabled attribute. And for the second, if the button is disabled or not.

And if you save the file or run again in your terminal yarn test, the test will pass.

Congrats! Your first test has passed!

congrats

Now, let’s learn how to test an event in the next section.

3. Testing events

Before writing our unit tests, let’s first check what the TestEvents.js looks like.

  • TestEvents.js
import React from 'react'

const TestEvents = () => {
  const [counter, setCounter] = React.useState(0)

return (
  <>
    <h1 data-testid="counter">{ counter }</h1>
    <button data-testid="button-up" onClick={() => setCounter(counter + 1)}> Up</button>
    <button data-testid="button-down" onClick={() => setCounter(counter - 1)}>Down</button>
 </>
    )
  }

  export default TestEvents

Now, let’s write the tests.

Test if the counter increments and decrements correctly when we click on buttons:

TestEvents.test.js

import React from 'react';
import { render, cleanup, fireEvent } from '@testing-library/react';
import TestEvents from './TestEvents'

  afterEach(cleanup);

  it('increments counter', () => {
    const { getByTestId } = render(<TestEvents />); 

    fireEvent.click(getByTestId('button-up'))

    expect(getByTestId('counter')).toHaveTextContent('1')
  });

  it('decrements counter', () => {
    const { getByTestId } = render(<TestEvents />); 

    fireEvent.click(getByTestId('button-down'))

    expect(getByTestId('counter')).toHaveTextContent('-1')
  });

As you can see, these two tests are very similar except the expected text content.

The first test fires a click event with fireEvent.click() to check if the counter increments to 1 when the button is clicked.

And the second one checks if the counter decrements to -1 when the button is clicked.

fireEvent has several methods you can use to test events, so feel free to dive into the documentation to learn more.

Now that we know how to test events, let’s move on and learn in the next section how to deal with asynchronous actions.

4. Testing asynchronous actions

An asynchronous action is something that can take time to complete. It can be an HTTP request, a timer, and so on.

Now, let’s check the TestAsync.js file.

  • TestAsync.js
import React from 'react'

const TestAsync = () => {
  const [counter, setCounter] = React.useState(0)

  const delayCount = () => (
    setTimeout(() => {
      setCounter(counter + 1)
    }, 500)
  )

return (
  <>
    <h1 data-testid="counter">{ counter }</h1>
    <button data-testid="button-up" onClick={delayCount}> Up</button>
    <button data-testid="button-down" onClick={() => setCounter(counter - 1)}>Down</button>
 </>
    )
  }

  export default TestAsync

Here, we use setTimeout() to delay the incrementing event by 0.5s.

Test if the counter is incremented after 0.5s:

TestAsync.test.js

import React from 'react';
import { render, cleanup, fireEvent, waitForElement } from '@testing-library/react';
import TestAsync from './TestAsync'

afterEach(cleanup);

  it('increments counter after 0.5s', async () => {
    const { getByTestId, getByText } = render(<TestAsync />); 

    fireEvent.click(getByTestId('button-up'))

    const counter = await waitForElement(() => getByText('1')) 

    expect(counter).toHaveTextContent('1')
  });

To test the incrementing event, we first have to use async/await to handle the action because, as I said earlier, it takes time to complete.

Next, we use a new helper method getByText(). This is similar to getByTestId(), except that getByText() selects the text content instead of id or data-testid.

Now, after clicking to the button, we wait for the counter to be incremented with waitForElement(() => getByText('1')). And once the counter incremented to 1, we can now move to the condition and check if the counter is effectively equal to 1.

That being said, let’s now move to more complex test cases.

Are you ready?

ready

5. Testing React Redux

If you’re new to React Redux, this article might help you. Otherwise, let’s check what the TestRedux.js looks like.

  • TestRedux.js
import React from 'react'
import { connect } from 'react-redux'

const TestRedux = ({counter, dispatch}) => {

 const increment = () => dispatch({ type: 'INCREMENT' })
 const decrement = () => dispatch({ type: 'DECREMENT' })

 return (
  <>
    <h1 data-testid="counter">{ counter }</h1>
    <button data-testid="button-up" onClick={increment}>Up</button>
    <button data-testid="button-down" onClick={decrement}>Down</button>
 </>
    )
  }

export default connect(state => ({ counter: state.count }))(TestRedux)

And for the reducer:

  • store/reducer.js
export const initialState = {
    count: 0,
  }

  export function reducer(state = initialState, action) {
    switch (action.type) {
      case 'INCREMENT':
        return {
          count: state.count + 1,
        }
      case 'DECREMENT':
        return {
          count: state.count - 1,
        }
      default:
        return state
    }
  }

As you can see, there is nothing fancy – it’s just a basic Counter Component handled by React Redux.

Now, let’s write the unit tests.

Test if the initial state is equal to 0:

TestRedux.test.js

import React from 'react'
import { createStore } from 'redux'
import { Provider } from 'react-redux'
import { render, cleanup, fireEvent } from '@testing-library/react';
import { initialState, reducer } from '../store/reducer'
import TestRedux from './TestRedux'

const renderWithRedux = (
  component,
  { initialState, store = createStore(reducer, initialState) } = {}
) => {
  return {
    ...render(<Provider store={store}>{component}</Provider>),
    store,
  }
}

 afterEach(cleanup);

it('checks initial state is equal to 0', () => {
    const { getByTestId } = renderWithRedux(<TestRedux />)
    expect(getByTestId('counter')).toHaveTextContent('0')
  })

There are a couple of things we need to import to test React Redux. And here, we create our own helper function renderWithRedux() to render the component since it will be used several times.

renderWithRedux() receives as parameters the component to render, the initial state, and the store. If there is no store, it will create a new one, and if it doesn’t receive an initial state or a store, it returns an empty object.

Next, we use render() to render the component and pass the store to the Provider.

That being said, we can now pass the component TestRedux to renderWithRedux() to test if the counter is equal to 0.

Test if the counter increments and decrements correctly:

TestRedux.test.js (add the following code block to the file)

it('increments the counter through redux', () => {
  const { getByTestId } = renderWithRedux(<TestRedux />, 
    {initialState: {count: 5}
})
  fireEvent.click(getByTestId('button-up'))
  expect(getByTestId('counter')).toHaveTextContent('6')
})

it('decrements the counter through redux', () => {
  const { getByTestId} = renderWithRedux(<TestRedux />, {
    initialState: { count: 100 },
  })
  fireEvent.click(getByTestId('button-down'))
  expect(getByTestId('counter')).toHaveTextContent('99')
})

To test the incrementing and decrementing events, we pass an initial state as a second argument to renderWithRedux(). Now, we can click on the buttons and test if the expected result matches the condition or not.

Now, let’s move to the next section and introduce React Context.

React Router and Axios will come next – are you still with me?

of-course

6. Testing React Context

If you’re new to React Context, check out this article first. Otherwise, let’s check the TextContext.js file.

  • TextContext.js
import React from "react"

export const CounterContext = React.createContext()

const CounterProvider = () => {
  const [counter, setCounter] = React.useState(0)
  const increment = () => setCounter(counter + 1)
  const decrement = () => setCounter(counter - 1)

  return (
    <CounterContext.Provider value={{ counter, increment, decrement }}>
      <Counter />
    </CounterContext.Provider>
  )
}

export const Counter = () => {  
    const { counter, increment, decrement } = React.useContext(CounterContext)   
    return (
     <>
       <h1 data-testid="counter">{ counter }</h1>
       <button data-testid="button-up" onClick={increment}> Up</button>
       <button data-testid="button-down" onClick={decrement}>Down</button>
    </>
       )
}

export default CounterProvider

Now, the counter state is managed through React Context. Let’s write the unit test to check if it behaves as expected.

Test if the initial state is equal to 0:

TextContext.test.js

import React from 'react'
import { render, cleanup,  fireEvent } from '@testing-library/react'
import CounterProvider, { CounterContext, Counter } from './TestContext'

const renderWithContext = (
  component) => {
  return {
    ...render(
        <CounterProvider value={CounterContext}>
            {component}
        </CounterProvider>)
  }
}

afterEach(cleanup);

it('checks if initial state is equal to 0', () => {
    const { getByTestId } = renderWithContext(<Counter />)
    expect(getByTestId('counter')).toHaveTextContent('0')
})

As in the previous section with React Redux, here we use the same approach, by creating a helper function renderWithContext() to render the component. But this time, it receives only the component as a parameter. And to create a new context, we pass CounterContext to the Provider.

Now, we can test if the counter is initially equal to 0 or not.

Test if the counter increments and decrements correctly:

TextContext.test.js (add the following code block to the file)

  it('increments the counter', () => {
    const { getByTestId } = renderWithContext(<Counter />)

    fireEvent.click(getByTestId('button-up'))
    expect(getByTestId('counter')).toHaveTextContent('1')
  })

  it('decrements the counter', () => {
    const { getByTestId} = renderWithContext(<Counter />)

    fireEvent.click(getByTestId('button-down'))
    expect(getByTestId('counter')).toHaveTextContent('-1')
  })

As you can see, here we fire a click event to test if the counter increments correctly to 1 and decrements to -1.

That being said, we can now move to the next section and introduce React Router.

7. Testing React Router

If you want to dive into React Router, this article might help you. Otherwise, let’s check the TestRouter.js file.

  • TestRouter.js
import React from 'react'
import { Link, Route, Switch,  useParams } from 'react-router-dom'

const About = () => <h1>About page</h1>

const Home = () => <h1>Home page</h1>

const Contact = () => {
  const { name } = useParams()
  return <h1 data-testid="contact-name">{name}</h1>
}

const TestRouter = () => {
    const name = 'John Doe'
    return (
    <>
    <nav data-testid="navbar">
      <Link data-testid="home-link" to="/">Home</Link>
      <Link data-testid="about-link" to="/about">About</Link>
      <Link data-testid="contact-link" to={`/contact/${name}`}>Contact</Link>
    </nav>

      <Switch>
        <Route exact path="/" component={Home} />
        <Route path="/about" component={About} />
        <Route path="/about:name" component={Contact} />
      </Switch>
    </>
  )
}

export default TestRouter

Here, we have some components to render when navigating the Home page.

Now, let’s write the tests:

  • TestRouter.test.js
import React from 'react'
import { Router } from 'react-router-dom'
import { render, fireEvent } from '@testing-library/react'
import { createMemoryHistory } from 'history'
import TestRouter from './TestRouter'

const renderWithRouter = (component) => {
    const history = createMemoryHistory()
    return { 
    ...render (
    <Router history={history}>
        {component}
    </Router>
    )
  }
}

it('should render the home page', () => {

  const { container, getByTestId } = renderWithRouter(<TestRouter />) 
  const navbar = getByTestId('navbar')
  const link = getByTestId('home-link')

  expect(container.innerHTML).toMatch('Home page')
  expect(navbar).toContainElement(link)
})

To test React Router, we have to first have a navigation history to start with. Therefore we use createMemoryHistory() to well as the name guessed to create a navigation history.

Next, we use our helper function renderWithRouter() to render the component and pass history to the Router component. With that, we can now test if the page loaded at the start is the Home page or not. And if the navigation bar is loaded with the expected links.

Test if it navigates to other pages with the parameters when we click on links:

TestRouter.test.js (add the following code block to the file)

it('should navigate to the about page', ()=> {
  const { container, getByTestId } = renderWithRouter(<TestRouter />) 

  fireEvent.click(getByTestId('about-link'))

  expect(container.innerHTML).toMatch('About page')
})

it('should navigate to the contact page with the params', ()=> {
  const { container, getByTestId } = renderWithRouter(<TestRouter />) 

  fireEvent.click(getByTestId('contact-link'))

  expect(container.innerHTML).toMatch('John Doe')
})

Now, to check if the navigation works, we have to fire a click event on the navigation links.

For the first test, we check if the content is equal to the text in the About Page, and for the second, we test the routing params and check if it passed correctly.

We can now move to the final section and learn how to test an Axios request.

We’re almost done!

still-here

8. Testing HTTP Request

As usual, let’s first see what the TextAxios.js file looks like.

  • TextAxios.js
import React from 'react'
import axios from 'axios'

const TestAxios = ({ url }) => {
  const [data, setData] = React.useState()

  const fetchData = async () => {
    const response = await axios.get(url)
    setData(response.data.greeting)    
 }     

 return (
  <>
    <button onClick={fetchData} data-testid="fetch-data">Load Data</button>
    { 
    data ?
    <div data-testid="show-data">{data}</div>:
    <h1 data-testid="loading">Loading...</h1>
    }
  </>
     )
}

export default TestAxios

As you can see here, we have a simple component that has a button to make a request. And if the data is not available, it will display a loading message.

Now, let’s write the tests.

Test if the data are fetched and displayed correctly:

TextAxios.test.js

import React from 'react'
import { render, waitForElement, fireEvent } from '@testing-library/react'
import axiosMock from 'axios'
import TestAxios from './TestAxios'

jest.mock('axios')

it('should display a loading text', () => {

 const { getByTestId } = render(<TestAxios />)

  expect(getByTestId('loading')).toHaveTextContent('Loading...')
})

it('should load and display the data', async () => {
  const url = '/greeting'
  const { getByTestId } = render(<TestAxios url={url} />)

  axiosMock.get.mockResolvedValueOnce({
    data: { greeting: 'hello there' },
  })

  fireEvent.click(getByTestId('fetch-data'))

  const greetingData = await waitForElement(() => getByTestId('show-data'))

  expect(axiosMock.get).toHaveBeenCalledTimes(1)
  expect(axiosMock.get).toHaveBeenCalledWith(url)
  expect(greetingData).toHaveTextContent('hello there')
})

This test case is a bit different because we have to deal with an HTTP request. And to do that, we have to mock an axios request with the help of jest.mock('axios').

Now, we can use axiosMock and apply a get() method to it. Finally we will use the Jest function mockResolvedValueOnce() to pass the mocked data as a parameter.

With that, now for the second test we can click to the button to fetch the data and use async/await to resolve it. And now we have to test 3 things:

  1. If the HTTP request has been done correctly
  2. If the HTTP request has been done with the url
  3. If the data fetched matches the expectation.

And for the first test, we just check if the loading message is displayed when we have no data to show.

That being said, we’re now done with the 8 simple steps to start testing your React Apps.

Don’t be scared to test anymore.

not-scared

Final Thoughts

The React Testing Library is a great package for testing React Apps. It gives us access to jest-dom matchers we can use to test our components more efficiently and with good practices. Hopefully this article was useful, and it will help you build robust React apps in the future.

You can find the finished project here

Thanks for reading it!

Originally published by Ibrahima Ndaw at https://www.freecodecamp.org

#reactjs #testing #jet #redux #webdev

Test React Apps with React Testing Library and Jest