Skip to content
This repository has been archived by the owner on Feb 12, 2024. It is now read-only.

Commit

Permalink
Feature/tests (#123)
Browse files Browse the repository at this point in the history
Setup the testing framework for fadi.

Add automated testing of the services using Jest and Puppeteer, test cases and scenarios specifications and implementation.

Co-authored-by: Faiez Zalila <[email protected]>
Co-authored-by: Rami Sellami <[email protected]>
Co-authored-by: Sebastien Dupont <[email protected]>
  • Loading branch information
4 people authored Jun 22, 2020
1 parent 04a6653 commit 9aaf46b
Show file tree
Hide file tree
Showing 49 changed files with 5,952 additions and 1 deletion.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,6 @@ teardown.log
*.tgz

# https://github.com/ekalinin/github-markdown-toc
gh-md-toc
gh-md-toc

.vscode
12 changes: 12 additions & 0 deletions .gitlab-ci.sample.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ stages:
- tf_plan
- tf_apply
- deployWithHelm
- test

variables:
KUBECONFIG: /etc/deploy/config
Expand Down Expand Up @@ -132,3 +133,14 @@ deployWithHelm:
url: http://$PROJECT
only:
- master

test:
stage: test
image: ceticasbl/puppeteer-jest
script:
- cd tests/
- npm run test
tags:
- docker
only:
- develop
1 change: 1 addition & 0 deletions doc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ FADI Documentation
* [Users management](USERMANAGEMENT.md) - user identification and authorization (LDAP, RBAC, ...)
* [Reverse proxy](REVERSEPROXY.md) - Traefik reverse proxy configuration
* [Security](SECURITY.md) - SSL setup
* [Testing](/tests/README.md) - tests for the FADI framework
* [TSimulus](TSIMULUS.md) - how to simulate sensors and generate realistic data with [TSimulus](https://github.com/cetic/TSimulus)
* [Sample self-hosted infrastructure](RANCHER_PROXMOX.md) - How to install FADI on a self hosted infrastructure using
* [Proxmox](https://www.proxmox.com/en/) as a self-hosted private cloud (IaaS) provider. It provides virtual machines for the various Kubernetes nodes.
Expand Down
9 changes: 9 additions & 0 deletions tests/.prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"semi": false,
"singleQuote": true,
"useTabs": true,
"tabWidth": 2,
"bracketSpacing": true,
"arrowParens": "avoid",
"trailingComma": "es5"
}
106 changes: 106 additions & 0 deletions tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Testing the FADI framework

<img src="https://miro.medium.com/max/1788/1*wby6AkTf3SggijT3GSTu4w.png" height="100" align="right" alt="Jest Puppeteer">

[![implemented with puppeteer](https://img.shields.io/badge/implemented%20with-puppeteer-%2300D8A2)](https://pptr.dev) [![tested with jest](https://img.shields.io/badge/tested_with-jest-99424f.svg)](https://github.com/facebook/jest)

* [Introduction](#introduction)
* [Quick start](#quick-start)
* [Example](#examples)
* [Documentation](#documentation)
* [References](#references)

## Introduction

The FADI framework is tested using Puppeteer and Jest.

[Puppeteer](https://pptr.dev) is a Node library which provides a high-level API to control Chrome or Chromium over the DevTools Protocol. Puppeteer runs headless by default, but can be configured to run full (non-headless) Chrome or Chromium.

[Jest](https://jestjs.io) is a JavaScript Testing Framework with a focus on simplicity. It works with projects using: Babel, TypeScript, Node, React, Angular, Vue and more!

## Quick start

To test the FADI framework, you need to implement the following instructions:

1. Install FADI framework. Refer to [the INSTALL section](../INSTALL.md).
2. Create a Docker container using [the Puppeteer-Jest Docker image](https://hub.docker.com/repository/docker/fzalila/docker-puppeteer-jest). To achieve that, run the following command:

```bash
docker container run --name testing-fadi fzalila/docker-puppeteer-jest:latest
```

3. Inside the created container, clone the FADI repository:

```bash
git clone https://github.com/cetic/fadi.git
```

4. Configure [here](./lib/config.js) the urls and paths of different FADI platform services

5. Go to the `tests` folder and launch the tests:

```bash
cd fadi/tests
npm run test
```

If tests pass, you should obtain the following results:

<img src="doc/images/test_results.png" height="500" alt="Tests results" />

## Examples

The following example checks the creation of a `example_basic` table in the `postgres` database.

```js
it('should create a table', async () => {
// Go to the indicated page
await page.goto(url)

// Click on SQL query button
await click(page, '.ltr > #menu > .links > a:nth-child(1)')

// type the query
await typeText(page, 'CREATE TABLE example_basic (measure_ts TIMESTAMP NOT NULL,temperature FLOAT (50));', '.ltr > #content > #form > p > .jush')

// Execute the table creation query
await click(page, '.ltr > #content > #form > p > input:nth-child(1)')

// Check the creation of the table
await shouldExist(page, '#content > p.message')
})
```

More examples are available in the [test-scripts folder](doc/test-scripts/).

## Documentation

Test cases of the FADI framework are specified using Cockburns[[1](#references)] templates, available [here](doc/Cockburns-specification.md).

Test scripts specifications are available [here](doc/Test-scripts-specifications.md).

Two templates are available in order to define a new [test case](doc/cockburns/TC-template.md) and a new [test script](doc/test-scripts/TS-template.md).

## Continuous integration

To automate testing inside a continuous integration process, you can for example add a `test` stage to a Gitlab-CI pipeline by editing the [`.gitlab-ci.yml`](../.gitlab-ci.sample.yml) configuration:

```yaml
stages:
- deployWithHelm
- test

deployWithHelm:
[...]

test:
stage: test
image: ceticasbl/puppeteer-jest
script:
- cd tests/
- npm run test
```
## References
[1] Alistair Cockburn. 2000. Writing Effective Use Cases (1st. ed.). Addison-Wesley Longman Publishing Co., Inc., USA.
9 changes: 9 additions & 0 deletions tests/TestSequencer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const TestSequencer = require('@jest/test-sequencer').default;

class CustomSequencer extends TestSequencer {
sort(tests) {
const copyTests = Array.from(tests);
return copyTests.sort((testA, testB) => (testA.path > testB.path ? 1 : -1));
}}

module.exports = CustomSequencer;
96 changes: 96 additions & 0 deletions tests/__tests__/1-adminer.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
const puppeteer = require('puppeteer')
const jestpkg = require('jest')
const config = require('../lib/config')
const click = require('../lib/helpers').click
const typeText = require('../lib/helpers').typeText
const loadUrl = require('../lib/helpers').loadUrl
const waitForText = require('../lib/helpers').waitForText
const pressKey = require('../lib/helpers').pressKey
const shouldExist = require('../lib/helpers').shouldExist
const shouldNotExist = require('../lib/helpers').shouldNotExist
const dragAndDrop = require('../lib/helpers').dragAndDrop
const Sequencer = require('@jest/test-sequencer').default

const url = config.AdminerUrl
//const utils = require('../lib/utils')

describe('Test the authentification to the Adminer service', () => {
/** @type {puppeteer.Browser} */
let browser

/** @type {puppeteer.Page} */
let page

beforeAll(async function () {
browser = await puppeteer.launch({
headless: config.isHeadless,
slowMo: config.slowMo,
devtools: config.isDevtools,
timeout: config.launchTimeout,
args: ['--no-sandbox']
})
page = await browser.newPage()
await page.setDefaultNavigationTimeout(config.waitingTimeout) //10 seconds is the industry standard
await page.setViewport({
width: config.viewportWidth,
height: config.viewportHeight
})
})
afterAll(async function () {
await browser.close()
})
it('should success the authentification process', async () => {
// Go to the indicated page
await page.goto(url)

// Click on the DBMS list
await click(page, '.layout > tbody > tr > td > select')

// Select the postgresql DBMS
await page.select('.layout > tbody > tr > td > select', 'pgsql')

// Empty the server value content (usually 'db')
await page.evaluate(() => document.querySelector(".layout > tbody > tr:nth-child(2) > td > input").value = "")

// Insert the server name fadi-postgresql
await typeText(page, 'fadi-postgresql', ".layout > tbody > tr:nth-child(2) > td > input")

// Insert the user
await typeText(page, 'admin', '.layout #username')

// Insert password
await typeText(page, 'password1', '.layout > tbody > tr:nth-child(4) > td > input')

// insert the db name
await typeText(page, 'postgres', '.layout > tbody > tr:nth-child(5) > td > input')

// Click on the authentification
await click(page, '.ltr > #content > form > p > input')

await page.waitFor(6000)

// Check access to the authentification page
const selector = await page.$('#content > h2')
const text = await page.evaluate(selector => selector.textContent, selector);
const result = text.includes('public')
//console.log(text.includes('public'))
expect(result).toBe(true)
})

it('should create a table', async () => {
// Go to the indicated page
//await page.goto(url)

// Click on SQL query button
await click(page, '.ltr > #menu > .links > a:nth-child(1)')

// type the query
await typeText(page, 'CREATE TABLE example_basic (measure_ts TIMESTAMP NOT NULL,temperature FLOAT (50));', '.ltr > #content > #form > p > .jush')

// Execute the table creation query
await click(page, '.ltr > #content > #form > p > input:nth-child(1)')

// Check the creation of the table
await shouldExist(page, '#content > p.message')
})
})
Loading

0 comments on commit 9aaf46b

Please sign in to comment.