diff --git a/docs/.vitepress/config.js b/docs/.vitepress/config.js index 3fc95f9b..8de78d35 100644 --- a/docs/.vitepress/config.js +++ b/docs/.vitepress/config.js @@ -120,6 +120,7 @@ export default ({ mode }) => { items: [ { text: 'Adding Core Widgets', link: '/contributing/widgets/core-widgets' }, { text: 'Third Party Widgets', link: '/contributing/widgets/third-party' }, + { text: 'Testing', link: '/contributing/widgets/testing' }, { text: 'Debugging', link: '/contributing/widgets/debugging' } ] }, diff --git a/docs/contributing/widgets/testing.md b/docs/contributing/widgets/testing.md new file mode 100644 index 00000000..9500dc85 --- /dev/null +++ b/docs/contributing/widgets/testing.md @@ -0,0 +1,53 @@ +# E2E Testing + +E2E Testing consists of runnig a local environment, and automating interaction with the browser to test the widgets behaviour. + +With Dashboard 2.0, we have the following commands which are used for testing: + +- `npm run cy:server` - Runs an instance of Node-RED with Dashboard 2.0 installed. +- `npm run cy:run` - Runs all of the Cypress tests in headless mode. +- `npm run cy:open` - Opens the Cypress test runner, whereby you can explicitly choose which tests to run locally. + + +## Cypress Test Helper + +In order to make it easier to write tests, we have created a helper function which can be used to test the output from particular widgets. + +] + +The "Store Latest Msg" function node here contains: + +```js +global.set('msg', msg) +return msg; +``` + +When a button is clicked in the Dashboard, the value emitted by that button is then stored in a global `msg` variable. We can then use this in conjuction with: + + + +In order to make an API call from Cypress after we've clicked the button and checked the stored value against that which we expect the button to have emitted. + +For example, from our button tests: + +```js +describe('Node-RED Dashboard 2.0 - Buttons', () => { + beforeEach(() => { + cy.deployFixture('dashboard-buttons') // reads in a flow.json and deploys it to the local Node-RED instance + cy.visit('/dashboard/page1') + }) + + it('can be clicked and outputs the correct payload & topic are emitted', () => { + // Emitting strings + cy.get('button').contains('Button 1 (str)').click() + // checkOutput calls our helper endpoints to checks the values against the stored msg + cy.checkOutput('msg.payload', 'button 1 clicked') + cy.checkOutput('msg.topic', 'button-str-topic') + + // Emitting JSON + cy.get('button').contains('Button 1 (json)').click() + cy.checkOutput('msg.payload.hello', 'world') + cy.checkOutput('msg.topic', 'button-json-topic') + }) +}) +``` \ No newline at end of file