-
Notifications
You must be signed in to change notification settings - Fork 119
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test(xod-client): add a test for the recovering process
- Loading branch information
Showing
10 changed files
with
302 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
--require babel-register | ||
--colors | ||
--timeout=60000 | ||
--timeout=90000 | ||
--bail |
36 changes: 36 additions & 0 deletions
36
packages/xod-client-browser/test-func/pageObjects/IdeCrashReport.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
import BasePageObject from './BasePageObject'; | ||
|
||
const SELECTOR = '.IdeCrashReport'; | ||
|
||
class IdeCrashReport extends BasePageObject { | ||
async getErrorReport() { | ||
const textAreaElementHandle = await this.elementHandle.$( | ||
'.Message textarea' | ||
); | ||
|
||
const errorReport = await this.page.evaluate( | ||
el => el.value, | ||
textAreaElementHandle | ||
); | ||
|
||
return errorReport; | ||
} | ||
|
||
async clickClose() { | ||
const [button] = await this.elementHandle.$x('//button'); | ||
await button.click(); | ||
} | ||
} | ||
|
||
IdeCrashReport.findOnPage = async page => { | ||
const elementHandle = await page.$(SELECTOR); | ||
if (!elementHandle) return null; | ||
return new IdeCrashReport(page, elementHandle); | ||
}; | ||
|
||
IdeCrashReport.waitOnPage = async page => { | ||
await page.waitFor(SELECTOR, { timeout: 20000 }); | ||
return IdeCrashReport.findOnPage(page); | ||
}; | ||
|
||
export default IdeCrashReport; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
/* global browser:false, assert:false */ | ||
|
||
import getPage from './utils/getPage'; | ||
|
||
import ProjectBrowser from './pageObjects/ProjectBrowser'; | ||
import PromptPopup from './pageObjects/PromptPopup'; | ||
import IdeCrashReport from './pageObjects/IdeCrashReport'; | ||
import { getAllNodeIds, getSelectedNodes } from './pageObjects/Node'; | ||
|
||
it('Recovers on IDE crash', async () => { | ||
const page = await getPage(browser); | ||
|
||
// Recovering of the IDE recreates all components, | ||
// so we have to find this element again after recovering finished | ||
let projectBrowser = await ProjectBrowser.findOnPage(page); | ||
|
||
// Create a new patch | ||
projectBrowser.clickCreatePatch(); | ||
|
||
const popup = await PromptPopup.waitOnPage(page); | ||
await popup.typeText('test-recover'); | ||
await popup.clickConfirm(); | ||
|
||
// Mock the `render` method of Link to emulate a React Error | ||
await page.evaluate(() => { | ||
window.Components.Link.prototype.render = function erroredRender() { | ||
throw new Error('CATCH ME'); | ||
}; | ||
}); | ||
|
||
// Add first node | ||
await projectBrowser.addNodeViaContextMenu('xod/core', 'clock'); | ||
const [clockNode] = await getSelectedNodes(page); | ||
await clockNode.drag(150, 150); | ||
|
||
// Add second node | ||
await projectBrowser.addNodeViaContextMenu('xod/core', 'flip-flop'); | ||
const [flipFlopNode] = await getSelectedNodes(page); | ||
await flipFlopNode.drag(150, 250); | ||
|
||
// Begin linking: click on first pin | ||
const clockTickPin = await clockNode.findPinByName('TICK'); | ||
await clockTickPin.click(); | ||
// It will create a Link, which render method are broken for the test | ||
// So the IDE should catch the Error and recover to the previous state | ||
|
||
// Test that state recovered and error has been shown | ||
const crashReport = await IdeCrashReport.waitOnPage(page); | ||
const report = await crashReport.getErrorReport(); | ||
|
||
// Report contains a lot of data, so we'll check only first two rows | ||
const expectedFirstRowsOfReport = [ | ||
'# ERROR', | ||
"Error: A cross-origin error was thrown. React doesn't have access to the actual error object in development. See https://fb.me/react-crossorigin-error for more information.", | ||
].join('\n'); | ||
assert.equal(report.split('\n', 2).join('\n'), expectedFirstRowsOfReport); | ||
|
||
// Test that report can be closed | ||
await crashReport.clickClose(); | ||
assert.isNull( | ||
await IdeCrashReport.findOnPage(page), | ||
'Crash report element is closed' | ||
); | ||
|
||
// Test that state was recovered correctly (the patch has placed nodes) | ||
const expectedNodesOnPatch = [ | ||
await clockNode.getId(), | ||
await flipFlopNode.getId(), | ||
]; | ||
assert.sameMembers( | ||
await getAllNodeIds(page), | ||
expectedNodesOnPatch, | ||
'The patch should contain the same nodes after recovering' | ||
); | ||
|
||
// Renew the `projectBrowser` page object | ||
projectBrowser = await ProjectBrowser.findOnPage(page); | ||
|
||
// Test that IDE still works (add one more node) | ||
await projectBrowser.addNodeViaContextMenu('xod/gpio', 'digital-write'); | ||
const [digitalWrite] = await getSelectedNodes(page); | ||
await digitalWrite.drag(150, 350); | ||
|
||
// Test that the third node was added successfully | ||
assert.sameMembers( | ||
await getAllNodeIds(page), | ||
[...expectedNodesOnPatch, await digitalWrite.getId()], | ||
'The patch should contain the same nodes after recovering' | ||
); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export const PORT = process.env.STATIC_SERVER_PORT || 8081; | ||
export const SERVER_URL = `http://localhost:${PORT}`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
const path = require('path'); | ||
/* eslint-disable import/no-extraneous-dependencies */ | ||
const merge = require('webpack-merge'); | ||
/* eslint-enable import/no-extraneous-dependencies */ | ||
const baseConfig = require('./webpack.config.js'); | ||
|
||
const pkgpath = subpath => path.join(__dirname, subpath); | ||
|
||
const babelLoader = { | ||
loader: 'babel-loader', | ||
options: { | ||
presets: ['react', 'es2015'], | ||
plugins: ['transform-object-rest-spread'], | ||
}, | ||
}; | ||
|
||
module.exports = merge.smart(baseConfig, { | ||
devtool: 'eval-source-map', | ||
output: { | ||
publicPath: 'http://localhost:8080/', | ||
}, | ||
devServer: { | ||
hot: false, | ||
host: 'localhost', | ||
port: 8080, | ||
contentBase: pkgpath('dist'), | ||
compress: true, | ||
}, | ||
module: { | ||
rules: [ | ||
{ | ||
test: /xod-client\/.+(components|containers)\/.+\.js$/, | ||
use: [ | ||
{ | ||
loader: 'expose-loader', | ||
options: { | ||
exposes: { | ||
globalName: 'Components.[name]', | ||
moduleLocalName: 'default', | ||
}, | ||
}, | ||
}, | ||
], | ||
}, | ||
{ | ||
test: /\.jsx$/, | ||
use: [ | ||
{ | ||
loader: 'expose-loader', | ||
options: { | ||
exposes: { | ||
globalName: 'Components.[name]', | ||
moduleLocalName: 'default', | ||
override: true, | ||
}, | ||
}, | ||
}, | ||
babelLoader, | ||
], | ||
}, | ||
], | ||
}, | ||
}); |
Oops, something went wrong.