UNPKG

siesta-lite

Version:

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

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