Merge pull request #584 from paulkaplan/selenium-with-jest
Add end-to-end testing using selenium-webdriver
This commit is contained in:
commit
d0fc523f6b
7 files changed
+170
-8
No files matched your search
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"plugins": [
|
||||
"syntax-dynamic-import",
|
||||
"transform-async-to-generator",
|
||||
"transform-object-rest-spread",
|
||||
["react-intl", {
|
||||
"messagesDir": "./translations/messages/"
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
language: node_js
|
||||
sudo: false
|
||||
dist: trusty
|
||||
addons:
|
||||
chrome: stable
|
||||
before_script:
|
||||
- "export DISPLAY=:99.0"
|
||||
- "sh -e /etc/init.d/xvfb start"
|
||||
node_js:
|
||||
- 6
|
||||
cache:
|
||||
|
||||
@@ -31,7 +31,7 @@ Then go to [http://localhost:8601/](http://localhost:8601/) - the playground out
|
||||
## Testing
|
||||
NOTE: If you're a windows user, please run these scripts in Windows `cmd.exe` instead of Git Bash/MINGW64.
|
||||
|
||||
Run linter, unit tests, and build.
|
||||
Run linter, unit tests, build, and integration tests.
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
@@ -46,6 +46,11 @@ Run unit tests in watch mode (watches for code changes and continuously runs tes
|
||||
npm run unit-test -- --watch
|
||||
```
|
||||
|
||||
Run integration tests in isolation.
|
||||
```bash
|
||||
npm run integration-test
|
||||
```
|
||||
|
||||
You may want to review the documentation for [Jest](https://facebook.github.io/jest/docs/en/api.html) and [Enzyme](http://airbnb.io/enzyme/docs/api/) as you write your tests.
|
||||
|
||||
## Publishing to GitHub Pages
|
||||
|
||||
+6
-2
@@ -11,8 +11,9 @@
|
||||
"i18n:src": "babel src > tmp.js && rimraf tmp.js && ./scripts/build-i18n-source.js ./translations/messages/ ./translations/",
|
||||
"lint": "eslint . --ext .js,.jsx",
|
||||
"start": "npm run i18n:msgs && webpack-dev-server",
|
||||
"unit-test": "jest",
|
||||
"test": "npm run lint && npm run unit-test && npm run build",
|
||||
"unit-test": "jest test/unit",
|
||||
"integration-test": "npm run build && jest test/integration",
|
||||
"test": "npm run lint && npm run unit-test && npm run integration-test",
|
||||
"watch": "webpack --progress --colors --watch"
|
||||
},
|
||||
"author": "Massachusetts Institute of Technology",
|
||||
@@ -34,9 +35,11 @@
|
||||
"babel-loader": "^7.0.0",
|
||||
"babel-plugin-react-intl": "2.3.1",
|
||||
"babel-plugin-syntax-dynamic-import": "6.18.0",
|
||||
"babel-plugin-transform-async-to-generator": "^6.24.1",
|
||||
"babel-plugin-transform-object-rest-spread": "^6.22.0",
|
||||
"babel-preset-es2015": "^6.22.0",
|
||||
"babel-preset-react": "^6.22.0",
|
||||
"chromedriver": "^2.31.0",
|
||||
"classnames": "2.2.5",
|
||||
"copy-webpack-plugin": "4.0.1",
|
||||
"css-loader": "0.28.3",
|
||||
@@ -83,6 +86,7 @@
|
||||
"scratch-render": "latest",
|
||||
"scratch-storage": "^0.2.0",
|
||||
"scratch-vm": "latest",
|
||||
"selenium-webdriver": "^3.5.0",
|
||||
"style-loader": "^0.18.0",
|
||||
"svg-to-image": "1.1.3",
|
||||
"svg-url-loader": "2.1.0",
|
||||
|
||||
@@ -7717,7 +7717,7 @@
|
||||
109,
|
||||
32
|
||||
],
|
||||
"md5": "4cddf35440090d30d4de188625d609c9.svg",
|
||||
"md5": "0a54c19714962c197532f68c56fde123.svg",
|
||||
"type": "costume",
|
||||
"name": "text awesome",
|
||||
"tags": [
|
||||
@@ -7731,7 +7731,7 @@
|
||||
135,
|
||||
24
|
||||
],
|
||||
"md5": "6f54c5de1985d7f23a24341e1688c4b0.svg",
|
||||
"md5": "97c9e6ef78d4f1987fd8c6e5042963cb.svg",
|
||||
"type": "costume",
|
||||
"name": "text keep scratching",
|
||||
"tags": [
|
||||
@@ -7745,7 +7745,7 @@
|
||||
172,
|
||||
30
|
||||
],
|
||||
"md5": "e634628e4b948573710f7e4a4f50659b.svg",
|
||||
"md5": "9fde2e190a9d01c08737dff291bdd4a8.svg",
|
||||
"type": "costume",
|
||||
"name": "text valentine's day",
|
||||
"tags": [
|
||||
@@ -7759,7 +7759,7 @@
|
||||
165,
|
||||
34
|
||||
],
|
||||
"md5": "7ebe62c6f2b7c8b644d2abe036b8f69e.svg",
|
||||
"md5": "0176a402a133f7b833da61b890e0d73e.svg",
|
||||
"type": "costume",
|
||||
"name": "text Halloween",
|
||||
"tags": [
|
||||
@@ -10629,4 +10629,4 @@
|
||||
"vector"
|
||||
]
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -0,0 +1,58 @@
|
||||
/* eslint-env jest */
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000; // eslint-disable-line no-undef
|
||||
|
||||
import webdriver from 'selenium-webdriver';
|
||||
|
||||
const {By, until} = webdriver;
|
||||
|
||||
const driver = new webdriver.Builder()
|
||||
.forBrowser('chrome')
|
||||
.build();
|
||||
|
||||
const findByXpath = (xpath) => {
|
||||
return driver.wait(until.elementLocated(By.xpath(xpath), 5 * 1000));
|
||||
};
|
||||
|
||||
const clickXpath = (xpath) => {
|
||||
return findByXpath(xpath).then(el => el.click());
|
||||
};
|
||||
|
||||
const clickText = (text) => {
|
||||
return clickXpath(`//*[contains(text(), '${text}')]`);
|
||||
};
|
||||
|
||||
const clickButton = (text) => {
|
||||
return clickXpath(`//button[contains(text(), '${text}')]`);
|
||||
};
|
||||
|
||||
const getLogs = (whitelist) => {
|
||||
return driver.manage()
|
||||
.logs()
|
||||
.get('browser')
|
||||
.then((entries) => {
|
||||
return entries.filter((entry) => {
|
||||
const message = entry.message;
|
||||
for (let i = 0; i < whitelist.length; i++) {
|
||||
if (message.indexOf(whitelist[i]) !== -1) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn('Ignoring whitelisted error: ' + whitelist[i]);
|
||||
return false;
|
||||
} else if (entry.level !== 'SEVERE') {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn('Ignoring non-SEVERE entry: ' + message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export {
|
||||
clickText,
|
||||
clickButton,
|
||||
clickXpath,
|
||||
driver,
|
||||
findByXpath,
|
||||
getLogs
|
||||
};
|
||||
@@ -0,0 +1,89 @@
|
||||
/* eslint-env jest */
|
||||
/* globals Promise */
|
||||
|
||||
import path from 'path';
|
||||
import {
|
||||
clickText,
|
||||
clickButton,
|
||||
clickXpath,
|
||||
driver,
|
||||
findByXpath,
|
||||
getLogs
|
||||
} from '../helpers/selenium-helpers';
|
||||
|
||||
const uri = path.resolve(__dirname, '../../build/index.html');
|
||||
|
||||
const errorWhitelist = [
|
||||
'The play() request was interrupted by a call to pause()'
|
||||
];
|
||||
|
||||
describe('costumes, sounds and variables', () => {
|
||||
afterAll(async () => {
|
||||
await driver.quit();
|
||||
});
|
||||
|
||||
test('Adding a costume', async () => {
|
||||
await driver.get('file://' + uri);
|
||||
await clickText('Costumes');
|
||||
await clickText('Add Costume');
|
||||
const el = await findByXpath("//input[@placeholder='what are you looking for?']");
|
||||
await el.sendKeys('abb');
|
||||
await clickText('abby-a'); // Should close the modal, then click the costumes in the selector
|
||||
await clickText('costume1');
|
||||
await clickText('abby-a');
|
||||
const logs = await getLogs(errorWhitelist);
|
||||
await expect(logs).toEqual([]);
|
||||
});
|
||||
|
||||
test('Adding a sound', async () => {
|
||||
await driver.get('file://' + uri);
|
||||
await clickText('Sounds');
|
||||
await clickText('Add Sound');
|
||||
const el = await findByXpath("//input[@placeholder='what are you looking for?']");
|
||||
await el.sendKeys('chom');
|
||||
await clickText('chomp'); // Should close the modal, then click the sounds in the selector
|
||||
await clickText('meow');
|
||||
await clickText('chomp');
|
||||
await clickXpath('//button[@title="Play"]');
|
||||
await clickText('meow');
|
||||
await clickXpath('//button[@title="Play"]');
|
||||
|
||||
await clickText('Louder');
|
||||
await clickText('Softer');
|
||||
await clickText('Faster');
|
||||
await clickText('Slower');
|
||||
await clickText('Robot');
|
||||
await clickText('Echo');
|
||||
await clickText('Reverse');
|
||||
|
||||
const logs = await getLogs(errorWhitelist);
|
||||
await expect(logs).toEqual([]);
|
||||
});
|
||||
|
||||
test('Load a project by ID', async () => {
|
||||
const projectId = '96708228';
|
||||
await driver.get('file://' + uri + '#' + projectId);
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
await clickXpath('//img[@title="Go"]');
|
||||
await new Promise(resolve => setTimeout(resolve, 2000));
|
||||
await clickXpath('//img[@title="Stop"]');
|
||||
const logs = await getLogs(errorWhitelist);
|
||||
await expect(logs).toEqual([]);
|
||||
});
|
||||
|
||||
test('Creating variables', async () => {
|
||||
await driver.get('file://' + uri);
|
||||
await clickText('Blocks');
|
||||
await clickText('Data');
|
||||
await clickText('Create variable...');
|
||||
let el = await findByXpath("//input[@placeholder='']");
|
||||
await el.sendKeys('score');
|
||||
await clickButton('OK');
|
||||
await clickText('Create variable...');
|
||||
el = await findByXpath("//input[@placeholder='']");
|
||||
await el.sendKeys('second variable');
|
||||
await clickButton('OK');
|
||||
const logs = await getLogs(errorWhitelist);
|
||||
await expect(logs).toEqual([]);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user