UNPKG

siesta-lite

Version:

Stress-free JavaScript unit testing and functional testing tool, works in NodeJS and browsers

416 lines (283 loc) 14.4 kB
Testing a sample React application with Siesta =============== In this guide, we'll describe how to use Siesta with React application. As a sample application, we'll use [GFontsSpace](https://github.com/pankajladhar/GFontsSpace). It is built with [react-scripts](https://www.npmjs.com/package/react-scripts) - a modern web application framework. This application already has tests, which runs in Node.js. It is arguable better, however, to run the tests on the same platform used by the end-user, so in this Siesta setup, we will aim to run application tests in real browsers. We won't write any new tests, instead, we "port" some of the existing ones to Siesta. In the following "Live example" sections there are instructions how to complete the setup of the example and examine it "live" in the browser. The 'Setup details' section, contains the detailed description of all changes, made to the "stock" GFontsSpace app. Live example ------------ The sample React application is bundled in the Siesta examples in the directory `examples-browser/react-google-fonts-space`. It is also available as a git repository, forked from the original app: [git://git.assembla.com/bryntum.siesta-react-gfonts-example.git]() To complete the setup, switch to the example folder in console, and run: > npm install Then to launch the server-side part of the example: > npm run start-siesta This command will open a Chrome window, pointing to `http://localhost:3000/`. There will be a running application in it: {@img images/gfonts-app.jpg} If you open the `http://localhost:3000/siesta.html` then you'll see Siesta's web interface, from which you can launch individual tests. {@img images/siesta-web-interface.jpg} There are 3 groups of tests - "Model", "Individual components", "Black box". This is a <a href="#!/guide/testing_strategy">recommended strategy</a> for testing your web application, which has the best ROI for time in our experience. Setup details -------------- Ok, we start we with the "stock" [GFontsSpace](https://github.com/pankajladhar/GFontsSpace) app, freshly cloned to some directory on your machine, which is assumed to be a current directory for the all console commands we'll use. ###Preparations To complete the clone: > npm install First we need to "eject" the application, to get access to the fine-grained configuration files and options. For that: > npm run eject Then, we add dependency on [siesta-lite](https://www.npmjs.com/package/siesta-lite) and couple of webpack plugins in `package.json`: ```json "devDependencies": { ... "siesta-lite": "^5.2.0", "webpack-watched-glob-entries-plugin": "^2.1.2", "copy-webpack-plugin": "^4.5.2" } ``` Then we install them: > npm install ### Siesta project creation Now, lets follow in general the <a href="#!/guide/getting_started_browser">Getting started with Siesta in browser environment</a> guide and create the Siesta project file as the `/src/siesta.js`, near the `/src/index.js` entry to the application itself: ```javascript const Siesta = require('siesta-lite/siesta-all.js') const project = new Siesta.Project.Browser(); project.configure({ title : 'React Google Fonts Space test suite' }); project.plan( { // Tests in this group, exercises model - the data layer of the app group : 'Model', items : [ './TRANSPILED/src/tests/model/mapper.t.js', ] }, { // Tests in this group, exercises individual components group : 'Individual components tests', items : [ './TRANSPILED/src/tests/components/text-box.t.js', './TRANSPILED/src/tests/components/color-picker.t.js' ] }, { // Tests in this group, access application as a "black box" // they open the `index.html` page and then executes as a // script on that page group : 'Black box tests', pageUrl : 'index.html', items : [ './TRANSPILED/src/tests/blackbox-app/010-sanity.t.js' ] } ); project.start(); ``` In the spirit of WebPack development, we "require" the `siesta-all.js` file, instead of loading it with the `<script>` tag. Our experiments with bundling Siesta's web interface CSS files in the same manner did not succeed though. That's why in the html wrapper for the Siesta project, we include them "normally", with the plain-old `<link>` tag. Lets name the wrapper file `/public/siesta.html`, again, it will be near the `public/index.html` file of the application entry. ```html <!DOCTYPE html> <html> <head> <!-- Recommended set of pragmas, required for IE11 compatibility--> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <!-- Web interface styles --> <link rel="stylesheet" type="text/css" href="static/siesta-lite/resources/css/siesta-all.css"> </head> <body> </body> </html> ``` We'll see shortly, how the "static/siesta-lite/resources/css" folder will be made available to the Siesta web interface page. ### Plugging into Webpack pipeline We now have the entry files to the Siesta web interface, but need to include them in the same WebPack pipeline that process files in the `src/` folder. That pipeline is defined in the `config/webpack.config.dev.js`. We will use it as a basis for two other pipelines we create. Lets create a new webpack config as `config/webpack.config.siesta-dev.js`: Import some infrastructure: ```javascript 'use strict'; const path = require('path'); const HtmlWebpackPlugin = require('html-webpack-plugin'); const paths = require('./paths'); const CopyWebpackPlugin = require('copy-webpack-plugin'); const WebpackWatchedGlobEntries = require('webpack-watched-glob-entries-plugin'); const lodash = require('lodash'); ``` Import the default WebPack config `webpack.config.dev.js` and tweak it - set the path for the output bundle to `build` folder. This is needed if you want to build a filesystem snapshot of the project (by default project files are served from memory with the development server). ```javascript const regularDev = require('./webpack.config.dev.js') // patch to always output to "build" directory (works fine with "npm start") regularDev.output.path = paths.appBuild ``` Then we create a new WebPack config, by cloning the dev one, and change the entry to point the Siesta project file, and output - to the `/static/siesta` folder ```javascript const siestaWebInterface = lodash.cloneDeep(regularDev) siestaWebInterface.entry = [ paths.siestaProject || (paths.appSrc + '/siesta.js') ] siestaWebInterface.output.filename = 'static/siesta/bundle.js' ``` We remove the `HtmlWebpackPlugin` plugin from the cloned config - as we don't want this pipeline to generate the `index.html` , and instead add our own plugins - `HtmlWebpackPlugin`, pointing to the `public/siesta.html` template, we've created earlier. In that template, we've used the `static/siesta-lite/resources` folder from the `siesta-lite` package, so also copy it to the distribution, using the `CopyWebpackPlugin` plugin: ```javascript lodash.remove(siestaWebInterface.plugins, plugin => plugin instanceof HtmlWebpackPlugin) siestaWebInterface.plugins.push( new HtmlWebpackPlugin({ inject : true, filename : 'siesta.html', template : paths.siestaHtml || 'public/siesta.html' }), new CopyWebpackPlugin([ { from : 'node_modules/siesta-lite/resources', to : 'static/siesta-lite/resources' } ]) ) ``` This is all for the Siesta web interface page, now we also want to setup the transpilation for the individual tests. For that, we use [WebpackWatchedGlobEntries](https://www.npmjs.com/package/webpack-watched-glob-entries-plugin) plugin, providing a glob, matching all the Siesta test files `*.t.js` in the `src/tests/**/`. We then setup an output name, so that filesystem structure is reflected in the `TRANSPILED` folder of the resulting build: ```javascript const testsTranspilation = lodash.cloneDeep(regularDev) testsTranspilation.entry = WebpackWatchedGlobEntries.getEntries( [ path.resolve(__dirname, '../src/tests/**/*.t.js'), ], { // // Optional glob options that are passed to glob.sync() // ignore: '**/*.test.js' } ) testsTranspilation.output.filename = 'TRANSPILED/src/tests/[name].js' ``` Then we again, remove the `HtmlWebpackPlugin` plugin, and include our own: ```javascript lodash.remove(testsTranspilation.plugins, plugin => plugin instanceof HtmlWebpackPlugin) testsTranspilation.plugins.push( new WebpackWatchedGlobEntries() ) ``` Finally, export all 3 webpack pipelines from our config file: ```javascript module.exports = [ regularDev, siestaWebInterface, testsTranspilation ]; ``` And, lets create a copy of the `scripts/start.js` - `scripts/start-siesta.js`. The only line we change in it: ```javascript const config = require('../config/webpack.config.dev'); ``` To: ```javascript const config = require('../config/webpack.config.siesta-dev'); ``` We need to also add it to the `package.json`: ```json "scripts": { "start-siesta": "node scripts/start-siesta.js", }, ``` ### Open Siesta web interface Now, we can use the `start-siesta.js` script, to launch the WebPack development server: > npm run start-siesta It will serve all 3 pipelines, we created in the previous section. Among them, there's a Siesta web interface webpage, available on the `http://localhost:3000/siesta.html`: {@img images/siesta-web-interface.jpg} From the web interface one can launch individual tests. Normally, WebPack takes care of auto-updating the sources, however when some drastical changes to the source folders structure, one may need to restart it. ### Porting test files Let examine how one Siesta tests compares with original tests of this application. The original one: ```javascript let mapper = require('./../index'); import fetchMock from 'fetch-mock'; import { googleFontResponse } from './../../TestData/MockGoogleFontResponse'; describe("Mapper", ()=>{ it("should map respose properly", ()=>{ fetchMock.get('*', googleFontResponse); mapper.fetchGoolgeFonts().then((obj)=>{ expect(obj.categories).toEqual(["All", "sans-serif", "serif", "display"]); expect(Object.keys(obj.fonts).length).toEqual(4); expect(obj.fonts["handwriting"]).toBeUndefined(); expect(obj.fonts["All"].length).toEqual(8); expect(obj.fonts["All"][0]).toEqual({"label": "ABeeZee", "value": "ABeeZee", "variants": [{"label": "regular", "value": "regular"}, {"label": "italic", "value": "italic"}]}); expect(obj.fonts["sans-serif"].length).toEqual(5); expect(obj.fonts["serif"].length).toEqual(2); expect(obj.fonts["display"].length).toEqual(1); }) }) }) ``` Its Siesta version: ```javascript import fetchMock from 'fetch-mock'; import { googleFontResponse } from './../../TestData/MockGoogleFontResponse'; let mapper = require('../../Mapper'); describe("Mapper", t => { t.it("should map respose properly", t => { fetchMock.get('*', googleFontResponse); // return the promise from the test function, to wait for it resolution return mapper.fetchGoolgeFonts().then(obj => { t.expect(obj.categories).toEqual(["All", "sans-serif", "serif", "display"]); t.expect(Object.keys(obj.fonts).length).toEqual(4); t.expect(obj.fonts["handwriting"]).toBeUndefined(); t.expect(obj.fonts["All"].length).toEqual(8); t.expect(obj.fonts["All"][0]).toEqual({"label": "ABeeZee", "value": "ABeeZee", "variants": [{"label": "regular", "value": "regular"}, {"label": "italic", "value": "italic"}]}); t.expect(obj.fonts["sans-serif"].length).toEqual(5); t.expect(obj.fonts["serif"].length).toEqual(2); t.expect(obj.fonts["display"].length).toEqual(1); }) }) }) ``` As you can see it maps pretty straightforward. We won't dive into this topic, there's more information available in the "Getting started guides", in this guide we are primarily interested in the overall project setup. Conclusion ---------- As you can see, Siesta can be plugged into React application in very straightforward way. You should be able to follow the same approach in your application, even if it does not use `react-scripts`. See also <a href="#!/guide/event_recorder">Using the event recorder</a> guide, in which this sample application is used to record some user actions. If you will encounter any issues or problems with your React testing, please let us know in the forums below, and we'll try to help you. Happy testing! Buy this product --------- Visit our store: <https://bryntum.com/store/siesta> Support --------- Ask question in our community forum: <https://www.bryntum.com/forum/viewforum.php?f=20> Subscribers can post expedited questions in Premium Forum: <https://www.bryntum.com/forum/viewforum.php?f=21> Please report any bugs through the web interface at <https://www.assembla.com/spaces/bryntum/support/tickets> See also --------- Siesta web-page: <https://bryntum.com/products/siesta> Other Bryntum products: <https://bryntum.com/products> Attribution --------- This software contains icons from the following icon packs (licensed under Creative Common 2.5/3.0 Attribution licenses) - <http://www.famfamfam.com/lab/icons/silk/> - <http://led24.de/iconset/> - <http://p.yusukekamiyamane.com/> - <http://rrze-icon-set.berlios.de/index.html> - <http://www.smashingmagazine.com/2009/05/20/flavour-extended-the-ultimate-icon-set-for-web-designers/> - <http://www.doublejdesign.co.uk/products-page/icons/super-mono-icons/> - <http://pixel-mixer.com/> Thanks a lot to the authors of the respective icons packs. COPYRIGHT AND LICENSE --------- Copyright (c) 2009-2022, Bryntum & Nickolay Platonov All rights reserved.