mirror of
https://github.com/scratchfoundation/scratch-www.git
synced 2024-11-25 16:46:55 +08:00
style(test): enable ES6 and Jest eslint rules for tests
This commit is contained in:
parent
2356a93122
commit
9a97535168
271
package-lock.json
generated
271
package-lock.json
generated
@ -53,6 +53,7 @@
|
||||
"enzyme-adapter-react-16": "1.14.0",
|
||||
"eslint": "5.16.0",
|
||||
"eslint-config-scratch": "7.0.0",
|
||||
"eslint-plugin-jest": "24.7.0",
|
||||
"eslint-plugin-json": "2.0.1",
|
||||
"eslint-plugin-react": "7.14.2",
|
||||
"eslint-plugin-react-hooks": "4.2.0",
|
||||
@ -2073,6 +2074,224 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/experimental-utils": {
|
||||
"version": "4.33.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz",
|
||||
"integrity": "sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/json-schema": "^7.0.7",
|
||||
"@typescript-eslint/scope-manager": "4.33.0",
|
||||
"@typescript-eslint/types": "4.33.0",
|
||||
"@typescript-eslint/typescript-estree": "4.33.0",
|
||||
"eslint-scope": "^5.1.1",
|
||||
"eslint-utils": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10.12.0 || >=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-scope": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
|
||||
"integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"esrecurse": "^4.3.0",
|
||||
"estraverse": "^4.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-utils": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
|
||||
"integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"eslint-visitor-keys": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10.0.0 || ^12.0.0 || >= 14.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/mysticatea"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"eslint": ">=5"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-visitor-keys": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
|
||||
"integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/scope-manager": {
|
||||
"version": "4.33.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz",
|
||||
"integrity": "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "4.33.0",
|
||||
"@typescript-eslint/visitor-keys": "4.33.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^8.10.0 || ^10.13.0 || >=11.10.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/types": {
|
||||
"version": "4.33.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz",
|
||||
"integrity": "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^8.10.0 || ^10.13.0 || >=11.10.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree": {
|
||||
"version": "4.33.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz",
|
||||
"integrity": "sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "4.33.0",
|
||||
"@typescript-eslint/visitor-keys": "4.33.0",
|
||||
"debug": "^4.3.1",
|
||||
"globby": "^11.0.3",
|
||||
"is-glob": "^4.0.1",
|
||||
"semver": "^7.3.5",
|
||||
"tsutils": "^3.21.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^10.12.0 || >=12.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"typescript": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/debug": {
|
||||
"version": "4.3.4",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"ms": "2.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"supports-color": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/is-extglob": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
|
||||
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/is-glob": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
|
||||
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"is-extglob": "^2.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"yallist": "^4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
|
||||
"version": "7.5.4",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"lru-cache": "^6.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/typescript-estree/node_modules/yallist": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys": {
|
||||
"version": "4.33.0",
|
||||
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz",
|
||||
"integrity": "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/types": "4.33.0",
|
||||
"eslint-visitor-keys": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^8.10.0 || ^10.13.0 || >=11.10.1"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/typescript-eslint"
|
||||
}
|
||||
},
|
||||
"node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
|
||||
"integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/@vernier/godirect": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@vernier/godirect/-/godirect-1.5.0.tgz",
|
||||
@ -8550,6 +8769,27 @@
|
||||
"eslint": ">=5.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-jest": {
|
||||
"version": "24.7.0",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-24.7.0.tgz",
|
||||
"integrity": "sha512-wUxdF2bAZiYSKBclsUMrYHH6WxiBreNjyDxbRv345TIvPeoCEgPNEn3Sa+ZrSqsf1Dl9SqqSREXMHExlMMu1DA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/experimental-utils": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@typescript-eslint/eslint-plugin": ">= 4",
|
||||
"eslint": ">=5"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@typescript-eslint/eslint-plugin": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/eslint-plugin-json": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/eslint-plugin-json/-/eslint-plugin-json-2.0.1.tgz",
|
||||
@ -8874,16 +9114,24 @@
|
||||
}
|
||||
},
|
||||
"node_modules/esrecurse": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz",
|
||||
"integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==",
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
|
||||
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
|
||||
"dependencies": {
|
||||
"estraverse": "^4.1.0"
|
||||
"estraverse": "^5.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/esrecurse/node_modules/estraverse": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
|
||||
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
|
||||
"engines": {
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/estraverse": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz",
|
||||
@ -29361,6 +29609,21 @@
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
|
||||
"integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ=="
|
||||
},
|
||||
"node_modules/tsutils": {
|
||||
"version": "3.21.0",
|
||||
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
|
||||
"integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"tslib": "^1.8.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
|
||||
}
|
||||
},
|
||||
"node_modules/tty-browserify": {
|
||||
"version": "0.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
|
||||
|
@ -88,6 +88,7 @@
|
||||
"enzyme-adapter-react-16": "1.14.0",
|
||||
"eslint": "5.16.0",
|
||||
"eslint-config-scratch": "7.0.0",
|
||||
"eslint-plugin-jest": "24.7.0",
|
||||
"eslint-plugin-json": "2.0.1",
|
||||
"eslint-plugin-react": "7.14.2",
|
||||
"eslint-plugin-react-hooks": "4.2.0",
|
||||
|
@ -1,6 +1,15 @@
|
||||
module.exports = {
|
||||
extends: ['scratch/react'],
|
||||
extends: ['scratch/react', 'scratch/es6', 'plugin:jest/recommended'],
|
||||
env: {
|
||||
jest: true
|
||||
},
|
||||
rules: {
|
||||
'jest/no-done-callback': 'off', // TODO: convert callback-based tests to async/await
|
||||
'no-confusing-arrow': [
|
||||
'error',
|
||||
{
|
||||
allowParens: true
|
||||
}
|
||||
],
|
||||
}
|
||||
};
|
||||
|
@ -7,19 +7,17 @@ import {createIntl, IntlProvider} from 'react-intl';
|
||||
import {mount, shallow} from 'enzyme';
|
||||
import intlShape from '../../src/lib/intl-shape';
|
||||
|
||||
const shallowWithIntl = (node, {context} = {}) => {
|
||||
return shallow(
|
||||
node,
|
||||
{
|
||||
context: Object.assign({}, context),
|
||||
wrappingComponent: IntlProvider,
|
||||
wrappingComponentProps: {
|
||||
locale: 'en',
|
||||
messages: {}
|
||||
}
|
||||
const shallowWithIntl = (node, {context} = {}) => shallow(
|
||||
node,
|
||||
{
|
||||
context: Object.assign({}, context),
|
||||
wrappingComponent: IntlProvider,
|
||||
wrappingComponentProps: {
|
||||
locale: 'en',
|
||||
messages: {}
|
||||
}
|
||||
).dive();
|
||||
};
|
||||
}
|
||||
).dive();
|
||||
|
||||
const mountWithIntl = (node, {context, childContextTypes} = {}) => {
|
||||
const intl = createIntl({locale: 'en', messages: {}});
|
||||
|
@ -36,8 +36,8 @@ class SeleniumHelper {
|
||||
if (remote === 'true'){
|
||||
let nameToUse;
|
||||
if (ci === 'true'){
|
||||
let ciName = usingCircle ? 'circleCi ' : 'unknown ';
|
||||
nameToUse = ciName + buildID + ' : ' + name;
|
||||
const ciName = usingCircle ? 'circleCi ' : 'unknown ';
|
||||
nameToUse = `${ciName + buildID} : ${name}`;
|
||||
} else {
|
||||
nameToUse = name;
|
||||
}
|
||||
@ -50,14 +50,14 @@ class SeleniumHelper {
|
||||
|
||||
getDriver () {
|
||||
const chromeCapabilities = webdriver.Capabilities.chrome();
|
||||
let args = [];
|
||||
const args = [];
|
||||
if (headless) {
|
||||
args.push('--headless');
|
||||
args.push('window-size=1024,1680');
|
||||
args.push('--no-sandbox');
|
||||
}
|
||||
chromeCapabilities.set('chromeOptions', {args});
|
||||
let driver = new webdriver.Builder()
|
||||
const driver = new webdriver.Builder()
|
||||
.forBrowser('chrome')
|
||||
.withCapabilities(chromeCapabilities)
|
||||
.build();
|
||||
@ -67,12 +67,12 @@ class SeleniumHelper {
|
||||
getSauceDriver (username, accessKey, name) {
|
||||
// Driver configs can be generated with the Sauce Platform Configurator
|
||||
// https://wiki.saucelabs.com/display/DOCS/Platform+Configurator
|
||||
let driverConfig = {
|
||||
const driverConfig = {
|
||||
browserName: 'chrome',
|
||||
platform: 'macOS 10.14',
|
||||
version: '76.0'
|
||||
};
|
||||
var driver = new webdriver.Builder()
|
||||
const driver = new webdriver.Builder()
|
||||
.withCapabilities({
|
||||
browserName: driverConfig.browserName,
|
||||
platform: driverConfig.platform,
|
||||
@ -128,13 +128,13 @@ class SeleniumHelper {
|
||||
}
|
||||
|
||||
dragFromXpathToXpath (startXpath, endXpath) {
|
||||
return this.findByXpath(startXpath).then(startEl => {
|
||||
return this.findByXpath(endXpath).then(endEl => {
|
||||
return this.driver.actions()
|
||||
return this.findByXpath(startXpath).then(startEl =>
|
||||
this.findByXpath(endXpath).then(endEl =>
|
||||
this.driver.actions()
|
||||
.dragAndDrop(startEl, endEl)
|
||||
.perform();
|
||||
});
|
||||
});
|
||||
.perform()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
urlMatches (regex) {
|
||||
@ -145,24 +145,22 @@ class SeleniumHelper {
|
||||
return this.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;
|
||||
.then(entries => 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;
|
||||
});
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,13 +9,13 @@ module.exports.constants = {
|
||||
};
|
||||
|
||||
module.exports.fillUsernameSlide = function (driver, seleniumWebdriver) {
|
||||
var passwordInput = driver.findElement(seleniumWebdriver.By.name('user.password'));
|
||||
var usernameInput = driver.findElement(seleniumWebdriver.By.name('user.username'));
|
||||
var usernamePromise = usernameInput.sendKeys('clipspringer');
|
||||
var passwordPromise = passwordInput.sendKeys('educators');
|
||||
var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath));
|
||||
return Promise.all([usernamePromise, passwordPromise]).then(function () { // eslint-disable-line no-undef
|
||||
nextStepButton.click().then(function () {
|
||||
const passwordInput = driver.findElement(seleniumWebdriver.By.name('user.password'));
|
||||
const usernameInput = driver.findElement(seleniumWebdriver.By.name('user.username'));
|
||||
const usernamePromise = usernameInput.sendKeys('clipspringer');
|
||||
const passwordPromise = passwordInput.sendKeys('educators');
|
||||
const nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath));
|
||||
return Promise.all([usernamePromise, passwordPromise]).then(() => { // eslint-disable-line no-undef
|
||||
nextStepButton.click().then(() => {
|
||||
driver.wait(seleniumWebdriver.until
|
||||
.elementLocated(seleniumWebdriver.By.className('demographics-step')));
|
||||
});
|
||||
@ -23,13 +23,13 @@ module.exports.fillUsernameSlide = function (driver, seleniumWebdriver) {
|
||||
};
|
||||
|
||||
module.exports.fillDemographicsSlide = function (driver, seleniumWebdriver) {
|
||||
var clickMaleInput = driver.findElement(seleniumWebdriver.By.xpath('//input[@value="male"' +
|
||||
const clickMaleInput = driver.findElement(seleniumWebdriver.By.xpath('//input[@value="male"' +
|
||||
'and @type="radio"]')).click();
|
||||
var selectCountry = driver.findElement(seleniumWebdriver.By.xpath('//select[@name="user.country"]' +
|
||||
const selectCountry = driver.findElement(seleniumWebdriver.By.xpath('//select[@name="user.country"]' +
|
||||
'/option[@value="us"]')).click();
|
||||
var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath));
|
||||
return Promise.all([clickMaleInput, selectCountry]).then(function () { // eslint-disable-line no-undef
|
||||
nextStepButton.click().then(function () {
|
||||
const nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath));
|
||||
return Promise.all([clickMaleInput, selectCountry]).then(() => { // eslint-disable-line no-undef
|
||||
nextStepButton.click().then(() => {
|
||||
driver.wait(seleniumWebdriver.until
|
||||
.elementLocated(seleniumWebdriver.By.className('name-step')));
|
||||
});
|
||||
@ -37,11 +37,11 @@ module.exports.fillDemographicsSlide = function (driver, seleniumWebdriver) {
|
||||
};
|
||||
|
||||
module.exports.fillNameSlide = function (driver, seleniumWebdriver) {
|
||||
var firstNamePromise = driver.findElement(seleniumWebdriver.By.name('user.name.first')).sendKeys('first');
|
||||
var lastNamePromise = driver.findElement(seleniumWebdriver.By.name('user.name.last')).sendKeys('surname');
|
||||
var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath));
|
||||
return Promise.all([firstNamePromise, lastNamePromise]).then(function () { // eslint-disable-line no-undef
|
||||
nextStepButton.click().then(function () {
|
||||
const firstNamePromise = driver.findElement(seleniumWebdriver.By.name('user.name.first')).sendKeys('first');
|
||||
const lastNamePromise = driver.findElement(seleniumWebdriver.By.name('user.name.last')).sendKeys('surname');
|
||||
const nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath));
|
||||
return Promise.all([firstNamePromise, lastNamePromise]).then(() => { // eslint-disable-line no-undef
|
||||
nextStepButton.click().then(() => {
|
||||
driver.wait(seleniumWebdriver.until
|
||||
.elementLocated(seleniumWebdriver.By.className('phone-step')));
|
||||
});
|
||||
@ -49,13 +49,13 @@ module.exports.fillNameSlide = function (driver, seleniumWebdriver) {
|
||||
};
|
||||
|
||||
module.exports.fillPhoneSlide = function (driver, seleniumWebdriver) {
|
||||
var phoneInput = driver.findElement(seleniumWebdriver.By.xpath('//input[@type="tel"]'));
|
||||
var consentCheckbox = driver.findElement(seleniumWebdriver.By.name('phoneConsent'));
|
||||
var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath));
|
||||
var phoneNumberPromise = phoneInput.sendKeys('6172535960');
|
||||
var consentPromise = consentCheckbox.click();
|
||||
return Promise.all([phoneNumberPromise, consentPromise]).then(function () { // eslint-disable-line no-undef
|
||||
nextStepButton.click().then(function () {
|
||||
const phoneInput = driver.findElement(seleniumWebdriver.By.xpath('//input[@type="tel"]'));
|
||||
const consentCheckbox = driver.findElement(seleniumWebdriver.By.name('phoneConsent'));
|
||||
const nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath));
|
||||
const phoneNumberPromise = phoneInput.sendKeys('6172535960');
|
||||
const consentPromise = consentCheckbox.click();
|
||||
return Promise.all([phoneNumberPromise, consentPromise]).then(() => { // eslint-disable-line no-undef
|
||||
nextStepButton.click().then(() => {
|
||||
driver.wait(seleniumWebdriver.until
|
||||
.elementLocated(seleniumWebdriver.By.className('organization-step')));
|
||||
});
|
||||
@ -63,16 +63,16 @@ module.exports.fillPhoneSlide = function (driver, seleniumWebdriver) {
|
||||
};
|
||||
|
||||
module.exports.fillOrganizationSlide = function (driver, seleniumWebdriver) {
|
||||
var organizationInput = driver.findElement(seleniumWebdriver.By.name('organization.name'));
|
||||
var titleInput = driver.findElement(seleniumWebdriver.By.name('organization.title'));
|
||||
var typeCheckbox = driver.findElement(seleniumWebdriver.By.xpath('//input[@type="checkbox" and @value="3"]'));
|
||||
var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath));
|
||||
var organizationPromise = organizationInput.sendKeys('MIT Media Lab');
|
||||
var titlePromise = titleInput.sendKeys('Software Developer');
|
||||
var typePromise = typeCheckbox.click();
|
||||
const organizationInput = driver.findElement(seleniumWebdriver.By.name('organization.name'));
|
||||
const titleInput = driver.findElement(seleniumWebdriver.By.name('organization.title'));
|
||||
const typeCheckbox = driver.findElement(seleniumWebdriver.By.xpath('//input[@type="checkbox" and @value="3"]'));
|
||||
const nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath));
|
||||
const organizationPromise = organizationInput.sendKeys('MIT Media Lab');
|
||||
const titlePromise = titleInput.sendKeys('Software Developer');
|
||||
const typePromise = typeCheckbox.click();
|
||||
return Promise.all([organizationPromise, titlePromise, typePromise]) // eslint-disable-line no-undef
|
||||
.then(function () {
|
||||
nextStepButton.click().then(function () {
|
||||
.then(() => {
|
||||
nextStepButton.click().then(() => {
|
||||
driver.wait(seleniumWebdriver.until
|
||||
.elementLocated(seleniumWebdriver.By.className('address-step')));
|
||||
});
|
||||
@ -80,18 +80,18 @@ module.exports.fillOrganizationSlide = function (driver, seleniumWebdriver) {
|
||||
};
|
||||
|
||||
module.exports.fillAddressSlide = function (driver, seleniumWebdriver) {
|
||||
var addressInput = driver.findElement(seleniumWebdriver.By.name('address.line1'));
|
||||
var cityInput = driver.findElement(seleniumWebdriver.By.name('address.city'));
|
||||
var zipCodeInput = driver.findElement(seleniumWebdriver.By.name('address.zip'));
|
||||
var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath));
|
||||
var addressPromise = addressInput.sendKeys('77 Massachusetts Avenue, E14/E15');
|
||||
var cityPromise = cityInput.sendKeys('Cambridge');
|
||||
var statePromise = driver.findElement(seleniumWebdriver.By.xpath('//select[@name="address.state"]' +
|
||||
const addressInput = driver.findElement(seleniumWebdriver.By.name('address.line1'));
|
||||
const cityInput = driver.findElement(seleniumWebdriver.By.name('address.city'));
|
||||
const zipCodeInput = driver.findElement(seleniumWebdriver.By.name('address.zip'));
|
||||
const nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(module.exports.constants.nextStepXpath));
|
||||
const addressPromise = addressInput.sendKeys('77 Massachusetts Avenue, E14/E15');
|
||||
const cityPromise = cityInput.sendKeys('Cambridge');
|
||||
const statePromise = driver.findElement(seleniumWebdriver.By.xpath('//select[@name="address.state"]' +
|
||||
'/option[@value="us-ma"]')).click();
|
||||
var zipPromise = zipCodeInput.sendKeys('02139');
|
||||
const zipPromise = zipCodeInput.sendKeys('02139');
|
||||
return Promise.all([addressPromise, cityPromise, statePromise, zipPromise]) // eslint-disable-line no-undef
|
||||
.then(function () {
|
||||
nextStepButton.click().then(function () {
|
||||
.then(() => {
|
||||
nextStepButton.click().then(() => {
|
||||
driver.wait(seleniumWebdriver.until
|
||||
.elementLocated(seleniumWebdriver.By.className('usescratch-step')));
|
||||
});
|
||||
|
@ -4,27 +4,27 @@
|
||||
* Test cases: https://github.com/LLK/scratch-www/wiki/Testing-Scratch-www#All_Test_Cases_Teacher_Join_Flow
|
||||
*/
|
||||
require('chromedriver');
|
||||
var seleniumWebdriver = require('selenium-webdriver');
|
||||
var tap = require('tap');
|
||||
const seleniumWebdriver = require('selenium-webdriver');
|
||||
const tap = require('tap');
|
||||
|
||||
var utils = require('./teacher_registration_utils.js');
|
||||
var constants = utils.constants;
|
||||
const utils = require('./teacher_registration_utils.js');
|
||||
const constants = utils.constants;
|
||||
|
||||
// Set test url through environment variable
|
||||
var rootUrl = process.env.ROOT_URL || 'http://localhost:8333';
|
||||
const rootUrl = process.env.ROOT_URL || 'http://localhost:8333';
|
||||
|
||||
// chrome driver
|
||||
var driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome())
|
||||
const driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome())
|
||||
.build();
|
||||
|
||||
tap.plan(2);
|
||||
|
||||
tap.tearDown(function () {
|
||||
tap.tearDown(() => {
|
||||
driver.quit();
|
||||
});
|
||||
|
||||
tap.beforeEach(function () {
|
||||
driver.get(rootUrl + '/educators/register');
|
||||
driver.get(`${rootUrl}/educators/register`);
|
||||
return utils.fillUsernameSlide(driver, seleniumWebdriver)
|
||||
.then(utils.fillDemographicsSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this
|
||||
.then(utils.fillNameSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this
|
||||
@ -33,26 +33,26 @@ tap.beforeEach(function () {
|
||||
});
|
||||
|
||||
// Selects Vatican City as the country, and checks that the state dropdown disappears
|
||||
tap.test('checkStateDropdownOnlyPresentWhenNeeded', function (t) {
|
||||
tap.test('checkStateDropdownOnlyPresentWhenNeeded', t => {
|
||||
driver.findElement(seleniumWebdriver.By.xpath('//select[@name="address.country"]' +
|
||||
'/option[@value="va"]')).click() // select Vatican City as the country
|
||||
.then(function () {
|
||||
.then(() => {
|
||||
driver.findElements(seleniumWebdriver.By.name('address.state'))
|
||||
.then(function (stateDropdown) {
|
||||
.then(stateDropdown => {
|
||||
t.equal(stateDropdown.length, 0);
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
tap.test('checkZipCodeRequired', function (t) {
|
||||
var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath));
|
||||
var errorMessageXPath = '//input[@name="address.zip"]/following-sibling::' +
|
||||
tap.test('checkZipCodeRequired', t => {
|
||||
const nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath));
|
||||
const errorMessageXPath = '//input[@name="address.zip"]/following-sibling::' +
|
||||
'span[@class="help-block validation-message"]/span[contains(text(),' +
|
||||
'"This field is required")]';
|
||||
nextStepButton.click().then(function () {
|
||||
nextStepButton.click().then(() => {
|
||||
driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath))
|
||||
.then(function (validationMessages) {
|
||||
.then(validationMessages => {
|
||||
t.equal(validationMessages.length, 1);
|
||||
t.end();
|
||||
});
|
||||
|
@ -4,41 +4,41 @@
|
||||
* Test cases: https://github.com/LLK/scratch-www/wiki/Testing-Scratch-www#All_Test_Cases_Teacher_Join_Flow
|
||||
*/
|
||||
require('chromedriver');
|
||||
var seleniumWebdriver = require('selenium-webdriver');
|
||||
var tap = require('tap');
|
||||
const seleniumWebdriver = require('selenium-webdriver');
|
||||
const tap = require('tap');
|
||||
|
||||
var utils = require('./teacher_registration_utils.js');
|
||||
var constants = utils.constants;
|
||||
const utils = require('./teacher_registration_utils.js');
|
||||
const constants = utils.constants;
|
||||
|
||||
// Set test url through environment variable
|
||||
var rootUrl = process.env.ROOT_URL || 'http://localhost:8333';
|
||||
const rootUrl = process.env.ROOT_URL || 'http://localhost:8333';
|
||||
|
||||
// chrome driver
|
||||
var driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome())
|
||||
const driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome())
|
||||
.build();
|
||||
|
||||
tap.plan(2);
|
||||
|
||||
tap.tearDown(function () {
|
||||
tap.tearDown(() => {
|
||||
driver.quit();
|
||||
});
|
||||
|
||||
tap.beforeEach(function () {
|
||||
driver.get(rootUrl + '/educators/register');
|
||||
tap.beforeEach(() => {
|
||||
driver.get(`${rootUrl}/educators/register`);
|
||||
return utils.fillUsernameSlide(driver, seleniumWebdriver);
|
||||
});
|
||||
|
||||
// if the user selects the other gender option, they must input a gender
|
||||
// selects the other gender option and attempt to advance the slide
|
||||
tap.test('checkOtherGenderInput', function (t) {
|
||||
var otherGenderRadio = driver.findElement(seleniumWebdriver.By.xpath('//input[@value="other"' +
|
||||
tap.test('checkOtherGenderInput', t => {
|
||||
const otherGenderRadio = driver.findElement(seleniumWebdriver.By.xpath('//input[@value="other"' +
|
||||
'and @type="radio"]'));
|
||||
var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath));
|
||||
const nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath));
|
||||
driver.findElement(seleniumWebdriver.By.xpath('//select[@name="user.country"]/option[2]')).click();
|
||||
otherGenderRadio.click().then(function () {
|
||||
nextStepButton.click().then(function () {
|
||||
otherGenderRadio.click().then(() => {
|
||||
nextStepButton.click().then(() => {
|
||||
driver.findElements(seleniumWebdriver.By.xpath(constants.generalErrorMessageXpath))
|
||||
.then(function (validationMessages) {
|
||||
.then(validationMessages => {
|
||||
t.equal(validationMessages.length, 1);
|
||||
t.end();
|
||||
});
|
||||
@ -48,12 +48,12 @@ tap.test('checkOtherGenderInput', function (t) {
|
||||
|
||||
// the user must select a gender
|
||||
// tries to advance the slide without selecting a gender
|
||||
tap.test('checkNoGenderInput', function (t) {
|
||||
var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath));
|
||||
tap.test('checkNoGenderInput', t => {
|
||||
const nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath));
|
||||
driver.findElement(seleniumWebdriver.By.xpath('//select[@name="user.country"]/option[2]')).click();
|
||||
nextStepButton.click().then(function () {
|
||||
nextStepButton.click().then(() => {
|
||||
driver.findElements(seleniumWebdriver.By.xpath(constants.generalErrorMessageXpath))
|
||||
.then(function (validationMessages) {
|
||||
.then(validationMessages => {
|
||||
t.equal(validationMessages.length, 1);
|
||||
t.end();
|
||||
});
|
||||
|
@ -4,40 +4,40 @@
|
||||
* Test cases: https://github.com/LLK/scratch-www/wiki/Testing-Scratch-www#All_Test_Cases_Teacher_Join_Flow
|
||||
*/
|
||||
require('chromedriver');
|
||||
var seleniumWebdriver = require('selenium-webdriver');
|
||||
var tap = require('tap');
|
||||
const seleniumWebdriver = require('selenium-webdriver');
|
||||
const tap = require('tap');
|
||||
|
||||
var utils = require('./teacher_registration_utils.js');
|
||||
var constants = utils.constants;
|
||||
const utils = require('./teacher_registration_utils.js');
|
||||
const constants = utils.constants;
|
||||
|
||||
// Set test url through environment variable
|
||||
var rootUrl = process.env.ROOT_URL || 'http://localhost:8333';
|
||||
const rootUrl = process.env.ROOT_URL || 'http://localhost:8333';
|
||||
|
||||
// chrome driver
|
||||
var driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome())
|
||||
const driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome())
|
||||
.build();
|
||||
|
||||
tap.plan(2);
|
||||
|
||||
tap.tearDown(function () {
|
||||
tap.tearDown(() => {
|
||||
driver.quit();
|
||||
});
|
||||
|
||||
tap.beforeEach(function () {
|
||||
driver.get(rootUrl + '/educators/register');
|
||||
driver.get(`${rootUrl}/educators/register`);
|
||||
return utils.fillUsernameSlide(driver, seleniumWebdriver)
|
||||
.then(utils.fillDemographicsSlide.bind(this, driver, seleniumWebdriver)); // eslint-disable-line no-invalid-this
|
||||
});
|
||||
|
||||
// attempts to advance the slide without inputting either name, checks that both give the correct error
|
||||
tap.test('checkFirstNameRequired', function (t) {
|
||||
var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath));
|
||||
var errorMessageXPath = '//input[@name="user.name.first"]/following-sibling::' +
|
||||
tap.test('checkFirstNameRequired', t => {
|
||||
const nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath));
|
||||
const errorMessageXPath = '//input[@name="user.name.first"]/following-sibling::' +
|
||||
'span[@class="help-block validation-message"]/span[contains(text(),' +
|
||||
'"This field is required")]';
|
||||
nextStepButton.click().then(function () {
|
||||
nextStepButton.click().then(() => {
|
||||
driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath))
|
||||
.then(function (validationMessages) {
|
||||
.then(validationMessages => {
|
||||
t.equal(validationMessages.length, 1);
|
||||
t.end();
|
||||
});
|
||||
@ -45,14 +45,14 @@ tap.test('checkFirstNameRequired', function (t) {
|
||||
});
|
||||
|
||||
// attempts to advance the slide without inputting either name, checks that both give the correct error
|
||||
tap.test('checkLastNameRequired', function (t) {
|
||||
var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath));
|
||||
var errorMessageXPath = '//input[@name="user.name.last"]/following-sibling::' +
|
||||
tap.test('checkLastNameRequired', t => {
|
||||
const nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath));
|
||||
const errorMessageXPath = '//input[@name="user.name.last"]/following-sibling::' +
|
||||
'span[@class="help-block validation-message"]/span[contains(text(),' +
|
||||
'"This field is required")]';
|
||||
nextStepButton.click().then(function () {
|
||||
nextStepButton.click().then(() => {
|
||||
driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath))
|
||||
.then(function (validationMessages) {
|
||||
.then(validationMessages => {
|
||||
t.equal(validationMessages.length, 1);
|
||||
t.end();
|
||||
});
|
||||
|
@ -4,41 +4,41 @@
|
||||
* Test cases: https://github.com/LLK/scratch-www/wiki/Testing-Scratch-www#All_Test_Cases_Teacher_Join_Flow
|
||||
*/
|
||||
require('chromedriver');
|
||||
var seleniumWebdriver = require('selenium-webdriver');
|
||||
var tap = require('tap');
|
||||
const seleniumWebdriver = require('selenium-webdriver');
|
||||
const tap = require('tap');
|
||||
|
||||
var utils = require('./teacher_registration_utils.js');
|
||||
var constants = utils.constants;
|
||||
const utils = require('./teacher_registration_utils.js');
|
||||
const constants = utils.constants;
|
||||
|
||||
// Set test url through environment variable
|
||||
var rootUrl = process.env.ROOT_URL || 'http://localhost:8333';
|
||||
const rootUrl = process.env.ROOT_URL || 'http://localhost:8333';
|
||||
|
||||
// chrome driver
|
||||
var driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome())
|
||||
const driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome())
|
||||
.build();
|
||||
|
||||
tap.plan(4);
|
||||
|
||||
tap.tearDown(function () {
|
||||
tap.tearDown(() => {
|
||||
driver.quit();
|
||||
});
|
||||
|
||||
tap.beforeEach(function () {
|
||||
driver.get(rootUrl + '/educators/register');
|
||||
driver.get(`${rootUrl}/educators/register`);
|
||||
return utils.fillUsernameSlide(driver, seleniumWebdriver)
|
||||
.then(utils.fillDemographicsSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this
|
||||
.then(utils.fillNameSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this
|
||||
.then(utils.fillPhoneSlide.bind(this, driver, seleniumWebdriver)); // eslint-disable-line no-invalid-this
|
||||
});
|
||||
|
||||
tap.test('otherFieldRequiredIfChecked', function (t) {
|
||||
var otherCheckbox = driver.findElement(seleniumWebdriver.By.xpath('//input[@type="checkbox" and @value="8"]'));
|
||||
var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath));
|
||||
var errorMessageXPath = '//div[@class="other-input"]' + constants.generalErrorMessageXpath;
|
||||
otherCheckbox.click().then(function () {
|
||||
nextStepButton.click().then(function () {
|
||||
tap.test('otherFieldRequiredIfChecked', t => {
|
||||
const otherCheckbox = driver.findElement(seleniumWebdriver.By.xpath('//input[@type="checkbox" and @value="8"]'));
|
||||
const nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath));
|
||||
const errorMessageXPath = `//div[@class="other-input"]${constants.generalErrorMessageXpath}`;
|
||||
otherCheckbox.click().then(() => {
|
||||
nextStepButton.click().then(() => {
|
||||
driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath))
|
||||
.then(function (validationMessages) {
|
||||
.then(validationMessages => {
|
||||
t.equal(validationMessages.length, 1);
|
||||
t.end();
|
||||
});
|
||||
@ -46,42 +46,42 @@ tap.test('otherFieldRequiredIfChecked', function (t) {
|
||||
});
|
||||
});
|
||||
|
||||
tap.test('checkOrganizationFieldRequired', function (t) {
|
||||
var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath));
|
||||
var errorMessageXPath = '//input[@name="organization.name"]/following-sibling::' +
|
||||
tap.test('checkOrganizationFieldRequired', t => {
|
||||
const nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath));
|
||||
const errorMessageXPath = '//input[@name="organization.name"]/following-sibling::' +
|
||||
'span[@class="help-block validation-message"]/span[contains(text(),' +
|
||||
'"This field is required")]';
|
||||
nextStepButton.click().then(function () {
|
||||
nextStepButton.click().then(() => {
|
||||
driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath))
|
||||
.then(function (validationMessages) {
|
||||
.then(validationMessages => {
|
||||
t.equal(validationMessages.length, 1);
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
tap.test('checkRoleFieldRequired', function (t) {
|
||||
var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath));
|
||||
var errorMessageXPath = '//input[@name="organization.title"]/following-sibling::' +
|
||||
tap.test('checkRoleFieldRequired', t => {
|
||||
const nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath));
|
||||
const errorMessageXPath = '//input[@name="organization.title"]/following-sibling::' +
|
||||
'span[@class="help-block validation-message"]/span[contains(text(),' +
|
||||
'"This field is required")]';
|
||||
nextStepButton.click().then(function () {
|
||||
nextStepButton.click().then(() => {
|
||||
driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath))
|
||||
.then(function (validationMessages) {
|
||||
.then(validationMessages => {
|
||||
t.equal(validationMessages.length, 1);
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
tap.test('checkOrganizationTypeRequired', function (t) {
|
||||
var nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath));
|
||||
var errorMessageXPath = '//div[@class="checkbox"]/following-sibling::' +
|
||||
tap.test('checkOrganizationTypeRequired', t => {
|
||||
const nextStepButton = driver.findElement(seleniumWebdriver.By.xpath(constants.nextStepXpath));
|
||||
const errorMessageXPath = '//div[@class="checkbox"]/following-sibling::' +
|
||||
'span[@class="help-block validation-message" and contains(text(),' +
|
||||
'"This field is required")]';
|
||||
nextStepButton.click().then(function () {
|
||||
nextStepButton.click().then(() => {
|
||||
driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath))
|
||||
.then(function (validationMessages) {
|
||||
.then(validationMessages => {
|
||||
t.equal(validationMessages.length, 1);
|
||||
t.end();
|
||||
});
|
||||
|
@ -4,40 +4,40 @@
|
||||
* Test cases: https://github.com/LLK/scratch-www/wiki/Testing-Scratch-www#All_Test_Cases_Teacher_Join_Flow
|
||||
*/
|
||||
require('chromedriver');
|
||||
var seleniumWebdriver = require('selenium-webdriver');
|
||||
var tap = require('tap');
|
||||
const seleniumWebdriver = require('selenium-webdriver');
|
||||
const tap = require('tap');
|
||||
|
||||
var utils = require('./teacher_registration_utils.js');
|
||||
const utils = require('./teacher_registration_utils.js');
|
||||
|
||||
// Set test url through environment variable
|
||||
var rootUrl = process.env.ROOT_URL || 'http://localhost:8333';
|
||||
const rootUrl = process.env.ROOT_URL || 'http://localhost:8333';
|
||||
|
||||
// chrome driver
|
||||
var driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome())
|
||||
const driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome())
|
||||
.build();
|
||||
|
||||
tap.plan(1);
|
||||
|
||||
tap.tearDown(function () {
|
||||
tap.tearDown(() => {
|
||||
driver.quit();
|
||||
});
|
||||
|
||||
tap.beforeEach(function () {
|
||||
driver.get(rootUrl + '/educators/register');
|
||||
driver.get(`${rootUrl}/educators/register`);
|
||||
return utils.fillUsernameSlide(driver, seleniumWebdriver)
|
||||
.then(utils.fillDemographicsSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this
|
||||
.then(utils.fillNameSlide.bind(this, driver, seleniumWebdriver)); // eslint-disable-line no-invalid-this
|
||||
});
|
||||
|
||||
// inputs an invalid phone number and checks that the correct error message appears
|
||||
tap.test('validatePhoneNumber', function (t) {
|
||||
var phoneInput = driver.findElement(seleniumWebdriver.By.xpath('//input[@type="tel"]'));
|
||||
var errorMessage = 'Please enter a valid phone number';
|
||||
var errorMessageXPath = '//span[@class="help-block validation-message"]/span[contains(text(),"' +
|
||||
errorMessage + '")]';
|
||||
phoneInput.sendKeys(1234567890).then(function () {
|
||||
tap.test('validatePhoneNumber', t => {
|
||||
const phoneInput = driver.findElement(seleniumWebdriver.By.xpath('//input[@type="tel"]'));
|
||||
const errorMessage = 'Please enter a valid phone number';
|
||||
const errorMessageXPath = `//span[@class="help-block validation-message"]/span[contains(text(),"${
|
||||
errorMessage}")]`;
|
||||
phoneInput.sendKeys(1234567890).then(() => {
|
||||
driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath))
|
||||
.then(function (validationMessages) {
|
||||
.then(validationMessages => {
|
||||
t.equal(validationMessages.length, 1);
|
||||
t.end();
|
||||
});
|
||||
|
@ -5,37 +5,35 @@
|
||||
*/
|
||||
|
||||
require('chromedriver');
|
||||
var seleniumWebdriver = require('selenium-webdriver');
|
||||
var tap = require('tap');
|
||||
const seleniumWebdriver = require('selenium-webdriver');
|
||||
const tap = require('tap');
|
||||
|
||||
// Set test url through environment variable
|
||||
var rootUrl = process.env.ROOT_URL || 'http://localhost:8333';
|
||||
const rootUrl = process.env.ROOT_URL || 'http://localhost:8333';
|
||||
|
||||
// chrome driver
|
||||
var driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome())
|
||||
const driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome())
|
||||
.build();
|
||||
|
||||
tap.plan(5);
|
||||
|
||||
tap.tearDown(function () {
|
||||
tap.tearDown(() => {
|
||||
driver.quit();
|
||||
});
|
||||
|
||||
tap.beforeEach(function () {
|
||||
return driver.get(rootUrl + '/educators/register');
|
||||
});
|
||||
tap.beforeEach(() => driver.get(`${rootUrl}/educators/register`));
|
||||
|
||||
// an error message should appear for a username less than 3 characters long
|
||||
// input a username less than 3 characters and look for the validation message
|
||||
tap.test('checkAtLeastThreeCharacters', function (t) {
|
||||
tap.test('checkAtLeastThreeCharacters', t => {
|
||||
// open scratch in a new instance of the browser
|
||||
driver.get('https://scratch.mit.edu/educators/register');
|
||||
var usernameInput = driver.findElement(seleniumWebdriver.By.name('user.username'));
|
||||
var errorMessage = 'Usernames must be at least 3 characters';
|
||||
var errorMessageXPath = '//span[@class="help-block validation-message" and contains(text(),"' +
|
||||
errorMessage + '")]';
|
||||
usernameInput.sendKeys('hi').then(function () {
|
||||
driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)).then(function (validationMessages) {
|
||||
const usernameInput = driver.findElement(seleniumWebdriver.By.name('user.username'));
|
||||
const errorMessage = 'Usernames must be at least 3 characters';
|
||||
const errorMessageXPath = `//span[@class="help-block validation-message" and contains(text(),"${
|
||||
errorMessage}")]`;
|
||||
usernameInput.sendKeys('hi').then(() => {
|
||||
driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)).then(validationMessages => {
|
||||
t.equal(validationMessages.length, 1);
|
||||
t.end();
|
||||
});
|
||||
@ -44,16 +42,16 @@ tap.test('checkAtLeastThreeCharacters', function (t) {
|
||||
|
||||
// usernames have to be unique
|
||||
// input a username that exists and check that an error message appears
|
||||
tap.test('checkUsernameExistsError', function (t) {
|
||||
var usernameInput = driver.findElement(seleniumWebdriver.By.name('user.username'));
|
||||
var passwordInput = driver.findElement(seleniumWebdriver.By.name('user.password'));
|
||||
var inputUsername = usernameInput.sendKeys('mres');
|
||||
var passwordClick = passwordInput.click();
|
||||
var errorMessage = 'Sorry, that username already exists';
|
||||
var errorMessageXPath = '//span[@class="help-block validation-message" and contains(text(),"' +
|
||||
errorMessage + '")]';
|
||||
Promise.all([inputUsername, passwordClick]).then(function () { // eslint-disable-line no-undef
|
||||
var errorBubble = driver.wait(seleniumWebdriver.until
|
||||
tap.test('checkUsernameExistsError', t => {
|
||||
const usernameInput = driver.findElement(seleniumWebdriver.By.name('user.username'));
|
||||
const passwordInput = driver.findElement(seleniumWebdriver.By.name('user.password'));
|
||||
const inputUsername = usernameInput.sendKeys('mres');
|
||||
const passwordClick = passwordInput.click();
|
||||
const errorMessage = 'Sorry, that username already exists';
|
||||
const errorMessageXPath = `//span[@class="help-block validation-message" and contains(text(),"${
|
||||
errorMessage}")]`;
|
||||
Promise.all([inputUsername, passwordClick]).then(() => { // eslint-disable-line no-undef
|
||||
const errorBubble = driver.wait(seleniumWebdriver.until
|
||||
.elementLocated(seleniumWebdriver.By.xpath(errorMessageXPath)), 10000);
|
||||
t.notEqual(errorBubble, undefined); // eslint-disable-line no-undefined
|
||||
t.end();
|
||||
@ -62,13 +60,13 @@ tap.test('checkUsernameExistsError', function (t) {
|
||||
|
||||
// passwords must be at least 6 characters
|
||||
// find the validation message if the input password is less than 6 characters
|
||||
tap.test('checkPasswordAtLeastSixCharacters', function (t) {
|
||||
var passwordInput = driver.findElement(seleniumWebdriver.By.name('user.password'));
|
||||
var errorMessage = 'Passwords must be at least six characters';
|
||||
var errorMessageXPath = '//span[@class="help-block validation-message" and contains(text(),"' +
|
||||
errorMessage + '")]';
|
||||
passwordInput.sendKeys('hello').then(function () {
|
||||
driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)).then(function (validationMessages) {
|
||||
tap.test('checkPasswordAtLeastSixCharacters', t => {
|
||||
const passwordInput = driver.findElement(seleniumWebdriver.By.name('user.password'));
|
||||
const errorMessage = 'Passwords must be at least six characters';
|
||||
const errorMessageXPath = `//span[@class="help-block validation-message" and contains(text(),"${
|
||||
errorMessage}")]`;
|
||||
passwordInput.sendKeys('hello').then(() => {
|
||||
driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)).then(validationMessages => {
|
||||
t.equal(validationMessages.length, 1);
|
||||
t.end();
|
||||
});
|
||||
@ -77,15 +75,15 @@ tap.test('checkPasswordAtLeastSixCharacters', function (t) {
|
||||
|
||||
// password cannot be "password"
|
||||
// find the validation message if the user inputs "password"
|
||||
tap.test('checkPasswordNotPassword', function (t) {
|
||||
tap.test('checkPasswordNotPassword', t => {
|
||||
driver.get('https://scratch.mit.edu/educators/register');
|
||||
var passwordInput = driver.findElement(seleniumWebdriver.By.name('user.password'));
|
||||
const passwordInput = driver.findElement(seleniumWebdriver.By.name('user.password'));
|
||||
// keeping "password" in messed with the xPath, may need to find a better way
|
||||
var errorMessage = 'Your password may not be';
|
||||
var errorMessageXPath = '//span[@class="help-block validation-message" and contains(text(),"' +
|
||||
errorMessage + '")]';
|
||||
passwordInput.sendKeys('password').then(function () {
|
||||
driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)).then(function (validationMessages) {
|
||||
const errorMessage = 'Your password may not be';
|
||||
const errorMessageXPath = `//span[@class="help-block validation-message" and contains(text(),"${
|
||||
errorMessage}")]`;
|
||||
passwordInput.sendKeys('password').then(() => {
|
||||
driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)).then(validationMessages => {
|
||||
t.equal(validationMessages.length, 1);
|
||||
t.end();
|
||||
});
|
||||
@ -94,18 +92,18 @@ tap.test('checkPasswordNotPassword', function (t) {
|
||||
|
||||
// the username and password cannot be the same
|
||||
// find the validation message if the username and password match
|
||||
tap.test('checkPasswordNotUsername', function (t) {
|
||||
tap.test('checkPasswordNotUsername', t => {
|
||||
driver.get('https://scratch.mit.edu/educators/register');
|
||||
var passwordInput = driver.findElement(seleniumWebdriver.By.name('user.password'));
|
||||
var usernameInput = driver.findElement(seleniumWebdriver.By.name('user.username'));
|
||||
var errorMessage = 'Your password may not be your username';
|
||||
var errorMessageXPath = '//span[@class="help-block validation-message" and contains(text(),"' +
|
||||
errorMessage + '")]';
|
||||
var usernamePromise = usernameInput.sendKeys('educator');
|
||||
var passwordPromise = passwordInput.sendKeys('educator');
|
||||
const passwordInput = driver.findElement(seleniumWebdriver.By.name('user.password'));
|
||||
const usernameInput = driver.findElement(seleniumWebdriver.By.name('user.username'));
|
||||
const errorMessage = 'Your password may not be your username';
|
||||
const errorMessageXPath = `//span[@class="help-block validation-message" and contains(text(),"${
|
||||
errorMessage}")]`;
|
||||
const usernamePromise = usernameInput.sendKeys('educator');
|
||||
const passwordPromise = passwordInput.sendKeys('educator');
|
||||
// wait for both inputs to have the same text, and check for validation message
|
||||
Promise.all([usernamePromise, passwordPromise]).then(function () { // eslint-disable-line no-undef
|
||||
driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)).then(function (validationMessages) {
|
||||
Promise.all([usernamePromise, passwordPromise]).then(() => { // eslint-disable-line no-undef
|
||||
driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)).then(validationMessages => {
|
||||
// there should be only one validation message
|
||||
t.equal(validationMessages.length, 1);
|
||||
t.end();
|
||||
|
@ -4,27 +4,27 @@
|
||||
* Test cases: https://github.com/LLK/scratch-www/wiki/Testing-Scratch-www#All_Test_Cases_Teacher_Join_Flow
|
||||
*/
|
||||
require('chromedriver');
|
||||
var seleniumWebdriver = require('selenium-webdriver');
|
||||
var tap = require('tap');
|
||||
const seleniumWebdriver = require('selenium-webdriver');
|
||||
const tap = require('tap');
|
||||
|
||||
var utils = require('./teacher_registration_utils.js');
|
||||
var constants = utils.constants;
|
||||
const utils = require('./teacher_registration_utils.js');
|
||||
const constants = utils.constants;
|
||||
|
||||
// Set test url through environment variable
|
||||
var rootUrl = process.env.ROOT_URL || 'http://localhost:8333';
|
||||
const rootUrl = process.env.ROOT_URL || 'http://localhost:8333';
|
||||
|
||||
// chrome driver
|
||||
var driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome())
|
||||
const driver = new seleniumWebdriver.Builder().withCapabilities(seleniumWebdriver.Capabilities.chrome())
|
||||
.build();
|
||||
|
||||
tap.plan(3);
|
||||
|
||||
tap.tearDown(function () {
|
||||
tap.tearDown(() => {
|
||||
driver.quit();
|
||||
});
|
||||
|
||||
tap.beforeEach(function () {
|
||||
driver.get(rootUrl + '/educators/register');
|
||||
driver.get(`${rootUrl}/educators/register`);
|
||||
return utils.fillUsernameSlide(driver, seleniumWebdriver)
|
||||
.then(utils.fillDemographicsSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this
|
||||
.then(utils.fillNameSlide.bind(this, driver, seleniumWebdriver)) // eslint-disable-line no-invalid-this
|
||||
@ -33,11 +33,11 @@ tap.beforeEach(function () {
|
||||
.then(utils.fillAddressSlide.bind(this, driver, seleniumWebdriver)); // eslint-disable-line no-invalid-this
|
||||
});
|
||||
|
||||
tap.test('checkCharacterCountIsCorrect', function (t) {
|
||||
var textarea = driver.findElement(seleniumWebdriver.By.name('useScratch'));
|
||||
var charCount = driver.findElement(seleniumWebdriver.By.xpath('//p[@class="char-count"]'));
|
||||
textarea.sendKeys('hello').then(function () {
|
||||
charCount.getText().then(function (charCountText) {
|
||||
tap.test('checkCharacterCountIsCorrect', t => {
|
||||
const textarea = driver.findElement(seleniumWebdriver.By.name('useScratch'));
|
||||
const charCount = driver.findElement(seleniumWebdriver.By.xpath('//p[@class="char-count"]'));
|
||||
textarea.sendKeys('hello').then(() => {
|
||||
charCount.getText().then(charCountText => {
|
||||
t.equal(charCountText, '5/300');
|
||||
t.end();
|
||||
});
|
||||
@ -46,24 +46,24 @@ tap.test('checkCharacterCountIsCorrect', function (t) {
|
||||
|
||||
// Inputs more than 300 characters and checks that the char count gets the class 'overmax'
|
||||
// which turns the text orange
|
||||
tap.test('checkCharacterCountTurnsOrangeWhenTooLong', function (t) {
|
||||
var textarea = driver.findElement(seleniumWebdriver.By.name('useScratch'));
|
||||
var charCount = driver.findElement(seleniumWebdriver.By.xpath('//p[@class="char-count"]'));
|
||||
textarea.sendKeys(constants.loremIpsumTextLong).then(function () {
|
||||
charCount.getAttribute('class').then(function (charCountClasses) {
|
||||
tap.test('checkCharacterCountTurnsOrangeWhenTooLong', t => {
|
||||
const textarea = driver.findElement(seleniumWebdriver.By.name('useScratch'));
|
||||
const charCount = driver.findElement(seleniumWebdriver.By.xpath('//p[@class="char-count"]'));
|
||||
textarea.sendKeys(constants.loremIpsumTextLong).then(() => {
|
||||
charCount.getAttribute('class').then(charCountClasses => {
|
||||
t.ok(charCountClasses.includes('overmax'));
|
||||
t.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
tap.test('checkCharacterCountErrorAppersWhenTooLong', function (t) {
|
||||
var textarea = driver.findElement(seleniumWebdriver.By.name('useScratch'));
|
||||
var errorMessage = 'Description must be at most 300 characters';
|
||||
var errorMessageXPath = '//span[@class="help-block validation-message" and contains(text(),"' +
|
||||
errorMessage + '")]';
|
||||
textarea.sendKeys(constants.loremIpsumTextLong).then(function () {
|
||||
driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)).then(function (validationMessages) {
|
||||
tap.test('checkCharacterCountErrorAppersWhenTooLong', t => {
|
||||
const textarea = driver.findElement(seleniumWebdriver.By.name('useScratch'));
|
||||
const errorMessage = 'Description must be at most 300 characters';
|
||||
const errorMessageXPath = `//span[@class="help-block validation-message" and contains(text(),"${
|
||||
errorMessage}")]`;
|
||||
textarea.sendKeys(constants.loremIpsumTextLong).then(() => {
|
||||
driver.findElements(seleniumWebdriver.By.xpath(errorMessageXPath)).then(validationMessages => {
|
||||
t.equal(validationMessages.length, 1);
|
||||
t.end();
|
||||
});
|
||||
|
@ -12,48 +12,48 @@ const {
|
||||
} = new SeleniumHelper();
|
||||
|
||||
// Using 1 and 2 here. Hopefully this is not confusing.
|
||||
let username1 = process.env.SMOKE_USERNAME + '4';
|
||||
let username2 = process.env.SMOKE_USERNAME + '5';
|
||||
let password = process.env.SMOKE_PASSWORD;
|
||||
let rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
const username1 = `${process.env.SMOKE_USERNAME}4`;
|
||||
const username2 = `${process.env.SMOKE_USERNAME}5`;
|
||||
const password = process.env.SMOKE_PASSWORD;
|
||||
const rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
|
||||
// project for comments (owned by username2)
|
||||
let projectId = process.env.COMMENT_PROJECT_ID || 1300008409;
|
||||
let projectUrl = `${rootUrl}/projects/${projectId}`;
|
||||
const projectId = process.env.COMMENT_PROJECT_ID || 1300008409;
|
||||
const projectUrl = `${rootUrl}/projects/${projectId}`;
|
||||
|
||||
// profile for comments (username2)
|
||||
let profileUrl = `${rootUrl}/users/${username2}`;
|
||||
const profileUrl = `${rootUrl}/users/${username2}`;
|
||||
|
||||
// studio for comments (hosted by username2) comments tab
|
||||
let studioId = process.env.COMMENT_STUDIO_ID || 10005646;
|
||||
let studioUrl = `${rootUrl}/studios/${studioId}/comments`;
|
||||
const studioId = process.env.COMMENT_STUDIO_ID || 10005646;
|
||||
const studioUrl = `${rootUrl}/studios/${studioId}/comments`;
|
||||
|
||||
// setup comments to leave
|
||||
let date = new Date();
|
||||
let dateString = `Y:${date.getFullYear()} - M:${date.getMonth() + 1} - D:${date.getDate()} ` +
|
||||
const date = new Date();
|
||||
const dateString = `Y:${date.getFullYear()} - M:${date.getMonth() + 1} - D:${date.getDate()} ` +
|
||||
`: ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`;
|
||||
let buildNumber = process.env.CIRCLE_BUILD_NUM || dateString;
|
||||
let projectComment = buildNumber + ' project';
|
||||
let profileComment = buildNumber + ' profile';
|
||||
let studioComment = buildNumber + ' studio';
|
||||
const buildNumber = process.env.CIRCLE_BUILD_NUM || dateString;
|
||||
const projectComment = `${buildNumber} project`;
|
||||
const profileComment = `${buildNumber} profile`;
|
||||
const studioComment = `${buildNumber} studio`;
|
||||
|
||||
let projectReply = projectComment + ' reply';
|
||||
let profileReply = profileComment + ' reply';
|
||||
let studioReply = studioComment + ' reply';
|
||||
const projectReply = `${projectComment} reply`;
|
||||
const profileReply = `${profileComment} reply`;
|
||||
const studioReply = `${studioComment} reply`;
|
||||
|
||||
jest.setTimeout(60000);
|
||||
|
||||
let driver;
|
||||
|
||||
describe('comment tests', async () => {
|
||||
describe('comment tests', () => {
|
||||
beforeAll(async () => {
|
||||
driver = await buildDriver('www-integration project comments');
|
||||
await driver.get(rootUrl);
|
||||
});
|
||||
|
||||
afterAll(async () => await driver.quit());
|
||||
afterAll(() => driver.quit());
|
||||
|
||||
describe('leave comments', async () => {
|
||||
describe('leave comments', () => {
|
||||
beforeAll(async () => {
|
||||
await signIn(username1, password);
|
||||
await findByXpath('//span[contains(@class, "profile-name")]');
|
||||
@ -69,33 +69,32 @@ describe('comment tests', async () => {
|
||||
await driver.get(projectUrl);
|
||||
|
||||
// leave the comment
|
||||
let commentBox = await findByXpath('//textArea[@name="compose-comment"]');
|
||||
const commentBox = await findByXpath('//textArea[@name="compose-comment"]');
|
||||
await commentBox.sendKeys(projectComment);
|
||||
await findByXpath(`//textarea[contains(text(), "${projectComment}")]`);
|
||||
await clickXpath('//button[@class="button compose-post"]');
|
||||
|
||||
// find the comment
|
||||
let commentXpath = await `//div[@class="comment-bubble"]/span/span[contains(text(),` +
|
||||
` "${projectComment}")]`;
|
||||
let postedComment = await findByXpath(commentXpath);
|
||||
let commentVisible = await postedComment.isDisplayed();
|
||||
await expect(commentVisible).toBe(true);
|
||||
const commentXpath = `//div[@class="comment-bubble"]/span/span[contains(text(), "${projectComment}")]`;
|
||||
const postedComment = await findByXpath(commentXpath);
|
||||
const commentVisible = await postedComment.isDisplayed();
|
||||
expect(commentVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('leave comment on a profile', async () => {
|
||||
await driver.get(profileUrl);
|
||||
|
||||
// leave the comment
|
||||
let commentXpath = await '//form[@id="main-post-form"]/div/textArea';
|
||||
let commentArea = await findByXpath(commentXpath);
|
||||
const commentXpath = '//form[@id="main-post-form"]/div/textArea';
|
||||
const commentArea = await findByXpath(commentXpath);
|
||||
await commentArea.sendKeys(profileComment);
|
||||
await clickXpath('//div[@class="button small"]/a[contains(text(), "Post")]');
|
||||
|
||||
// find the comment
|
||||
let newComment = await findByXpath(`//div[@class="comment "]/div/div[contains(text(),` +
|
||||
const newComment = await findByXpath(`//div[@class="comment "]/div/div[contains(text(),` +
|
||||
` "${profileComment}")]`);
|
||||
let commentVisible = await newComment.isDisplayed();
|
||||
await expect(commentVisible).toBe(true);
|
||||
const commentVisible = await newComment.isDisplayed();
|
||||
expect(commentVisible).toBe(true);
|
||||
|
||||
// return to homepage to sign out with www
|
||||
await driver.get(rootUrl);
|
||||
@ -105,20 +104,20 @@ describe('comment tests', async () => {
|
||||
await driver.get(studioUrl);
|
||||
|
||||
// leave the comment
|
||||
let commentBox = await findByXpath('//textArea[@name="compose-comment"]');
|
||||
const commentBox = await findByXpath('//textArea[@name="compose-comment"]');
|
||||
await commentBox.sendKeys(studioComment);
|
||||
await findByXpath(`//textarea[contains(text(), "${studioComment}")]`);
|
||||
await clickXpath('//button[@class="button compose-post"]');
|
||||
|
||||
// find the comment
|
||||
let commentXpath = `//div[@class="comment-bubble"]/span/span[contains(text(), "${studioComment}")]`;
|
||||
let postedComment = await findByXpath(commentXpath);
|
||||
let commentVisible = await postedComment.isDisplayed();
|
||||
await expect(commentVisible).toBe(true);
|
||||
const commentXpath = `//div[@class="comment-bubble"]/span/span[contains(text(), "${studioComment}")]`;
|
||||
const postedComment = await findByXpath(commentXpath);
|
||||
const commentVisible = await postedComment.isDisplayed();
|
||||
expect(commentVisible).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('second user tests', async () => {
|
||||
describe('second user tests', () => {
|
||||
beforeAll(async () => {
|
||||
await signIn(username2, password);
|
||||
await findByXpath('//span[contains(@class, "profile-name")]');
|
||||
@ -126,157 +125,157 @@ describe('comment tests', async () => {
|
||||
|
||||
// get notifications
|
||||
test('get notification badge for comments', async () => {
|
||||
let messages = await findByXpath('//span[@class = "message-count show"]');
|
||||
let messagesVisible = await messages.isDisplayed();
|
||||
await expect(messagesVisible).toBe(true);
|
||||
const messages = await findByXpath('//span[@class = "message-count show"]');
|
||||
const messagesVisible = await messages.isDisplayed();
|
||||
expect(messagesVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('click notifications for comments', async () => {
|
||||
await clickXpath('//li[@class="link right messages"]');
|
||||
let messages = await findByXpath('//ul[@class="messages-social-list"]');
|
||||
let messagesVisible = await messages.isDisplayed();
|
||||
await expect(messagesVisible).toBe(true);
|
||||
const messages = await findByXpath('//ul[@class="messages-social-list"]');
|
||||
const messagesVisible = await messages.isDisplayed();
|
||||
expect(messagesVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('project comment message visible', async () => {
|
||||
await driver.get(rootUrl + '/messages');
|
||||
await driver.get(`${rootUrl}/messages`);
|
||||
|
||||
let projectMessageXpath = '//p[@class="emoji-text mod-comment" ' +
|
||||
const projectMessageXpath = '//p[@class="emoji-text mod-comment" ' +
|
||||
`and contains(text(), "${projectComment}")]`;
|
||||
let projectMessage = await findByXpath(projectMessageXpath);
|
||||
let projectMessageVisible = await projectMessage.isDisplayed();
|
||||
await expect(projectMessageVisible).toBe(true);
|
||||
const projectMessage = await findByXpath(projectMessageXpath);
|
||||
const projectMessageVisible = await projectMessage.isDisplayed();
|
||||
expect(projectMessageVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('profile comment message visible', async () => {
|
||||
await driver.get(rootUrl + '/messages');
|
||||
await driver.get(`${rootUrl}/messages`);
|
||||
|
||||
let profileMessageXpath = '//p[@class="emoji-text mod-comment" ' +
|
||||
const profileMessageXpath = '//p[@class="emoji-text mod-comment" ' +
|
||||
`and contains(text(), "${profileComment}")]`;
|
||||
let profileMessage = await findByXpath(profileMessageXpath);
|
||||
let profileMessageVisible = await profileMessage.isDisplayed();
|
||||
await expect(profileMessageVisible).toBe(true);
|
||||
const profileMessage = await findByXpath(profileMessageXpath);
|
||||
const profileMessageVisible = await profileMessage.isDisplayed();
|
||||
expect(profileMessageVisible).toBe(true);
|
||||
});
|
||||
|
||||
// studio comments do not send a notification
|
||||
|
||||
test('project message links you to project page', async () => {
|
||||
let projectLinkXpath = '//p[@class="emoji-text mod-comment" ' +
|
||||
const projectLinkXpath = '//p[@class="emoji-text mod-comment" ' +
|
||||
`and contains(text(), "${projectComment}")]/../../../p[@class = "comment-message-info"]/span/a[2]`;
|
||||
|
||||
await driver.get(rootUrl + '/messages');
|
||||
await driver.get(`${rootUrl}/messages`);
|
||||
await clickXpath(projectLinkXpath);
|
||||
|
||||
// find green flag overlay
|
||||
let gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]');
|
||||
const gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]');
|
||||
await gfOverlay.isDisplayed();
|
||||
});
|
||||
|
||||
test('project comment is on project page', async () => {
|
||||
let projectLinkXpath = '//p[@class="emoji-text mod-comment" ' +
|
||||
const projectLinkXpath = '//p[@class="emoji-text mod-comment" ' +
|
||||
`and contains(text(), "${projectComment}")]/../../../p[@class = "comment-message-info"]/span/a[2]`;
|
||||
|
||||
await driver.get(rootUrl + '/messages');
|
||||
await driver.get(`${rootUrl}/messages`);
|
||||
await clickXpath(projectLinkXpath);
|
||||
|
||||
let commentXpath = `//span[contains(text(), "${projectComment}")]`;
|
||||
let singleComment = await findByXpath(commentXpath);
|
||||
let commentVisible = await singleComment.isDisplayed();
|
||||
await expect(commentVisible).toBe(true);
|
||||
const commentXpath = `//span[contains(text(), "${projectComment}")]`;
|
||||
const singleComment = await findByXpath(commentXpath);
|
||||
const commentVisible = await singleComment.isDisplayed();
|
||||
expect(commentVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('project comment is highlighted', async () => {
|
||||
let projectLinkXpath = '//p[@class="emoji-text mod-comment" ' +
|
||||
const projectLinkXpath = '//p[@class="emoji-text mod-comment" ' +
|
||||
`and contains(text(), "${projectComment}")]/../../../p[@class = "comment-message-info"]/span/a[2]`;
|
||||
let containerXpath = `//span[contains(text(), "${projectComment}")]/../../../..`;
|
||||
const containerXpath = `//span[contains(text(), "${projectComment}")]/../../../..`;
|
||||
|
||||
await driver.get(rootUrl + '/messages');
|
||||
await driver.get(`${rootUrl}/messages`);
|
||||
await clickXpath(projectLinkXpath);
|
||||
|
||||
let commentContainer = await findByXpath(containerXpath);
|
||||
let isHighlighted = await containsClass(commentContainer, 'highlighted-comment');
|
||||
await expect(isHighlighted).toBe(true);
|
||||
const commentContainer = await findByXpath(containerXpath);
|
||||
const isHighlighted = await containsClass(commentContainer, 'highlighted-comment');
|
||||
expect(isHighlighted).toBe(true);
|
||||
});
|
||||
|
||||
test('profile message links you to profile page', async () => {
|
||||
let profileLinkXpath = await '//p[@class="emoji-text mod-comment" ' +
|
||||
const profileLinkXpath = '//p[@class="emoji-text mod-comment" ' +
|
||||
`and contains(text(), "${profileComment}")]/../../../` +
|
||||
`p[@class = "comment-message-info"]/span/a[2]`;
|
||||
await driver.get(rootUrl + '/messages');
|
||||
'p[@class = "comment-message-info"]/span/a[2]';
|
||||
await driver.get(`${rootUrl}/messages`);
|
||||
await clickXpath(profileLinkXpath);
|
||||
|
||||
// find profile data
|
||||
let profileDataXpath = '//div[@id="profile-data"]';
|
||||
let pathToUsername = '/div[@class="box-head"]/div[@class="header-text"]/h2';
|
||||
const profileDataXpath = '//div[@id="profile-data"]';
|
||||
const pathToUsername = '/div[@class="box-head"]/div[@class="header-text"]/h2';
|
||||
await findByXpath(profileDataXpath);
|
||||
|
||||
let header = await findByXpath(profileDataXpath + pathToUsername);
|
||||
let uname = await header.getText();
|
||||
await expect(uname).toBe(username2);
|
||||
const header = await findByXpath(profileDataXpath + pathToUsername);
|
||||
const uname = await header.getText();
|
||||
expect(uname).toBe(username2);
|
||||
});
|
||||
|
||||
test('profile comment is on profile page', async () => {
|
||||
let profileLinkXpath = await '//p[@class="emoji-text mod-comment" ' +
|
||||
const profileLinkXpath = '//p[@class="emoji-text mod-comment" ' +
|
||||
`and contains(text(), "${profileComment}")]/../../../` +
|
||||
`p[@class = "comment-message-info"]/span/a[2]`;
|
||||
await driver.get(rootUrl + '/messages');
|
||||
'p[@class = "comment-message-info"]/span/a[2]';
|
||||
await driver.get(`${rootUrl}/messages`);
|
||||
await clickXpath(profileLinkXpath);
|
||||
|
||||
// find comment
|
||||
let commentXpath = `//div[contains(text(), "${profileComment}")]`;
|
||||
let leftComment = await findByXpath(commentXpath);
|
||||
let commentVisible = await leftComment.isDisplayed();
|
||||
await expect(commentVisible).toBe(true);
|
||||
const commentXpath = `//div[contains(text(), "${profileComment}")]`;
|
||||
const leftComment = await findByXpath(commentXpath);
|
||||
const commentVisible = await leftComment.isDisplayed();
|
||||
expect(commentVisible).toBe(true);
|
||||
|
||||
});
|
||||
|
||||
test('profile comment is highlighted', async () => {
|
||||
let profileLinkXpath = await '//p[@class="emoji-text mod-comment" ' +
|
||||
const profileLinkXpath = '//p[@class="emoji-text mod-comment" ' +
|
||||
`and contains(text(), "${profileComment}")]/../../../` +
|
||||
`p[@class = "comment-message-info"]/span/a[2]`;
|
||||
await driver.get(rootUrl + '/messages');
|
||||
'p[@class = "comment-message-info"]/span/a[2]';
|
||||
await driver.get(`${rootUrl}/messages`);
|
||||
await clickXpath(profileLinkXpath);
|
||||
|
||||
// comment highlighted?
|
||||
let containerXpath = `//div[contains(text(), "${profileComment}")]/../../..`;
|
||||
let commentContainer = await findByXpath(containerXpath);
|
||||
let isHighlighted = await containsClass(commentContainer, 'highlighted');
|
||||
await expect(isHighlighted).toBe(true);
|
||||
const containerXpath = `//div[contains(text(), "${profileComment}")]/../../..`;
|
||||
const commentContainer = await findByXpath(containerXpath);
|
||||
const isHighlighted = await containsClass(commentContainer, 'highlighted');
|
||||
expect(isHighlighted).toBe(true);
|
||||
});
|
||||
|
||||
test('project: reply to comment', async () => {
|
||||
await driver.get(projectUrl);
|
||||
let commentXpath = `//span[contains(text(), "${projectComment}")]/../..`;
|
||||
let replyXpath = commentXpath + '//span[@class = "comment-reply"]';
|
||||
const commentXpath = `//span[contains(text(), "${projectComment}")]/../..`;
|
||||
const replyXpath = `${commentXpath}//span[@class = "comment-reply"]`;
|
||||
await clickXpath(replyXpath);
|
||||
|
||||
// type reply
|
||||
let replyRow = '//div[contains(@class, "comment-reply-row")]';
|
||||
let replyComposeXpath = replyRow + '//textArea[@class = "inplace-textarea"]';
|
||||
let composeBox = await findByXpath(replyComposeXpath);
|
||||
const replyRow = '//div[contains(@class, "comment-reply-row")]';
|
||||
const replyComposeXpath = `${replyRow}//textArea[@class = "inplace-textarea"]`;
|
||||
const composeBox = await findByXpath(replyComposeXpath);
|
||||
await composeBox.sendKeys(projectReply);
|
||||
|
||||
// click post
|
||||
let postButton = await findByXpath(replyRow + '//button[@class = "button compose-post"]');
|
||||
const postButton = await findByXpath(`${replyRow}//button[@class = "button compose-post"]`);
|
||||
await postButton.click();
|
||||
|
||||
let postedReply = await findByXpath(`//span[contains(text(), "${projectReply}")]`);
|
||||
let commentVisible = await postedReply.isDisplayed();
|
||||
await expect(commentVisible).toBe(true);
|
||||
const postedReply = await findByXpath(`//span[contains(text(), "${projectReply}")]`);
|
||||
const commentVisible = await postedReply.isDisplayed();
|
||||
expect(commentVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('profile reply to comment', async () => {
|
||||
await driver.get(profileUrl);
|
||||
// find the comment and click reply
|
||||
let commentXpath = `//div[contains(text(), "${profileComment}")]/..`;
|
||||
await clickXpath(commentXpath + '//a[@class = "reply"]');
|
||||
const commentXpath = `//div[contains(text(), "${profileComment}")]/..`;
|
||||
await clickXpath(`${commentXpath}//a[@class = "reply"]`);
|
||||
|
||||
// select reply box and type reply
|
||||
let replyComposeBox = await findByXpath(commentXpath + '//textArea');
|
||||
const replyComposeBox = await findByXpath(`${commentXpath}//textArea`);
|
||||
await replyComposeBox.sendKeys(profileReply);
|
||||
|
||||
// click post
|
||||
await clickXpath(commentXpath + '//a[contains(text(), "Post")]');
|
||||
await clickXpath(`${commentXpath}//a[contains(text(), "Post")]`);
|
||||
|
||||
// The reply wasn't findable by xpath after several attempts, but it seems
|
||||
// better to have this much of a test
|
||||
@ -286,23 +285,23 @@ describe('comment tests', async () => {
|
||||
await driver.get(studioUrl);
|
||||
|
||||
// find the comment and click reply
|
||||
let commentXpath = `//span[contains(text(), "${studioComment}")]/../..`;
|
||||
await clickXpath(commentXpath + '//span[@class = "comment-reply"]');
|
||||
const commentXpath = `//span[contains(text(), "${studioComment}")]/../..`;
|
||||
await clickXpath(`${commentXpath}//span[@class = "comment-reply"]`);
|
||||
|
||||
// type reply
|
||||
let replyRow = '//div[contains(@class, "comment-reply-row")]';
|
||||
let replyComposeXpath = replyRow + '//textArea[@class = "inplace-textarea"]';
|
||||
let composeBox = await findByXpath(replyComposeXpath);
|
||||
const replyRow = '//div[contains(@class, "comment-reply-row")]';
|
||||
const replyComposeXpath = `${replyRow}//textArea[@class = "inplace-textarea"]`;
|
||||
const composeBox = await findByXpath(replyComposeXpath);
|
||||
await composeBox.sendKeys(studioReply);
|
||||
|
||||
// click post
|
||||
let postButton = await findByXpath(replyRow + '//button[@class = "button compose-post"]');
|
||||
const postButton = await findByXpath(`${replyRow}//button[@class = "button compose-post"]`);
|
||||
await postButton.click();
|
||||
|
||||
// find reply
|
||||
let postedReply = await findByXpath(`//span[contains(text(), "${studioReply}")]`);
|
||||
let commentVisible = await postedReply.isDisplayed();
|
||||
await expect(commentVisible).toBe(true);
|
||||
const postedReply = await findByXpath(`//span[contains(text(), "${studioReply}")]`);
|
||||
const commentVisible = await postedReply.isDisplayed();
|
||||
expect(commentVisible).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -8,7 +8,7 @@ const {
|
||||
findText
|
||||
} = new SeleniumHelper();
|
||||
|
||||
let rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
const rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
|
||||
jest.setTimeout(60000);
|
||||
|
||||
@ -24,35 +24,35 @@ describe('www-integration footer links', () => {
|
||||
await findText('Create stories, games, and animations');
|
||||
});
|
||||
|
||||
afterAll(async () => await driver.quit());
|
||||
afterAll(() => driver.quit());
|
||||
|
||||
// ==== About Scratch column ====
|
||||
|
||||
test('click About Scratch link', async () => {
|
||||
await clickText('About Scratch');
|
||||
let url = await driver.getCurrentUrl();
|
||||
let pathname = (new URL(url)).pathname;
|
||||
const url = await driver.getCurrentUrl();
|
||||
const pathname = (new URL(url)).pathname;
|
||||
expect(pathname).toMatch(/^\/about\/?$/);
|
||||
});
|
||||
|
||||
test('click For Parents link', async () => {
|
||||
await clickText('For Parents');
|
||||
let url = await driver.getCurrentUrl();
|
||||
let pathname = (new URL(url)).pathname;
|
||||
const url = await driver.getCurrentUrl();
|
||||
const pathname = (new URL(url)).pathname;
|
||||
expect(pathname).toMatch(/^\/parents\/?$/);
|
||||
});
|
||||
|
||||
test('click For Educators link', async () => {
|
||||
await clickText('For Educators');
|
||||
let url = await driver.getCurrentUrl();
|
||||
let pathname = (new URL(url)).pathname;
|
||||
const url = await driver.getCurrentUrl();
|
||||
const pathname = (new URL(url)).pathname;
|
||||
expect(pathname).toMatch(/^\/educators\/?$/);
|
||||
});
|
||||
|
||||
test('click For Developers link', async () => {
|
||||
await clickText('For Developers');
|
||||
let url = await driver.getCurrentUrl();
|
||||
let pathname = (new URL(url)).pathname;
|
||||
const url = await driver.getCurrentUrl();
|
||||
const pathname = (new URL(url)).pathname;
|
||||
expect(pathname).toMatch(/^\/developers\/?$/);
|
||||
});
|
||||
|
||||
@ -60,22 +60,22 @@ describe('www-integration footer links', () => {
|
||||
|
||||
test('click Community Guidelines link', async () => {
|
||||
await clickText('Community Guidelines');
|
||||
let url = await driver.getCurrentUrl();
|
||||
let pathname = (new URL(url)).pathname;
|
||||
const url = await driver.getCurrentUrl();
|
||||
const pathname = (new URL(url)).pathname;
|
||||
expect(pathname).toMatch(/^\/community_guidelines\/?$/);
|
||||
});
|
||||
|
||||
test('click Discussion Forums link', async () => {
|
||||
await clickText('Discussion Forums');
|
||||
let url = await driver.getCurrentUrl();
|
||||
let pathname = (new URL(url)).pathname;
|
||||
const url = await driver.getCurrentUrl();
|
||||
const pathname = (new URL(url)).pathname;
|
||||
expect(pathname).toMatch(/^\/discuss\/?$/);
|
||||
});
|
||||
|
||||
test('click Statistics link', async () => {
|
||||
await clickText('Statistics');
|
||||
let url = await driver.getCurrentUrl();
|
||||
let pathname = (new URL(url)).pathname;
|
||||
const url = await driver.getCurrentUrl();
|
||||
const pathname = (new URL(url)).pathname;
|
||||
expect(pathname).toMatch(/^\/statistics\/?$/);
|
||||
});
|
||||
|
||||
@ -83,29 +83,29 @@ describe('www-integration footer links', () => {
|
||||
|
||||
test('click Ideas link', async () => {
|
||||
await clickText('Ideas');
|
||||
let url = await driver.getCurrentUrl();
|
||||
let pathname = (new URL(url)).pathname;
|
||||
const url = await driver.getCurrentUrl();
|
||||
const pathname = (new URL(url)).pathname;
|
||||
expect(pathname).toMatch(/^\/ideas\/?$/);
|
||||
});
|
||||
|
||||
test('click FAQ link', async () => {
|
||||
await clickText('FAQ');
|
||||
let url = await driver.getCurrentUrl();
|
||||
let pathname = (new URL(url)).pathname;
|
||||
const url = await driver.getCurrentUrl();
|
||||
const pathname = (new URL(url)).pathname;
|
||||
expect(pathname).toMatch(/^\/faq\/?$/);
|
||||
});
|
||||
|
||||
test('click Download link', async () => {
|
||||
await clickText('Download');
|
||||
let url = await driver.getCurrentUrl();
|
||||
let pathname = (new URL(url)).pathname;
|
||||
const url = await driver.getCurrentUrl();
|
||||
const pathname = (new URL(url)).pathname;
|
||||
expect(pathname).toMatch(/^\/download\/?$/);
|
||||
});
|
||||
|
||||
test('click Contact Us link', async () => {
|
||||
await clickText('Contact Us');
|
||||
let url = await driver.getCurrentUrl();
|
||||
let pathname = (new URL(url)).pathname;
|
||||
const url = await driver.getCurrentUrl();
|
||||
const pathname = (new URL(url)).pathname;
|
||||
expect(pathname).toMatch(/^\/contact-us\/?$/);
|
||||
});
|
||||
|
||||
@ -113,34 +113,34 @@ describe('www-integration footer links', () => {
|
||||
|
||||
test('click Terms of Use link', async () => {
|
||||
await clickText('Terms of Use');
|
||||
let url = await driver.getCurrentUrl();
|
||||
let pathname = (new URL(url)).pathname;
|
||||
const url = await driver.getCurrentUrl();
|
||||
const pathname = (new URL(url)).pathname;
|
||||
expect(pathname).toMatch(/^\/terms_of_use\/?$/);
|
||||
});
|
||||
|
||||
test('click Privacy Policy link', async () => {
|
||||
await clickText('Privacy Policy');
|
||||
let url = await driver.getCurrentUrl();
|
||||
let pathname = (new URL(url)).pathname;
|
||||
const url = await driver.getCurrentUrl();
|
||||
const pathname = (new URL(url)).pathname;
|
||||
expect(pathname).toMatch(/^\/privacy_policy\/?$/);
|
||||
});
|
||||
|
||||
test('click Cookies link', async () => {
|
||||
await clickText('Cookies');
|
||||
let url = await driver.getCurrentUrl();
|
||||
let pathname = (new URL(url)).pathname;
|
||||
const url = await driver.getCurrentUrl();
|
||||
const pathname = (new URL(url)).pathname;
|
||||
expect(pathname).toMatch(/^\/cookies\/?$/);
|
||||
|
||||
// Verify localization of last updated message
|
||||
let lastUpdated = await findText('The Scratch Cookie Policy was last updated June 28, 2023');
|
||||
let lastUpdatedVisible = await lastUpdated.isDisplayed();
|
||||
await expect(lastUpdatedVisible).toBe(true);
|
||||
const lastUpdated = await findText('The Scratch Cookie Policy was last updated June 28, 2023');
|
||||
const lastUpdatedVisible = await lastUpdated.isDisplayed();
|
||||
expect(lastUpdatedVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('click DMCA link', async () => {
|
||||
await clickText('DMCA');
|
||||
let url = await driver.getCurrentUrl();
|
||||
let pathname = (new URL(url)).pathname;
|
||||
const url = await driver.getCurrentUrl();
|
||||
const pathname = (new URL(url)).pathname;
|
||||
expect(pathname).toMatch(/^\/DMCA\/?$/);
|
||||
});
|
||||
|
||||
@ -148,8 +148,8 @@ describe('www-integration footer links', () => {
|
||||
|
||||
test('click Scratch Conference link', async () => {
|
||||
await clickText('Scratch Conference');
|
||||
let url = await driver.getCurrentUrl();
|
||||
let pathname = (new URL(url)).pathname;
|
||||
const url = await driver.getCurrentUrl();
|
||||
const pathname = (new URL(url)).pathname;
|
||||
expect(pathname).toMatch(/^\/scratch-conference\/?$/);
|
||||
});
|
||||
|
||||
|
@ -8,7 +8,7 @@ const {
|
||||
buildDriver
|
||||
} = new SeleniumHelper();
|
||||
|
||||
let rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
const rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
|
||||
jest.setTimeout(60000);
|
||||
|
||||
@ -24,33 +24,33 @@ describe('www-integration project rows', () => {
|
||||
await driver.get(rootUrl);
|
||||
});
|
||||
|
||||
afterAll(async () => await driver.quit());
|
||||
afterAll(() => driver.quit());
|
||||
|
||||
test('Featured Projects row title', async () => {
|
||||
let projects = await findByXpath('//div[@class="box"]/div[@class="box-header"]/h4');
|
||||
let projectsText = await projects.getText();
|
||||
await expect(projectsText).toEqual('Featured Projects');
|
||||
const projects = await findByXpath('//div[@class="box"]/div[@class="box-header"]/h4');
|
||||
const projectsText = await projects.getText();
|
||||
expect(projectsText).toEqual('Featured Projects');
|
||||
});
|
||||
|
||||
test('Featured Project link', async () => {
|
||||
await clickXpath('//div[@class="box"][descendant::text()="Featured Projects"]' +
|
||||
'//div[contains(@class, "thumbnail")][1]/a[@class="thumbnail-image"]');
|
||||
let guiPlayer = await findByXpath('//div[@class="guiPlayer"]');
|
||||
let guiPlayerDisplayed = await guiPlayer.isDisplayed();
|
||||
await expect(guiPlayerDisplayed).toBe(true);
|
||||
const guiPlayer = await findByXpath('//div[@class="guiPlayer"]');
|
||||
const guiPlayerDisplayed = await guiPlayer.isDisplayed();
|
||||
expect(guiPlayerDisplayed).toBe(true);
|
||||
});
|
||||
|
||||
test('Featured Studios row title', async () => {
|
||||
let studios = await findByXpath('//div[@class="box"][2]/div[@class="box-header"]/h4');
|
||||
let studiosText = await studios.getText();
|
||||
await expect(studiosText).toEqual('Featured Studios');
|
||||
const studios = await findByXpath('//div[@class="box"][2]/div[@class="box-header"]/h4');
|
||||
const studiosText = await studios.getText();
|
||||
expect(studiosText).toEqual('Featured Studios');
|
||||
});
|
||||
|
||||
test('Featured Studios link', async () => {
|
||||
await clickXpath('//div[@class="box"][descendant::text()="Featured Studios"]' +
|
||||
'//div[contains(@class, "thumbnail")][1]/a[@class="thumbnail-image"]');
|
||||
let studioInfo = await findByXpath('//div[contains(@class, "studio-info")]');
|
||||
let studioInfoDisplayed = await studioInfo.isDisplayed();
|
||||
await expect(studioInfoDisplayed).toBe(true);
|
||||
const studioInfo = await findByXpath('//div[contains(@class, "studio-info")]');
|
||||
const studioInfoDisplayed = await studioInfo.isDisplayed();
|
||||
expect(studioInfoDisplayed).toBe(true);
|
||||
});
|
||||
});
|
||||
|
@ -8,8 +8,8 @@ const {
|
||||
buildDriver
|
||||
} = new SeleniumHelper();
|
||||
|
||||
let rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
let takenUsername = process.env.SMOKE_USERNAME;
|
||||
const rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
const takenUsername = process.env.SMOKE_USERNAME;
|
||||
|
||||
jest.setTimeout(60000);
|
||||
|
||||
@ -21,7 +21,7 @@ describe('www-integration join flow', () => {
|
||||
await driver.get(rootUrl);
|
||||
});
|
||||
|
||||
afterAll(async () => await driver.quit());
|
||||
afterAll(() => driver.quit());
|
||||
|
||||
beforeEach(async () => {
|
||||
await driver.get(rootUrl);
|
||||
@ -29,61 +29,61 @@ describe('www-integration join flow', () => {
|
||||
});
|
||||
|
||||
test('click Join opens join modal', async () => {
|
||||
let joinModal = await findByXpath('//div[@class = "join-flow-outer-content"]');
|
||||
let modalVisible = await joinModal.isDisplayed();
|
||||
await expect(modalVisible).toBe(true);
|
||||
const joinModal = await findByXpath('//div[@class = "join-flow-outer-content"]');
|
||||
const modalVisible = await joinModal.isDisplayed();
|
||||
expect(modalVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('username validation message appears', async () => {
|
||||
await clickXpath('//input[contains(@name, "username")]');
|
||||
let message = await findByXpath('//div[contains(@class, "validation-message")]');
|
||||
let messageText = await message.getText();
|
||||
await expect(messageText).toEqual('Don\'t use your real name');
|
||||
const message = await findByXpath('//div[contains(@class, "validation-message")]');
|
||||
const messageText = await message.getText();
|
||||
expect(messageText).toEqual('Don\'t use your real name');
|
||||
|
||||
});
|
||||
|
||||
test('password validation message appears', async () => {
|
||||
await clickXpath('//input[contains(@name, "password")]');
|
||||
let message = await findByXpath('//div[contains(@class, "validation-message")]');
|
||||
let messageText = await message.getText();
|
||||
await expect(messageText).toContain('Write it down so you remember.');
|
||||
const message = await findByXpath('//div[contains(@class, "validation-message")]');
|
||||
const messageText = await message.getText();
|
||||
expect(messageText).toContain('Write it down so you remember.');
|
||||
});
|
||||
|
||||
test('password validation message appears', async () => {
|
||||
test('password confirmation validation message appears', async () => {
|
||||
await clickXpath('//input[contains(@name, "passwordConfirm")]');
|
||||
let message = await findByXpath('//div[contains(@class, "validation-message")]');
|
||||
let messageText = await message.getText();
|
||||
await expect(messageText).toEqual('Type password again');
|
||||
const message = await findByXpath('//div[contains(@class, "validation-message")]');
|
||||
const messageText = await message.getText();
|
||||
expect(messageText).toEqual('Type password again');
|
||||
});
|
||||
|
||||
test('username validation: too short', async () => {
|
||||
let textInput = await findByXpath('//input[contains(@name, "username")]');
|
||||
const textInput = await findByXpath('//input[contains(@name, "username")]');
|
||||
await textInput.click();
|
||||
await textInput.sendKeys('ab');
|
||||
await clickXpath('//div[@class = "join-flow-outer-content"]');
|
||||
let message = await findByXpath('//div[contains(@class, "validation-error")]');
|
||||
let messageText = await message.getText();
|
||||
await expect(messageText).toContain('Must be 3 letters or longer');
|
||||
const message = await findByXpath('//div[contains(@class, "validation-error")]');
|
||||
const messageText = await message.getText();
|
||||
expect(messageText).toContain('Must be 3 letters or longer');
|
||||
});
|
||||
|
||||
test('username validation: username taken', async () => {
|
||||
let textInput = await findByXpath('//input[contains(@name, "username")]');
|
||||
const textInput = await findByXpath('//input[contains(@name, "username")]');
|
||||
await textInput.click();
|
||||
await textInput.sendKeys(takenUsername);
|
||||
await clickXpath('//div[@class = "join-flow-outer-content"]');
|
||||
let message = await findByXpath('//div[contains(@class, "validation-error")]');
|
||||
let messageText = await message.getText();
|
||||
await expect(messageText).toContain('Username taken.');
|
||||
const message = await findByXpath('//div[contains(@class, "validation-error")]');
|
||||
const messageText = await message.getText();
|
||||
expect(messageText).toContain('Username taken.');
|
||||
});
|
||||
|
||||
test('username validation: bad word', async () => {
|
||||
let textInput = await findByXpath('//input[contains(@name, "username")]');
|
||||
const textInput = await findByXpath('//input[contains(@name, "username")]');
|
||||
await textInput.click();
|
||||
// Should be caught by the filter
|
||||
await textInput.sendKeys('xxxxxxxxx');
|
||||
await clickXpath('//div[@class = "join-flow-outer-content"]');
|
||||
let message = await findByXpath('//div[contains(@class, "validation-error")]');
|
||||
let messageText = await message.getText();
|
||||
await expect(messageText).toContain('Username not allowed');
|
||||
const message = await findByXpath('//div[contains(@class, "validation-error")]');
|
||||
const messageText = await message.getText();
|
||||
expect(messageText).toContain('Username not allowed');
|
||||
});
|
||||
});
|
||||
|
@ -10,12 +10,12 @@ const {
|
||||
signIn
|
||||
} = new SeleniumHelper();
|
||||
|
||||
let username = process.env.SMOKE_USERNAME + '1';
|
||||
let password = process.env.SMOKE_PASSWORD;
|
||||
const username = `${process.env.SMOKE_USERNAME}1`;
|
||||
const password = process.env.SMOKE_PASSWORD;
|
||||
|
||||
let rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
let myStuffURL = rootUrl + '/mystuff';
|
||||
let rateLimitCheck = process.env.RATE_LIMIT_CHECK || rootUrl;
|
||||
const rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
const myStuffURL = `${rootUrl}/mystuff`;
|
||||
const rateLimitCheck = process.env.RATE_LIMIT_CHECK || rootUrl;
|
||||
|
||||
jest.setTimeout(60000);
|
||||
|
||||
@ -30,74 +30,74 @@ describe('www-integration my_stuff', () => {
|
||||
await findByXpath('//span[contains(@class, "profile-name")]');
|
||||
});
|
||||
|
||||
afterAll(async () => await driver.quit());
|
||||
afterAll(() => driver.quit());
|
||||
|
||||
test('verify My Stuff structure (tabs, title)', async () => {
|
||||
await driver.get(myStuffURL);
|
||||
let header = await findByXpath('//div[@class="box-head"]/h2');
|
||||
let headerVisible = await header.isDisplayed();
|
||||
await expect(headerVisible).toBe(true);
|
||||
let allTab = await findByXpath('//li[@data-tab="projects"]/a');
|
||||
let allTabVisible = await allTab.isDisplayed();
|
||||
await expect(allTabVisible).toBe(true);
|
||||
let sharedTab = await findByXpath('//li[@data-tab="shared"]/a');
|
||||
let sharedTabVisible = await sharedTab.isDisplayed();
|
||||
await expect(sharedTabVisible).toBe(true);
|
||||
let unsharedTab = await findByXpath('//li[@data-tab="unshared"]/a');
|
||||
let unsharedTabVisible = await unsharedTab.isDisplayed();
|
||||
await expect(unsharedTabVisible).toBe(true);
|
||||
let studios = await findByXpath('//li[@data-tab="galleries"]/a');
|
||||
let studiosVisible = await studios.isDisplayed();
|
||||
await expect(studiosVisible).toBe(true);
|
||||
let trash = await findByXpath('//li[@data-tab="trash"]/a');
|
||||
let trashVisible = await trash.isDisplayed();
|
||||
await expect(trashVisible).toBe(true);
|
||||
const header = await findByXpath('//div[@class="box-head"]/h2');
|
||||
const headerVisible = await header.isDisplayed();
|
||||
expect(headerVisible).toBe(true);
|
||||
const allTab = await findByXpath('//li[@data-tab="projects"]/a');
|
||||
const allTabVisible = await allTab.isDisplayed();
|
||||
expect(allTabVisible).toBe(true);
|
||||
const sharedTab = await findByXpath('//li[@data-tab="shared"]/a');
|
||||
const sharedTabVisible = await sharedTab.isDisplayed();
|
||||
expect(sharedTabVisible).toBe(true);
|
||||
const unsharedTab = await findByXpath('//li[@data-tab="unshared"]/a');
|
||||
const unsharedTabVisible = await unsharedTab.isDisplayed();
|
||||
expect(unsharedTabVisible).toBe(true);
|
||||
const studios = await findByXpath('//li[@data-tab="galleries"]/a');
|
||||
const studiosVisible = await studios.isDisplayed();
|
||||
expect(studiosVisible).toBe(true);
|
||||
const trash = await findByXpath('//li[@data-tab="trash"]/a');
|
||||
const trashVisible = await trash.isDisplayed();
|
||||
expect(trashVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('clicking a project title should take you to the project page', async () => {
|
||||
await driver.get(myStuffURL);
|
||||
await clickXpath('//span[@class="media-info-item title"]');
|
||||
await driver.sleep(6000);
|
||||
let gui = await findByXpath('//div[@class="guiPlayer"]');
|
||||
let guiVisible = await gui.isDisplayed();
|
||||
await expect(guiVisible).toBe(true);
|
||||
const gui = await findByXpath('//div[@class="guiPlayer"]');
|
||||
const guiVisible = await gui.isDisplayed();
|
||||
expect(guiVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('clicking "see inside" should take you to the editor', async () =>{
|
||||
test('clicking "see inside" should take you to the editor', async () => {
|
||||
await driver.get(myStuffURL);
|
||||
await clickXpath('//a[@data-control="edit"]');
|
||||
let gf = await findByXpath('//img[@class="green-flag_green-flag_1kiAo"]');
|
||||
let gfVisible = await gf.isDisplayed();
|
||||
await expect(gfVisible).toBe(true);
|
||||
const gf = await findByXpath('//img[@class="green-flag_green-flag_1kiAo"]');
|
||||
const gfVisible = await gf.isDisplayed();
|
||||
expect(gfVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('Add To button should bring up a list of studios', async () =>{
|
||||
test('Add To button should bring up a list of studios', async () => {
|
||||
await driver.get(myStuffURL);
|
||||
await clickXpath('//div[@id="sidebar"]/ul/li[@data-tab="shared"]');
|
||||
await clickXpath('//div[@data-control="add-to"]');
|
||||
let dropDown = await findByXpath('//div[@class="dropdown-menu"]/ul/li');
|
||||
let dropDownVisible = await dropDown.isDisplayed();
|
||||
await expect(dropDownVisible).toBe(true);
|
||||
const dropDown = await findByXpath('//div[@class="dropdown-menu"]/ul/li');
|
||||
const dropDownVisible = await dropDown.isDisplayed();
|
||||
expect(dropDownVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('+ New Project button should open the editor', async () =>{
|
||||
test('+ New Project button should open the editor', async () => {
|
||||
await driver.get(myStuffURL);
|
||||
await clickText('+ New Project');
|
||||
let gf = await findByXpath('//img[@class="green-flag_green-flag_1kiAo"]');
|
||||
let gfVisible = await gf.isDisplayed();
|
||||
await expect(gfVisible).toBe(true);
|
||||
const gf = await findByXpath('//img[@class="green-flag_green-flag_1kiAo"]');
|
||||
const gfVisible = await gf.isDisplayed();
|
||||
expect(gfVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('+ New Studio button should take you to the studio page', async ()=>{
|
||||
test('+ New Studio button should take you to the studio page', async () => {
|
||||
await driver.get(rateLimitCheck);
|
||||
await driver.get(myStuffURL);
|
||||
await clickXpath('//form[@id="new_studio"]/button[@type="submit"]');
|
||||
let tabs = await findByXpath('//div[@class="studio-tabs"]');
|
||||
let tabsVisible = await tabs.isDisplayed();
|
||||
await expect(tabsVisible).toBe(true);
|
||||
const tabs = await findByXpath('//div[@class="studio-tabs"]');
|
||||
const tabsVisible = await tabs.isDisplayed();
|
||||
expect(tabsVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('New studio rate limited to five', async () =>{
|
||||
test('New studio rate limited to five', async () => {
|
||||
await driver.get(rateLimitCheck);
|
||||
// 1st studio
|
||||
await driver.get(myStuffURL);
|
||||
@ -122,9 +122,9 @@ describe('www-integration my_stuff', () => {
|
||||
// 6th studio should fail
|
||||
await driver.get(myStuffURL);
|
||||
await clickXpath('//form[@id="new_studio"]/button[@type="submit"]');
|
||||
let alertMessage = await findByXpath('//div[contains(@class, "alert-error")]');
|
||||
let errVisible = await alertMessage.isDisplayed();
|
||||
await expect(errVisible).toBe(true);
|
||||
const alertMessage = await findByXpath('//div[contains(@class, "alert-error")]');
|
||||
const errVisible = await alertMessage.isDisplayed();
|
||||
expect(errVisible).toBe(true);
|
||||
|
||||
await driver.get(rateLimitCheck);
|
||||
});
|
||||
|
@ -8,7 +8,7 @@ const {
|
||||
buildDriver
|
||||
} = new SeleniumHelper();
|
||||
|
||||
let rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
const rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
|
||||
jest.setTimeout(60000);
|
||||
|
||||
@ -23,78 +23,78 @@ describe('www-integration navbar links', () => {
|
||||
await driver.get(rootUrl);
|
||||
});
|
||||
|
||||
afterAll(async () => await driver.quit());
|
||||
afterAll(() => driver.quit());
|
||||
|
||||
test('Check text of navbar items', async () => {
|
||||
let create = await findByXpath('//li[@class="link create"]');
|
||||
let createText = await create.getText();
|
||||
await expect(createText).toEqual('Create');
|
||||
const create = await findByXpath('//li[@class="link create"]');
|
||||
const createText = await create.getText();
|
||||
expect(createText).toEqual('Create');
|
||||
|
||||
let explore = await findByXpath('//li[@class="link explore"]');
|
||||
let exploreText = await explore.getText();
|
||||
await expect(exploreText).toEqual('Explore');
|
||||
const explore = await findByXpath('//li[@class="link explore"]');
|
||||
const exploreText = await explore.getText();
|
||||
expect(exploreText).toEqual('Explore');
|
||||
|
||||
let ideas = await findByXpath('//li[@class="link ideas"]');
|
||||
let ideasText = await ideas.getText();
|
||||
await expect(ideasText).toEqual('Ideas');
|
||||
const ideas = await findByXpath('//li[@class="link ideas"]');
|
||||
const ideasText = await ideas.getText();
|
||||
expect(ideasText).toEqual('Ideas');
|
||||
|
||||
let about = await findByXpath('//li[@class="link about"]');
|
||||
let aboutText = await about.getText();
|
||||
await expect(aboutText).toEqual('About');
|
||||
const about = await findByXpath('//li[@class="link about"]');
|
||||
const aboutText = await about.getText();
|
||||
expect(aboutText).toEqual('About');
|
||||
|
||||
let join = await findByXpath('//a[@class="registrationLink"]');
|
||||
let joinText = await join.getText();
|
||||
await expect(joinText).toEqual('Join Scratch');
|
||||
const join = await findByXpath('//a[@class="registrationLink"]');
|
||||
const joinText = await join.getText();
|
||||
expect(joinText).toEqual('Join Scratch');
|
||||
|
||||
let signIn = await findByXpath('//li[@class="link right login-item"]/a');
|
||||
let signInText = await signIn.getText();
|
||||
await expect(signInText).toEqual('Sign in');
|
||||
const signIn = await findByXpath('//li[@class="link right login-item"]/a');
|
||||
const signInText = await signIn.getText();
|
||||
expect(signInText).toEqual('Sign in');
|
||||
});
|
||||
|
||||
test('create when signed out', async () => {
|
||||
await clickXpath('//li[@class="link create"]');
|
||||
let gui = await findByXpath('//div[contains(@class, "gui")]');
|
||||
let guiVisible = await gui.isDisplayed();
|
||||
await expect(guiVisible).toBe(true);
|
||||
const gui = await findByXpath('//div[contains(@class, "gui")]');
|
||||
const guiVisible = await gui.isDisplayed();
|
||||
expect(guiVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('Explore link when signed out', async () => {
|
||||
await clickXpath('//li[@class="link explore"]');
|
||||
let banner = await findByXpath('//h1[@class="title-banner-h1"]');
|
||||
let bannerText = await banner.getText();
|
||||
await expect(bannerText).toEqual('Explore');
|
||||
const banner = await findByXpath('//h1[@class="title-banner-h1"]');
|
||||
const bannerText = await banner.getText();
|
||||
expect(bannerText).toEqual('Explore');
|
||||
});
|
||||
|
||||
test('Ideas link when signed out', async () => {
|
||||
await clickXpath('//li[@class="link ideas"]');
|
||||
let banner = await findByXpath('//div[contains(@class, "ideas-banner")]');
|
||||
let bannerVisible = await banner.isDisplayed();
|
||||
await expect(bannerVisible).toBe(true);
|
||||
const banner = await findByXpath('//div[contains(@class, "ideas-banner")]');
|
||||
const bannerVisible = await banner.isDisplayed();
|
||||
expect(bannerVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('About link when signed out', async () => {
|
||||
await clickXpath('//li[@class="link about"]');
|
||||
let aboutPage = await findByXpath('//div[@class="inner about"]');
|
||||
let aboutPageVisible = await aboutPage.isDisplayed();
|
||||
await expect(aboutPageVisible).toBe(true);
|
||||
const aboutPage = await findByXpath('//div[@class="inner about"]');
|
||||
const aboutPageVisible = await aboutPage.isDisplayed();
|
||||
expect(aboutPageVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('Search Bar', async () => {
|
||||
let searchBar = await findByXpath('//div[contains(@class, "search-wrapper")]/div/input');
|
||||
const searchBar = await findByXpath('//div[contains(@class, "search-wrapper")]/div/input');
|
||||
await searchBar.sendKeys('cat');
|
||||
await driver.sleep(500); // without it sends an empty string on submit
|
||||
await searchBar.submit();
|
||||
let banner = await findByXpath('//h1[@class="title-banner-h1"]');
|
||||
let bannerText = await banner.getText();
|
||||
await expect(bannerText).toEqual('Search');
|
||||
const banner = await findByXpath('//h1[@class="title-banner-h1"]');
|
||||
const bannerText = await banner.getText();
|
||||
expect(bannerText).toEqual('Search');
|
||||
});
|
||||
|
||||
test('Scratch Logo', async () => {
|
||||
await clickXpath('//li[@class="link explore"]');
|
||||
await findByXpath('//h1[@class="title-banner-h1"]');
|
||||
await clickXpath('//li[@class="logo"]');
|
||||
let splash = await findByXpath('//div[@class="splash"]');
|
||||
let splashVisible = await splash.isDisplayed();
|
||||
const splash = await findByXpath('//div[@class="splash"]');
|
||||
const splashVisible = await splash.isDisplayed();
|
||||
expect(splashVisible).toBe(true);
|
||||
});
|
||||
|
||||
|
@ -15,29 +15,29 @@ const {
|
||||
waitUntilVisible
|
||||
} = new SeleniumHelper();
|
||||
|
||||
let rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
const rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
|
||||
// project IDs and URLs
|
||||
let unownedSharedId = process.env.UNOWNED_SHARED_PROJECT_ID || 1300006196;
|
||||
let unownedSharedUrl = rootUrl + '/projects/' + unownedSharedId;
|
||||
const unownedSharedId = process.env.UNOWNED_SHARED_PROJECT_ID || 1300006196;
|
||||
const unownedSharedUrl = `${rootUrl}/projects/${unownedSharedId}`;
|
||||
|
||||
let ownedSharedId = process.env.OWNED_SHARED_PROJECT_ID || 1300009464;
|
||||
let ownedSharedUrl = rootUrl + '/projects/' + ownedSharedId;
|
||||
const ownedSharedId = process.env.OWNED_SHARED_PROJECT_ID || 1300009464;
|
||||
const ownedSharedUrl = `${rootUrl}/projects/${ownedSharedId}`;
|
||||
|
||||
let ownedUnsharedID = process.env.OWNED_UNSHARED_PROJECT_ID || 1300009465;
|
||||
let ownedUnsharedUrl = rootUrl + '/projects/' + ownedUnsharedID;
|
||||
const ownedUnsharedID = process.env.OWNED_UNSHARED_PROJECT_ID || 1300009465;
|
||||
const ownedUnsharedUrl = `${rootUrl}/projects/${ownedUnsharedID}`;
|
||||
|
||||
let unownedUnsharedID = process.env.UNOWNED_UNSHARED_PROJECT_ID || 1300006306;
|
||||
let unownedUnsharedUrl = rootUrl + '/projects/' + unownedUnsharedID;
|
||||
const unownedUnsharedID = process.env.UNOWNED_UNSHARED_PROJECT_ID || 1300006306;
|
||||
const unownedUnsharedUrl = `${rootUrl}/projects/${unownedUnsharedID}`;
|
||||
|
||||
let unownedSharedScratch2ID = process.env.UNOWNED_SHARED_SCRATCH2_PROJECT_ID || 1300009487;
|
||||
let unownedSharedScratch2Url = rootUrl + '/projects/' + unownedSharedScratch2ID;
|
||||
const unownedSharedScratch2ID = process.env.UNOWNED_SHARED_SCRATCH2_PROJECT_ID || 1300009487;
|
||||
const unownedSharedScratch2Url = `${rootUrl}/projects/${unownedSharedScratch2ID}`;
|
||||
|
||||
let ownedUnsharedScratch2ID = process.env.OWNED_UNSHARED_SCRATCH2_PROJECT_ID || 1300009488;
|
||||
let ownedUnsharedScratch2Url = rootUrl + '/projects/' + ownedUnsharedScratch2ID;
|
||||
const ownedUnsharedScratch2ID = process.env.OWNED_UNSHARED_SCRATCH2_PROJECT_ID || 1300009488;
|
||||
const ownedUnsharedScratch2Url = `${rootUrl}/projects/${ownedUnsharedScratch2ID}`;
|
||||
|
||||
let username = process.env.SMOKE_USERNAME + '6';
|
||||
let password = process.env.SMOKE_PASSWORD;
|
||||
const username = `${process.env.SMOKE_USERNAME}6`;
|
||||
const password = process.env.SMOKE_PASSWORD;
|
||||
|
||||
const remote = process.env.SMOKE_REMOTE || false;
|
||||
|
||||
@ -57,57 +57,57 @@ describe('www-integration project-page signed out', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await driver.get(unownedSharedUrl);
|
||||
let gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]');
|
||||
const gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]');
|
||||
await waitUntilVisible(gfOverlay, driver);
|
||||
});
|
||||
|
||||
afterAll(async () => await driver.quit());
|
||||
afterAll(() => driver.quit());
|
||||
|
||||
// LOGGED OUT TESTS
|
||||
|
||||
test('Find fullscreen button', async () => {
|
||||
await clickXpath('//div[starts-with(@class, "stage_green-flag-overlay")]');
|
||||
await clickXpath('//img[contains(@alt, "Enter full screen mode")]');
|
||||
let fullscreenGui = await findByXpath('//div[@class="guiPlayer fullscreen"]');
|
||||
let guiVisible = await fullscreenGui.isDisplayed();
|
||||
await expect(guiVisible).toBe(true);
|
||||
const fullscreenGui = await findByXpath('//div[@class="guiPlayer fullscreen"]');
|
||||
const guiVisible = await fullscreenGui.isDisplayed();
|
||||
expect(guiVisible).toBe(true);
|
||||
});
|
||||
|
||||
test.skip('Open Copy Link modal', async () => {
|
||||
await clickXpath('//button[@class="button action-button copy-link-button"]');
|
||||
let projectLink = await findByXpath('//input[@name="link"]');
|
||||
let linkValue = await projectLink.getAttribute('value');
|
||||
await expect(linkValue).toEqual(unownedSharedUrl);
|
||||
const projectLink = await findByXpath('//input[@name="link"]');
|
||||
const linkValue = await projectLink.getAttribute('value');
|
||||
expect(linkValue).toEqual(unownedSharedUrl);
|
||||
});
|
||||
|
||||
test('Click Username to go to profile page', async ()=> {
|
||||
test('Click Username to go to profile page', async () => {
|
||||
await clickXpath('//div[@class="title"]/a');
|
||||
let userContent = await findByXpath('//div[@class="user-content"]');
|
||||
let contentVisible = await userContent.isDisplayed();
|
||||
await expect(contentVisible).toBe(true);
|
||||
const userContent = await findByXpath('//div[@class="user-content"]');
|
||||
const contentVisible = await userContent.isDisplayed();
|
||||
expect(contentVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('click See Inside to go to the editor', async ()=> {
|
||||
test('click See Inside to go to the editor', async () => {
|
||||
await clickXpath('//button[@class="button button see-inside-button"]');
|
||||
let infoArea = await findByXpath('//div[@class="sprite-info_sprite-info_3EyZh box_box_2jjDp"]');
|
||||
let areaVisible = await infoArea.isDisplayed();
|
||||
await expect(areaVisible).toBe(true);
|
||||
const infoArea = await findByXpath('//div[@class="sprite-info_sprite-info_3EyZh box_box_2jjDp"]');
|
||||
const areaVisible = await infoArea.isDisplayed();
|
||||
expect(areaVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('click View All remixes takes you to remix page', async ()=> {
|
||||
test('click View All remixes takes you to remix page', async () => {
|
||||
await clickXpath('//div[@class="list-header-link"]');
|
||||
let originalLink = await findByXpath('//h2/a');
|
||||
let link = await originalLink.getAttribute('href');
|
||||
await expect(link).toEqual(rootUrl + '/projects/' + unownedSharedId + '/');
|
||||
const originalLink = await findByXpath('//h2/a');
|
||||
const link = await originalLink.getAttribute('href');
|
||||
expect(link).toEqual(`${rootUrl}/projects/${unownedSharedId}/`);
|
||||
});
|
||||
|
||||
// Load an unshared project while signed out, get error
|
||||
test('Load an ushared project you do not own (error)', async () => {
|
||||
await driver.get(unownedUnsharedUrl);
|
||||
let unavailableImage = await findByXpath('//img[@class="not-available-image"]');
|
||||
const unavailableImage = await findByXpath('//img[@class="not-available-image"]');
|
||||
await waitUntilVisible(unavailableImage, driver);
|
||||
let unavailableVisible = await unavailableImage.isDisplayed();
|
||||
await expect(unavailableVisible).toBe(true);
|
||||
const unavailableVisible = await unavailableImage.isDisplayed();
|
||||
expect(unavailableVisible).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@ -127,62 +127,62 @@ describe('www-integration project-page signed in', () => {
|
||||
await driver.get(rootUrl);
|
||||
});
|
||||
|
||||
afterAll(async () => await driver.quit());
|
||||
afterAll(() => driver.quit());
|
||||
|
||||
// LOGGED in TESTS
|
||||
|
||||
// Load a shared project you own
|
||||
test('Load a shared project you own', async () => {
|
||||
await driver.get(ownedSharedUrl);
|
||||
let gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]');
|
||||
const gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]');
|
||||
await waitUntilVisible(gfOverlay, driver);
|
||||
let gfVisible = await gfOverlay.isDisplayed();
|
||||
await expect(gfVisible).toBe(true);
|
||||
const gfVisible = await gfOverlay.isDisplayed();
|
||||
expect(gfVisible).toBe(true);
|
||||
});
|
||||
|
||||
// Load a shared project you don't own
|
||||
test('Load a shared project you do not own', async () => {
|
||||
await driver.get(unownedSharedUrl);
|
||||
let gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]');
|
||||
const gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]');
|
||||
await waitUntilVisible(gfOverlay, driver);
|
||||
let gfVisible = await gfOverlay.isDisplayed();
|
||||
await expect(gfVisible).toBe(true);
|
||||
const gfVisible = await gfOverlay.isDisplayed();
|
||||
expect(gfVisible).toBe(true);
|
||||
});
|
||||
|
||||
// Load an unshared project you own
|
||||
test('Load an unshared project you own', async () => {
|
||||
await driver.get(ownedUnsharedUrl);
|
||||
let gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]');
|
||||
const gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]');
|
||||
await waitUntilVisible(gfOverlay, driver);
|
||||
let gfVisible = await gfOverlay.isDisplayed();
|
||||
await expect(gfVisible).toBe(true);
|
||||
const gfVisible = await gfOverlay.isDisplayed();
|
||||
expect(gfVisible).toBe(true);
|
||||
});
|
||||
|
||||
// Load an unshared project you don't own, get error
|
||||
test('Load an ushared project you do not own (error)', async () => {
|
||||
await driver.get(unownedUnsharedUrl);
|
||||
let unavailableImage = await findByXpath('//img[@class="not-available-image"]');
|
||||
const unavailableImage = await findByXpath('//img[@class="not-available-image"]');
|
||||
await waitUntilVisible(unavailableImage, driver);
|
||||
let unavailableVisible = await unavailableImage.isDisplayed();
|
||||
await expect(unavailableVisible).toBe(true);
|
||||
const unavailableVisible = await unavailableImage.isDisplayed();
|
||||
expect(unavailableVisible).toBe(true);
|
||||
});
|
||||
|
||||
// Load a shared scratch 2 project you don't own
|
||||
test('Load a shared scratch 2 project you do not own', async () => {
|
||||
await driver.get(unownedSharedScratch2Url);
|
||||
let gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]');
|
||||
const gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]');
|
||||
await waitUntilVisible(gfOverlay, driver);
|
||||
let gfVisible = await gfOverlay.isDisplayed();
|
||||
await expect(gfVisible).toBe(true);
|
||||
const gfVisible = await gfOverlay.isDisplayed();
|
||||
expect(gfVisible).toBe(true);
|
||||
});
|
||||
|
||||
// Load an unshared scratch 2 project you own
|
||||
test('Load an unshared scratch 2 project you own', async () => {
|
||||
await driver.get(ownedUnsharedScratch2Url);
|
||||
let gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]');
|
||||
const gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]');
|
||||
await waitUntilVisible(gfOverlay, driver);
|
||||
let gfVisible = await gfOverlay.isDisplayed();
|
||||
await expect(gfVisible).toBe(true);
|
||||
const gfVisible = await gfOverlay.isDisplayed();
|
||||
expect(gfVisible).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@ -208,35 +208,35 @@ describe('www-integration project-creation signed in', () => {
|
||||
await driver.get(rootUrl);
|
||||
});
|
||||
|
||||
afterAll(async () => await driver.quit());
|
||||
afterAll(() => driver.quit());
|
||||
|
||||
test('make a copy of a project', async () => {
|
||||
await driver.get(ownedUnsharedUrl + '/editor');
|
||||
let gf = await findByXpath('//img[@class="green-flag_green-flag_1kiAo"]');
|
||||
await driver.get(`${ownedUnsharedUrl}/editor`);
|
||||
const gf = await findByXpath('//img[@class="green-flag_green-flag_1kiAo"]');
|
||||
await gf.isDisplayed();
|
||||
await clickXpath(FILE_MENU_XPATH);
|
||||
await clickText('Save as a copy');
|
||||
let successAlert = await findText('Project saved as a copy.');
|
||||
let alertVisible = await successAlert.isDisplayed();
|
||||
await expect(alertVisible).toBe(true);
|
||||
const successAlert = await findText('Project saved as a copy.');
|
||||
const alertVisible = await successAlert.isDisplayed();
|
||||
expect(alertVisible).toBe(true);
|
||||
await driver.sleep(1000);
|
||||
let infoArea = await findByXpath('//div[@class="sprite-info_sprite-info_3EyZh box_box_2jjDp"]');
|
||||
let areaVisible = await infoArea.isDisplayed();
|
||||
await expect(areaVisible).toBe(true);
|
||||
const infoArea = await findByXpath('//div[@class="sprite-info_sprite-info_3EyZh box_box_2jjDp"]');
|
||||
const areaVisible = await infoArea.isDisplayed();
|
||||
expect(areaVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('remix a project', async () => {
|
||||
await driver.get(unownedSharedUrl);
|
||||
let gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]');
|
||||
const gfOverlay = await findByXpath('//div[@class="stage-wrapper_stage-wrapper_2bejr box_box_2jjDp"]');
|
||||
await waitUntilVisible(gfOverlay, driver);
|
||||
await clickXpath('//button[@class="button remix-button"]');
|
||||
let successAlert = await findText('Project saved as a remix.');
|
||||
let alertVisible = await successAlert.isDisplayed();
|
||||
await expect(alertVisible).toBe(true);
|
||||
const successAlert = await findText('Project saved as a remix.');
|
||||
const alertVisible = await successAlert.isDisplayed();
|
||||
expect(alertVisible).toBe(true);
|
||||
await driver.sleep(1000);
|
||||
let infoArea = await findByXpath('//div[@class="sprite-info_sprite-info_3EyZh box_box_2jjDp"]');
|
||||
let areaVisible = await infoArea.isDisplayed();
|
||||
await expect(areaVisible).toBe(true);
|
||||
const infoArea = await findByXpath('//div[@class="sprite-info_sprite-info_3EyZh box_box_2jjDp"]');
|
||||
const areaVisible = await infoArea.isDisplayed();
|
||||
expect(areaVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('load project from file', async () => {
|
||||
@ -247,7 +247,7 @@ describe('www-integration project-creation signed in', () => {
|
||||
|
||||
// upload file
|
||||
await clickXpath('//li[@class="link create"]');
|
||||
let gf = await findByXpath('//img[@class="green-flag_green-flag_1kiAo"]');
|
||||
const gf = await findByXpath('//img[@class="green-flag_green-flag_1kiAo"]');
|
||||
await gf.isDisplayed();
|
||||
await clickXpath(FILE_MENU_XPATH);
|
||||
await clickText('Load from your computer');
|
||||
@ -256,18 +256,18 @@ describe('www-integration project-creation signed in', () => {
|
||||
await input.sendKeys(projectPath);
|
||||
|
||||
// accept alert
|
||||
let alert = await driver.switchTo().alert();
|
||||
const alert = await driver.switchTo().alert();
|
||||
await alert.accept();
|
||||
|
||||
// check that project is loaded
|
||||
let spriteTile = await findText('project1-sprite');
|
||||
let spriteTileVisible = await spriteTile.isDisplayed();
|
||||
await expect(spriteTileVisible).toBe(true);
|
||||
const spriteTile = await findText('project1-sprite');
|
||||
const spriteTileVisible = await spriteTile.isDisplayed();
|
||||
expect(spriteTileVisible).toBe(true);
|
||||
|
||||
// check that gui is still there after some time has passed
|
||||
await driver.sleep(1000);
|
||||
let infoArea = await findByXpath('//div[@class="sprite-info_sprite-info_3EyZh box_box_2jjDp"]');
|
||||
let areaVisible = await infoArea.isDisplayed();
|
||||
await expect(areaVisible).toBe(true);
|
||||
const infoArea = await findByXpath('//div[@class="sprite-info_sprite-info_3EyZh box_box_2jjDp"]');
|
||||
const areaVisible = await infoArea.isDisplayed();
|
||||
expect(areaVisible).toBe(true);
|
||||
});
|
||||
});
|
||||
|
@ -9,7 +9,7 @@ const {
|
||||
getKey
|
||||
} = new SeleniumHelper();
|
||||
|
||||
let rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
const rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
|
||||
jest.setTimeout(60000);
|
||||
|
||||
@ -24,35 +24,35 @@ describe('www-integration search', () => {
|
||||
await driver.get(rootUrl);
|
||||
});
|
||||
|
||||
afterAll(async () => await driver.quit());
|
||||
afterAll(() => driver.quit());
|
||||
|
||||
test('search converts spaces', async () => {
|
||||
let searchBar = await findByXpath('//div[contains(@class, "search-wrapper")]/div/input');
|
||||
await searchBar.sendKeys('Test search string' + getKey('ENTER'));
|
||||
const searchBar = await findByXpath('//div[contains(@class, "search-wrapper")]/div/input');
|
||||
await searchBar.sendKeys(`Test search string${getKey('ENTER')}`);
|
||||
|
||||
// check url
|
||||
let url = await driver.getCurrentUrl();
|
||||
await expect(url).toMatch(/^.*\?q=Test%20search%20string$/);
|
||||
const url = await driver.getCurrentUrl();
|
||||
expect(url).toMatch(/^.*\?q=Test%20search%20string$/);
|
||||
});
|
||||
|
||||
test('Search escapes symbols', async () => {
|
||||
let searchBar = await findByXpath('//div[contains(@class, "search-wrapper")]/div/input');
|
||||
await searchBar.sendKeys('100% pen' + getKey('ENTER'));
|
||||
const searchBar = await findByXpath('//div[contains(@class, "search-wrapper")]/div/input');
|
||||
await searchBar.sendKeys(`100% pen${getKey('ENTER')}`);
|
||||
|
||||
// check url
|
||||
let url = await driver.getCurrentUrl();
|
||||
await expect(url).toMatch(/^.*\?q=100%25%20pen$/);
|
||||
const url = await driver.getCurrentUrl();
|
||||
expect(url).toMatch(/^.*\?q=100%25%20pen$/);
|
||||
});
|
||||
|
||||
test('Switching to studios maintains search string', async () => {
|
||||
let searchBar = await findByXpath('//div[contains(@class, "search-wrapper")]/div/input');
|
||||
await searchBar.sendKeys('100% pen' + getKey('ENTER'));
|
||||
const searchBar = await findByXpath('//div[contains(@class, "search-wrapper")]/div/input');
|
||||
await searchBar.sendKeys(`100% pen${getKey('ENTER')}`);
|
||||
|
||||
// switch to studios tab
|
||||
clickXpath('//a/li/span[contains(text(),"Studios")]');
|
||||
|
||||
// check url
|
||||
let url = await driver.getCurrentUrl();
|
||||
await expect(url).toMatch(/^.*\?q=100%25%20pen$/);
|
||||
const url = await driver.getCurrentUrl();
|
||||
expect(url).toMatch(/^.*\?q=100%25%20pen$/);
|
||||
});
|
||||
});
|
||||
|
@ -40,8 +40,8 @@ class SeleniumHelper {
|
||||
if (remote === 'true'){
|
||||
let nameToUse;
|
||||
if (ci === 'true'){
|
||||
let ciName = usingCircle ? 'circleCi ' : 'unknown ';
|
||||
nameToUse = ciName + buildID + ' : ' + name;
|
||||
const ciName = usingCircle ? 'circleCi ' : 'unknown ';
|
||||
nameToUse = `${ciName + buildID} : ${name}`;
|
||||
} else {
|
||||
nameToUse = name;
|
||||
}
|
||||
@ -54,7 +54,7 @@ class SeleniumHelper {
|
||||
|
||||
getDriver () {
|
||||
const chromeCapabilities = webdriver.Capabilities.chrome();
|
||||
let args = [];
|
||||
const args = [];
|
||||
if (headless) {
|
||||
args.push('--headless');
|
||||
args.push('window-size=1024,1680');
|
||||
@ -62,7 +62,7 @@ class SeleniumHelper {
|
||||
}
|
||||
chromeCapabilities.set('chromeOptions', {args});
|
||||
chromeCapabilities.setPageLoadStrategy(PageLoadStrategy.EAGER);
|
||||
let driver = new webdriver.Builder()
|
||||
const driver = new webdriver.Builder()
|
||||
.forBrowser('chrome')
|
||||
.withCapabilities(chromeCapabilities)
|
||||
.build();
|
||||
@ -82,12 +82,12 @@ class SeleniumHelper {
|
||||
const chromeVersion = this.getChromeVersionNumber();
|
||||
// Driver configs can be generated with the Sauce Platform Configurator
|
||||
// https://wiki.saucelabs.com/display/DOCS/Platform+Configurator
|
||||
let driverConfig = {
|
||||
const driverConfig = {
|
||||
browserName: 'chrome',
|
||||
platform: 'macOS 10.15',
|
||||
version: chromeVersion
|
||||
};
|
||||
var driver = new webdriver.Builder()
|
||||
const driver = new webdriver.Builder()
|
||||
.withCapabilities({
|
||||
browserName: driverConfig.browserName,
|
||||
platform: driverConfig.platform,
|
||||
@ -143,21 +143,21 @@ class SeleniumHelper {
|
||||
}
|
||||
|
||||
dragFromXpathToXpath (startXpath, endXpath) {
|
||||
return this.findByXpath(startXpath).then(startEl => {
|
||||
return this.findByXpath(endXpath).then(endEl => {
|
||||
return this.driver.actions()
|
||||
return this.findByXpath(startXpath).then(startEl =>
|
||||
this.findByXpath(endXpath).then(endEl =>
|
||||
this.driver.actions()
|
||||
.dragAndDrop(startEl, endEl)
|
||||
.perform();
|
||||
});
|
||||
});
|
||||
.perform()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// must be used on a www page
|
||||
async signIn (username, password) {
|
||||
await this.clickXpath('//li[@class="link right login-item"]/a');
|
||||
let name = await this.findByXpath('//input[@id="frc-username-1088"]');
|
||||
const name = await this.findByXpath('//input[@id="frc-username-1088"]');
|
||||
await name.sendKeys(username);
|
||||
let word = await this.findByXpath('//input[@id="frc-password-1088"]');
|
||||
const word = await this.findByXpath('//input[@id="frc-password-1088"]');
|
||||
await word.sendKeys(password + this.getKey('ENTER'));
|
||||
await this.findByXpath('//span[contains(@class, "profile-name")]');
|
||||
}
|
||||
@ -170,29 +170,27 @@ class SeleniumHelper {
|
||||
return this.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;
|
||||
.then(entries => 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;
|
||||
});
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
async containsClass (element, cl) {
|
||||
let classes = await element.getAttribute('class');
|
||||
let classList = classes.split(' ');
|
||||
const classes = await element.getAttribute('class');
|
||||
const classList = classes.split(' ');
|
||||
if (classList.includes(cl)){
|
||||
return true;
|
||||
}
|
||||
|
@ -13,11 +13,11 @@ const {
|
||||
waitUntilVisible
|
||||
} = new SeleniumHelper();
|
||||
|
||||
let username = process.env.SMOKE_USERNAME;
|
||||
let password = process.env.SMOKE_PASSWORD;
|
||||
let rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
let scratchr2url = rootUrl + '/users/' + username;
|
||||
let wwwURL = rootUrl;
|
||||
const username = process.env.SMOKE_USERNAME;
|
||||
const password = process.env.SMOKE_PASSWORD;
|
||||
const rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
const scratchr2url = `${rootUrl}/users/${username}`;
|
||||
const wwwURL = rootUrl;
|
||||
|
||||
jest.setTimeout(60000);
|
||||
|
||||
@ -43,30 +43,30 @@ describe('www-integration sign-in-and-out', () => {
|
||||
await driver.get(wwwURL);
|
||||
await driver.sleep(1000);
|
||||
await clickXpath('//li[@class="link right login-item"]/a');
|
||||
let name = await findByXpath('//input[@id="frc-username-1088"]');
|
||||
const name = await findByXpath('//input[@id="frc-username-1088"]');
|
||||
await name.sendKeys(username);
|
||||
let word = await findByXpath('//input[@id="frc-password-1088"]');
|
||||
const word = await findByXpath('//input[@id="frc-password-1088"]');
|
||||
await word.sendKeys(password);
|
||||
await driver.sleep(500);
|
||||
await clickXpath('//button[contains(@class, "button") and ' +
|
||||
'contains(@class, "submit-button") and contains(@class, "white")]');
|
||||
await driver.sleep(500);
|
||||
let element = await findByXpath('//span[contains(@class, "profile-name")]');
|
||||
let text = await element.getText();
|
||||
await expect(text.toLowerCase()).toEqual(username.toLowerCase());
|
||||
const element = await findByXpath('//span[contains(@class, "profile-name")]');
|
||||
const text = await element.getText();
|
||||
expect(text.toLowerCase()).toEqual(username.toLowerCase());
|
||||
});
|
||||
|
||||
test('sign in on scratchr2', async () => {
|
||||
await driver.get(scratchr2url);
|
||||
await clickXpath('//li[@class="sign-in dropdown"]/span');
|
||||
let name = await findByXpath('//input[@id="login_dropdown_username"]');
|
||||
const name = await findByXpath('//input[@id="login_dropdown_username"]');
|
||||
await name.sendKeys(username);
|
||||
let word = await findByXpath('//input[@name="password"]');
|
||||
const word = await findByXpath('//input[@name="password"]');
|
||||
await word.sendKeys(password);
|
||||
await clickButton('Sign in');
|
||||
let element = await findByXpath('//span[@class="user-name dropdown-toggle"]');
|
||||
let text = await element.getText();
|
||||
await expect(text.toLowerCase()).toEqual(username.toLowerCase());
|
||||
const element = await findByXpath('//span[@class="user-name dropdown-toggle"]');
|
||||
const text = await element.getText();
|
||||
expect(text.toLowerCase()).toEqual(username.toLowerCase());
|
||||
});
|
||||
});
|
||||
|
||||
@ -80,73 +80,73 @@ describe('www-integration sign-in-and-out', () => {
|
||||
test('sign out on www', async () => {
|
||||
await clickXpath('//a[contains(@class, "user-info")]');
|
||||
await clickText('Sign out');
|
||||
let element = await findByXpath('//li[@class="link right login-item"]/a/span');
|
||||
let text = await element.getText();
|
||||
await expect(text.toLowerCase()).toEqual('Sign In'.toLowerCase());
|
||||
const element = await findByXpath('//li[@class="link right login-item"]/a/span');
|
||||
const text = await element.getText();
|
||||
expect(text.toLowerCase()).toEqual('Sign In'.toLowerCase());
|
||||
});
|
||||
|
||||
test('sign out on scratchr2', async () => {
|
||||
await driver.get(scratchr2url);
|
||||
await clickXpath('//span[@class="user-name dropdown-toggle"]');
|
||||
await clickXpath('//li[@id="logout"]');
|
||||
let element = await findByXpath('//li[@class="link right login-item"]/a/span');
|
||||
let text = await element.getText();
|
||||
await expect(text.toLowerCase()).toEqual('Sign In'.toLowerCase());
|
||||
const element = await findByXpath('//li[@class="link right login-item"]/a/span');
|
||||
const text = await element.getText();
|
||||
expect(text.toLowerCase()).toEqual('Sign In'.toLowerCase());
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('login failures', async () => {
|
||||
describe('login failures', () => {
|
||||
test('sign in with no password in Scratchr2', async () => {
|
||||
let nonsenseUsername = Math.random().toString(36)
|
||||
const nonsenseUsername = Math.random().toString(36)
|
||||
.replace(/[^a-z]+/g, '')
|
||||
.substr(0, 5);
|
||||
await driver.get(scratchr2url);
|
||||
await clickXpath('//li[@class="sign-in dropdown"]/span');
|
||||
let name = await findByXpath('//input[@id="login_dropdown_username"]');
|
||||
const name = await findByXpath('//input[@id="login_dropdown_username"]');
|
||||
await name.sendKeys(nonsenseUsername + getKey('ENTER'));
|
||||
|
||||
// find error
|
||||
let error = await findByXpath('//form[@id="login"]//div[@class="error"]');
|
||||
const error = await findByXpath('//form[@id="login"]//div[@class="error"]');
|
||||
await waitUntilVisible(error, driver);
|
||||
let errorText = await error.getText();
|
||||
await expect(errorText).toEqual('This field is required.');
|
||||
const errorText = await error.getText();
|
||||
expect(errorText).toEqual('This field is required.');
|
||||
});
|
||||
|
||||
test('sign in with wrong username', async () => {
|
||||
let nonsenseUsername = Math.random().toString(36)
|
||||
const nonsenseUsername = Math.random().toString(36)
|
||||
.replace(/[^a-z]+/g, '')
|
||||
.substr(0, 5);
|
||||
await driver.get(scratchr2url);
|
||||
await clickXpath('//li[@class="sign-in dropdown"]/span');
|
||||
let name = await findByXpath('//input[@id="login_dropdown_username"]');
|
||||
const name = await findByXpath('//input[@id="login_dropdown_username"]');
|
||||
await name.sendKeys(nonsenseUsername);
|
||||
let word = await findByXpath('//input[@name="password"]');
|
||||
const word = await findByXpath('//input[@name="password"]');
|
||||
await word.sendKeys(password + getKey('ENTER'));
|
||||
|
||||
// find error
|
||||
let error = await findByXpath('//form[@id="login"]//div[@class="error"]');
|
||||
const error = await findByXpath('//form[@id="login"]//div[@class="error"]');
|
||||
await waitUntilVisible(error, driver);
|
||||
let errorText = await error.getText();
|
||||
await expect(errorText).toEqual('Incorrect username or password.');
|
||||
const errorText = await error.getText();
|
||||
expect(errorText).toEqual('Incorrect username or password.');
|
||||
});
|
||||
|
||||
test('sign in with wrong password', async () => {
|
||||
let nonsensePassword = Math.random().toString(36)
|
||||
const nonsensePassword = Math.random().toString(36)
|
||||
.replace(/[^a-z]+/g, '')
|
||||
.substr(0, 5);
|
||||
await driver.get(scratchr2url);
|
||||
await clickXpath('//li[@class="sign-in dropdown"]/span');
|
||||
let name = await findByXpath('//input[@id="login_dropdown_username"]');
|
||||
const name = await findByXpath('//input[@id="login_dropdown_username"]');
|
||||
await name.sendKeys(username);
|
||||
let word = await findByXpath('//input[@name="password"]');
|
||||
const word = await findByXpath('//input[@name="password"]');
|
||||
await word.sendKeys(nonsensePassword + getKey('ENTER'));
|
||||
|
||||
// find error
|
||||
let error = await findByXpath('//form[@id="login"]//div[@class="error"]');
|
||||
const error = await findByXpath('//form[@id="login"]//div[@class="error"]');
|
||||
await waitUntilVisible(error, driver);
|
||||
let errorText = await error.getText();
|
||||
await expect(errorText).toEqual('Incorrect username or password.');
|
||||
const errorText = await error.getText();
|
||||
expect(errorText).toEqual('Incorrect username or password.');
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -9,14 +9,14 @@ const {
|
||||
findByXpath
|
||||
} = new SeleniumHelper();
|
||||
|
||||
let rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
let statisticsPage = rootUrl + '/statistics';
|
||||
const rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
const statisticsPage = `${rootUrl}/statistics`;
|
||||
|
||||
jest.setTimeout(60000);
|
||||
|
||||
let driver;
|
||||
|
||||
describe('www-integration statistics page', async () => {
|
||||
describe('www-integration statistics page', () => {
|
||||
beforeAll(async () => {
|
||||
driver = await buildDriver('www-integration statistics page');
|
||||
});
|
||||
@ -25,37 +25,37 @@ describe('www-integration statistics page', async () => {
|
||||
await driver.get(statisticsPage);
|
||||
});
|
||||
|
||||
afterAll(async () => await driver.quit());
|
||||
afterAll(() => driver.quit());
|
||||
|
||||
test('check Monthly Activity Trends title', async () => {
|
||||
let chartTitle = await findByXpath('//div[contains(@class, "box0")]//h3');
|
||||
let chartTitleText = await chartTitle.getText();
|
||||
await expect(chartTitleText).toBe('Monthly Activity Trends');
|
||||
const chartTitle = await findByXpath('//div[contains(@class, "box0")]//h3');
|
||||
const chartTitleText = await chartTitle.getText();
|
||||
expect(chartTitleText).toBe('Monthly Activity Trends');
|
||||
});
|
||||
|
||||
test('New Projects label on first chart defaults to selected', async () => {
|
||||
let toggleXpath = `(//div[@id="activity_chart"]/*[name()='svg']/*[name()='g']/*[name()='g']/*` +
|
||||
const toggleXpath = `(//div[@id="activity_chart"]/*[name()='svg']/*[name()='g']/*[name()='g']/*` +
|
||||
`[name()='g'])[4]/*[name()='g']/*[name()='g']/*[name()='g']`;
|
||||
let newProjectsToggle = await findByXpath(toggleXpath);
|
||||
let toggleState = await containsClass(newProjectsToggle, 'nv-disabled');
|
||||
await expect(toggleState).toBe(false);
|
||||
const newProjectsToggle = await findByXpath(toggleXpath);
|
||||
const toggleState = await containsClass(newProjectsToggle, 'nv-disabled');
|
||||
expect(toggleState).toBe(false);
|
||||
|
||||
|
||||
});
|
||||
|
||||
test('New Projects label on first chart can be toggled', async () => {
|
||||
let toggleXpath = `(//div[@id="activity_chart"]/*[name()='svg']/*[name()='g']/*[name()='g']/*` +
|
||||
const toggleXpath = `(//div[@id="activity_chart"]/*[name()='svg']/*[name()='g']/*[name()='g']/*` +
|
||||
`[name()='g'])[4]/*[name()='g']/*[name()='g']/*[name()='g']`;
|
||||
let newProjectsToggle = await findByXpath(toggleXpath);
|
||||
const newProjectsToggle = await findByXpath(toggleXpath);
|
||||
|
||||
// toggle off New Projects
|
||||
await clickText('New Projects');
|
||||
let toggleState = await containsClass(newProjectsToggle, 'nv-disabled');
|
||||
await expect(toggleState).toBe(true);
|
||||
expect(toggleState).toBe(true);
|
||||
|
||||
// toggle New Projects on again
|
||||
await clickText('New Projects');
|
||||
toggleState = await containsClass(newProjectsToggle, 'nv-disabled');
|
||||
await expect(toggleState).toBe(false);
|
||||
expect(toggleState).toBe(false);
|
||||
});
|
||||
});
|
||||
|
@ -10,17 +10,17 @@ const {
|
||||
signIn
|
||||
} = new SeleniumHelper();
|
||||
|
||||
let rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
let studioId = process.env.TEST_STUDIO_ID || 10004360;
|
||||
let studioUrl = rootUrl + '/studios/' + studioId;
|
||||
let myStuffURL = rootUrl + '/mystuff';
|
||||
let rateLimitCheck = process.env.RATE_LIMIT_CHECK || rootUrl;
|
||||
const rootUrl = process.env.ROOT_URL || 'https://scratch.ly';
|
||||
const studioId = process.env.TEST_STUDIO_ID || 10004360;
|
||||
const studioUrl = `${rootUrl}/studios/${studioId}`;
|
||||
const myStuffURL = `${rootUrl}/mystuff`;
|
||||
const rateLimitCheck = process.env.RATE_LIMIT_CHECK || rootUrl;
|
||||
|
||||
// since the usernames end in 2 and 3 we're using username2 and username3
|
||||
// username 1 is used in other tests. Hopefully this is not confusing.
|
||||
let username2 = process.env.SMOKE_USERNAME + '2';
|
||||
let username3 = process.env.SMOKE_USERNAME + '3';
|
||||
let password = process.env.SMOKE_PASSWORD;
|
||||
const username2 = `${process.env.SMOKE_USERNAME}2`;
|
||||
const username3 = `${process.env.SMOKE_USERNAME}3`;
|
||||
const password = process.env.SMOKE_PASSWORD;
|
||||
|
||||
let promoteStudioURL;
|
||||
let curatorTab;
|
||||
@ -38,30 +38,30 @@ describe('studio page while signed out', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await driver.get(studioUrl);
|
||||
let studioNav = await findByXpath('//div[@class="studio-tabs"]');
|
||||
const studioNav = await findByXpath('//div[@class="studio-tabs"]');
|
||||
await studioNav.isDisplayed();
|
||||
});
|
||||
|
||||
afterAll(async () => await driver.quit());
|
||||
afterAll(() => driver.quit());
|
||||
|
||||
test('land on projects tab', async () => {
|
||||
await driver.get(studioUrl);
|
||||
let projectGrid = await findByXpath('//div[@class="studio-projects-grid"]');
|
||||
let projectGridDisplayed = await projectGrid.isDisplayed();
|
||||
await expect(projectGridDisplayed).toBe(true);
|
||||
const projectGrid = await findByXpath('//div[@class="studio-projects-grid"]');
|
||||
const projectGridDisplayed = await projectGrid.isDisplayed();
|
||||
expect(projectGridDisplayed).toBe(true);
|
||||
});
|
||||
|
||||
test('studio title', async () => {
|
||||
let studioTitle = await findByXpath('//div[@class="studio-title"]');
|
||||
let titleText = await studioTitle.getText();
|
||||
await expect(titleText).toEqual('studio for automated testing');
|
||||
const studioTitle = await findByXpath('//div[@class="studio-title"]');
|
||||
const titleText = await studioTitle.getText();
|
||||
expect(titleText).toEqual('studio for automated testing');
|
||||
});
|
||||
|
||||
test('studio description', async () => {
|
||||
let xpath = '//div[contains(@class, "studio-description")]';
|
||||
let studioDescription = await findByXpath(xpath);
|
||||
let descriptionText = await studioDescription.getText();
|
||||
await expect(descriptionText).toEqual('a description');
|
||||
const xpath = '//div[contains(@class, "studio-description")]';
|
||||
const studioDescription = await findByXpath(xpath);
|
||||
const descriptionText = await studioDescription.getText();
|
||||
expect(descriptionText).toEqual('a description');
|
||||
});
|
||||
});
|
||||
|
||||
@ -80,7 +80,7 @@ describe('studio management', () => {
|
||||
await clickXpath('//form[@id="new_studio"]/button[@type="submit"]');
|
||||
await findByXpath('//div[@class="studio-tabs"]');
|
||||
promoteStudioURL = await driver.getCurrentUrl();
|
||||
curatorTab = await promoteStudioURL + 'curators';
|
||||
curatorTab = `${promoteStudioURL}curators`;
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
@ -90,7 +90,7 @@ describe('studio management', () => {
|
||||
await findByXpath('//div[@class="studio-tabs"]');
|
||||
});
|
||||
|
||||
afterAll(async () => await driver.quit());
|
||||
afterAll(() => driver.quit());
|
||||
|
||||
test('invite a curator', async () => {
|
||||
// sign in as user2
|
||||
@ -98,13 +98,13 @@ describe('studio management', () => {
|
||||
await findByXpath('//span[contains(@class, "profile-name")]');
|
||||
|
||||
// invite user3 to curate
|
||||
let inviteBox = await findByXpath('//div[@class="studio-adder-row"]/input');
|
||||
const inviteBox = await findByXpath('//div[@class="studio-adder-row"]/input');
|
||||
await inviteBox.sendKeys(username3);
|
||||
await clickXpath('//div[@class="studio-adder-row"]/button');
|
||||
let inviteAlert = await findByXpath('//div[@class="alert-msg"]'); // the confirm alert
|
||||
let alertText = await inviteAlert.getText();
|
||||
let successText = await `Curator invite sent to "${username3}"`;
|
||||
await expect(alertText).toMatch(successText);
|
||||
const inviteAlert = await findByXpath('//div[@class="alert-msg"]'); // the confirm alert
|
||||
const alertText = await inviteAlert.getText();
|
||||
const successText = `Curator invite sent to "${username3}"`;
|
||||
expect(alertText).toMatch(successText);
|
||||
});
|
||||
|
||||
test('accept curator invite', async () => {
|
||||
@ -114,9 +114,9 @@ describe('studio management', () => {
|
||||
|
||||
// accept the curator invite
|
||||
await clickXpath('//button[@class="studio-invitation-button button"]');
|
||||
let acceptSuccess = await findByXpath('//div[contains(@class,"studio-info-box-success")]');
|
||||
let acceptSuccessVisible = await acceptSuccess.isDisplayed();
|
||||
await expect(acceptSuccessVisible).toBe(true);
|
||||
const acceptSuccess = await findByXpath('//div[contains(@class,"studio-info-box-success")]');
|
||||
const acceptSuccessVisible = await acceptSuccess.isDisplayed();
|
||||
expect(acceptSuccessVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('promote to manager', async () => {
|
||||
@ -128,20 +128,19 @@ describe('studio management', () => {
|
||||
await driver.get(curatorTab);
|
||||
|
||||
// promote user3
|
||||
let user3href = await '/users/' + username3;
|
||||
const user3href = `/users/${username3}`;
|
||||
// click kebab menu on the user tile
|
||||
let kebabMenuXpath = await `//a[@href = "${user3href}"]/` +
|
||||
'following-sibling::div[@class="overflow-menu-container"]';
|
||||
await clickXpath(kebabMenuXpath + '/button[@class="overflow-menu-trigger"]');
|
||||
const kebabMenuXpath = `//a[@href = "${user3href}"]/following-sibling::div[@class="overflow-menu-container"]`;
|
||||
await clickXpath(`${kebabMenuXpath}/button[@class="overflow-menu-trigger"]`);
|
||||
// click promote
|
||||
// await clickXpath('//button[@class="promote-menu-button"]'); //<-- I think this will do it
|
||||
await clickXpath(kebabMenuXpath + '/ul/li/button/span[contains(text(), "Promote")]/..');
|
||||
await clickXpath(`${kebabMenuXpath}/ul/li/button/span[contains(text(), "Promote")]/..`);
|
||||
await findByXpath('//div[@class="promote-content"]');
|
||||
// await clickXpath(//button[contains(@class="promote-button")]) <-- add this selector to the button
|
||||
await clickXpath('//div[@class="promote-button-row"]/button/span[contains(text(),"Promote")]/..');
|
||||
let promoteSuccess = await findByXpath('//div[contains(@class, "alert-success")]');
|
||||
let promoteSuccessVisible = await promoteSuccess.isDisplayed();
|
||||
await expect(promoteSuccessVisible).toBe(true);
|
||||
const promoteSuccess = await findByXpath('//div[contains(@class, "alert-success")]');
|
||||
const promoteSuccessVisible = await promoteSuccess.isDisplayed();
|
||||
expect(promoteSuccessVisible).toBe(true);
|
||||
});
|
||||
|
||||
test('transfer studio host', async () => {
|
||||
@ -152,11 +151,10 @@ describe('studio management', () => {
|
||||
await driver.get(curatorTab);
|
||||
|
||||
// open kebab menu
|
||||
let user2href = await '/users/' + username2;
|
||||
const user2href = `/users/${username2}`;
|
||||
// click kebab menu on the user tile
|
||||
let kebabMenuXpath = await `//a[@href = "${user2href}"]/` +
|
||||
'following-sibling::div[@class="overflow-menu-container"]';
|
||||
await clickXpath(kebabMenuXpath + '/button[@class="overflow-menu-trigger"]');
|
||||
const kebabMenuXpath = `//a[@href = "${user2href}"]/following-sibling::div[@class="overflow-menu-container"]`;
|
||||
await clickXpath(`${kebabMenuXpath}/button[@class="overflow-menu-trigger"]`);
|
||||
|
||||
// click transfer in dropdown
|
||||
await clickXpath('//button[@class="studio-member-tile-menu-wide"]');
|
||||
@ -175,15 +173,15 @@ describe('studio management', () => {
|
||||
await findByXpath('//div[@class="transfer-outcome"]');
|
||||
|
||||
// enter password
|
||||
let passwordInput = await findByXpath('//input[@class="transfer-password-input"]');
|
||||
const passwordInput = await findByXpath('//input[@class="transfer-password-input"]');
|
||||
await passwordInput.sendKeys(password);
|
||||
await findByXpath(`//input[@value="${password}"]`);
|
||||
|
||||
// click confirm
|
||||
// await clickXpath('//button[contains(@class, "confirm-transfer-button")]')
|
||||
await clickXpath('//span[contains(text(), "Confirm")]/..');
|
||||
let transferSuccess = await findByXpath('//div[contains(@class, "alert-success")]');
|
||||
let successVisible = await transferSuccess.isDisplayed();
|
||||
await expect(successVisible).toBe(true);
|
||||
const transferSuccess = await findByXpath('//div[contains(@class, "alert-success")]');
|
||||
const successVisible = await transferSuccess.isDisplayed();
|
||||
expect(successVisible).toBe(true);
|
||||
});
|
||||
});
|
||||
|
@ -9,16 +9,16 @@
|
||||
* with languages as keys and the missing IDs as values
|
||||
*/
|
||||
|
||||
var path = require('path');
|
||||
var fs = require('fs');
|
||||
var tap = require('tap');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const tap = require('tap');
|
||||
|
||||
/**
|
||||
* To get the files (containing message IDs and localized strings for each page in www)
|
||||
* from the intl directory
|
||||
*/
|
||||
var intlDirPath = path.resolve(__dirname, '../../intl/');
|
||||
var intlFiles = fs.readdirSync(intlDirPath);
|
||||
const intlDirPath = path.resolve(__dirname, '../../intl/');
|
||||
const intlFiles = fs.readdirSync(intlDirPath);
|
||||
|
||||
/*
|
||||
* Tells tap whether the test should pass or fail for a given file.
|
||||
@ -30,36 +30,36 @@ const noMissingStrings = (fileName, missingMessageId, pagesMissingIds) => {
|
||||
if (Object.keys(missingMessageId).length === 0) {
|
||||
tap.pass();
|
||||
} else {
|
||||
tap.fail(fileName + ' is missing string IDs');
|
||||
tap.fail(`${fileName} is missing string IDs`);
|
||||
pagesMissingIds[fileName] = [];
|
||||
pagesMissingIds[fileName].push(missingMessageId);
|
||||
}
|
||||
};
|
||||
|
||||
var pagesWithLanguagesMissingIds = {};
|
||||
const pagesWithLanguagesMissingIds = {};
|
||||
|
||||
for (var i in intlFiles) {
|
||||
var file = intlFiles[i];
|
||||
var filePath = path.resolve(__dirname, '../../intl/' + file);
|
||||
var pageMessagesString = fs.readFileSync(filePath, 'utf8');
|
||||
for (const i in intlFiles) {
|
||||
const file = intlFiles[i];
|
||||
const filePath = path.resolve(__dirname, `../../intl/${file}`);
|
||||
const pageMessagesString = fs.readFileSync(filePath, 'utf8');
|
||||
|
||||
/**
|
||||
* To make the string of the file of the page.intl.js back into useable objects
|
||||
*/
|
||||
var window = {};
|
||||
var pageMessages = eval(pageMessagesString); // eslint-disable-line no-eval
|
||||
const window = {};
|
||||
const pageMessages = eval(pageMessagesString); // eslint-disable-line no-eval
|
||||
|
||||
/**
|
||||
* The goal is to compare the IDs for each language to the IDs for English,
|
||||
* so we need the list of IDs for the given page in English
|
||||
*/
|
||||
var englishIdList = window._messages.en;
|
||||
const englishIdList = window._messages.en;
|
||||
|
||||
var messageIdNotInLanguage = {};
|
||||
const messageIdNotInLanguage = {};
|
||||
|
||||
for (var languageKey in pageMessages) {
|
||||
var currentLanguageObject = pageMessages[languageKey];
|
||||
for (var messageId in englishIdList) {
|
||||
for (const languageKey in pageMessages) {
|
||||
const currentLanguageObject = pageMessages[languageKey];
|
||||
for (const messageId in englishIdList) {
|
||||
if (!(messageId in currentLanguageObject)) {
|
||||
if (typeof messageIdNotInLanguage[languageKey] === 'undefined') {
|
||||
messageIdNotInLanguage[languageKey] = [];
|
||||
|
@ -1,20 +1,20 @@
|
||||
var fs = require('fs');
|
||||
var glob = require('glob');
|
||||
var tap = require('tap');
|
||||
const fs = require('fs');
|
||||
const glob = require('glob');
|
||||
const tap = require('tap');
|
||||
|
||||
var TRANSLATIONS_PATTERN = './node_modules/scratch-l10n/www/**/*.json';
|
||||
var files = glob.sync(TRANSLATIONS_PATTERN);
|
||||
const TRANSLATIONS_PATTERN = './node_modules/scratch-l10n/www/**/*.json';
|
||||
const files = glob.sync(TRANSLATIONS_PATTERN);
|
||||
|
||||
const checkJson = (data, name) => {
|
||||
try {
|
||||
JSON.parse(data);
|
||||
} catch (e) {
|
||||
tap.fail(name + ' has invalid Json.\n');
|
||||
tap.fail(`${name} has invalid Json.\n`);
|
||||
}
|
||||
};
|
||||
|
||||
tap.test('check valid json', function (t) {
|
||||
files.forEach(function (f) {
|
||||
tap.test('check valid json', t => {
|
||||
files.forEach(f => {
|
||||
const data = fs.readFileSync(f);
|
||||
checkJson(data, f);
|
||||
});
|
||||
|
@ -1,9 +1,9 @@
|
||||
var defaults = require('lodash.defaults');
|
||||
var fastlyConfig = require('../../bin/lib/fastly-config-methods');
|
||||
var routeJson = require('../../src/routes.json');
|
||||
var tap = require('tap');
|
||||
const defaults = require('lodash.defaults');
|
||||
const fastlyConfig = require('../../bin/lib/fastly-config-methods');
|
||||
const routeJson = require('../../src/routes.json');
|
||||
const tap = require('tap');
|
||||
|
||||
var testRoutes = [
|
||||
const testRoutes = [
|
||||
{
|
||||
name: 'less-traveled',
|
||||
pattern: '^/?$',
|
||||
@ -20,10 +20,10 @@ var testRoutes = [
|
||||
}
|
||||
];
|
||||
|
||||
var routes = routeJson.map(function (route) {
|
||||
return defaults({}, {pattern: fastlyConfig.expressPatternToRegex(route.pattern)}, route);
|
||||
});
|
||||
var extraAppRoutes = [
|
||||
const routes = routeJson.map(route =>
|
||||
defaults({}, {pattern: fastlyConfig.expressPatternToRegex(route.pattern)}, route)
|
||||
);
|
||||
const extraAppRoutes = [
|
||||
// Homepage with querystring.
|
||||
// TODO: Should this be added for every route?
|
||||
'/\\?',
|
||||
@ -32,35 +32,35 @@ var extraAppRoutes = [
|
||||
];
|
||||
|
||||
|
||||
tap.test('getStaticPaths', function (t) {
|
||||
var staticPaths = fastlyConfig.getStaticPaths(__dirname, '../../build/*');
|
||||
tap.test('getStaticPaths', t => {
|
||||
const staticPaths = fastlyConfig.getStaticPaths(__dirname, '../../build/*');
|
||||
t.type(staticPaths, 'object');
|
||||
t.end();
|
||||
});
|
||||
|
||||
tap.test('getViewPaths', function (t) {
|
||||
var viewPaths = fastlyConfig.getViewPaths(testRoutes);
|
||||
tap.test('getViewPaths', t => {
|
||||
const viewPaths = fastlyConfig.getViewPaths(testRoutes);
|
||||
t.type(viewPaths, 'object');
|
||||
t.equal(viewPaths[0], '/?$');
|
||||
t.equal(viewPaths[1], '/more?$');
|
||||
t.end();
|
||||
});
|
||||
|
||||
tap.test('pathsToCondition', function (t) {
|
||||
var condition = fastlyConfig.pathsToCondition(['/?$', '/more?$']);
|
||||
tap.test('pathsToCondition', t => {
|
||||
const condition = fastlyConfig.pathsToCondition(['/?$', '/more?$']);
|
||||
t.type(condition, 'string');
|
||||
t.equal(condition, 'req.url~"^(/?$|/more?$)"');
|
||||
t.end();
|
||||
});
|
||||
|
||||
tap.test('getAppRouteCondition', function (t) {
|
||||
var condition = fastlyConfig.getAppRouteCondition('../../build/*', routes, extraAppRoutes, __dirname);
|
||||
tap.test('getAppRouteCondition', t => {
|
||||
const condition = fastlyConfig.getAppRouteCondition('../../build/*', routes, extraAppRoutes, __dirname);
|
||||
t.type(condition, 'string');
|
||||
t.end();
|
||||
});
|
||||
|
||||
tap.test('testSetTTL', function (t) {
|
||||
var ttl = fastlyConfig.setResponseTTL('itsactuallyttyl');
|
||||
tap.test('testSetTTL', t => {
|
||||
const ttl = fastlyConfig.setResponseTTL('itsactuallyttyl');
|
||||
t.equal(ttl, '' +
|
||||
'if (itsactuallyttyl) {\n' +
|
||||
' if (req.url ~ "^(/projects/|/fragment/account-nav.json|/session/)" && ' +
|
||||
|
@ -33,18 +33,6 @@ describe('Captcha test', () => {
|
||||
expect(global.grecaptcha.execute).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('Captcha load calls props captchaOnLoad', () => {
|
||||
const props = {
|
||||
onCaptchaLoad: jest.fn()
|
||||
};
|
||||
const wrapper = enzyme.shallow(<Captcha
|
||||
{...props}
|
||||
/>);
|
||||
wrapper.instance().onCaptchaLoad();
|
||||
expect(global.grecaptcha.render).toHaveBeenCalled();
|
||||
expect(props.onCaptchaLoad).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('Captcha renders the div google wants', () => {
|
||||
const props = {
|
||||
onCaptchaLoad: jest.fn()
|
||||
|
@ -7,7 +7,7 @@ import configureStore from 'redux-mock-store';
|
||||
describe('Compose Comment test', () => {
|
||||
const mockStore = configureStore();
|
||||
let _mockFormat;
|
||||
const defaultProps = () =>({
|
||||
const defaultProps = () => ({
|
||||
user: {
|
||||
thumbnailUrl: 'scratch.mit.edu',
|
||||
username: 'auser'
|
||||
@ -51,7 +51,7 @@ describe('Compose Comment test', () => {
|
||||
return wrapper;
|
||||
};
|
||||
|
||||
test('status is EDITING when props do not contain a muteStatus ', () => {
|
||||
test('status is EDITING when props do not contain a muteStatus', () => {
|
||||
const commentInstance = getComposeCommentWrapper({}).instance();
|
||||
expect(commentInstance.state.status).toBe('EDITING');
|
||||
});
|
||||
@ -81,7 +81,7 @@ describe('Compose Comment test', () => {
|
||||
global.Date.now = realDateNow;
|
||||
});
|
||||
|
||||
test('Modal & Comment status do not show ', () => {
|
||||
test('Modal & Comment status do not show', () => {
|
||||
const component = getComposeCommentWrapper({});
|
||||
// Comment compsoe box is there
|
||||
expect(component.find('FlexRow.compose-comment').exists()).toEqual(true);
|
||||
@ -95,7 +95,7 @@ describe('Compose Comment test', () => {
|
||||
|
||||
});
|
||||
|
||||
test('Error messages shows when comment rejected ', () => {
|
||||
test('Error messages shows when comment rejected', () => {
|
||||
const component = getComposeCommentWrapper({});
|
||||
const commentInstance = component.instance();
|
||||
commentInstance.setState({
|
||||
@ -109,7 +109,7 @@ describe('Compose Comment test', () => {
|
||||
expect(component.find('Button.compose-cancel').props().disabled).toBe(false);
|
||||
});
|
||||
|
||||
test('No error message shows when comment rejected because user is already muted ', () => {
|
||||
test('No error message shows when comment rejected because user is already muted', () => {
|
||||
const component = getComposeCommentWrapper({});
|
||||
const commentInstance = component.instance();
|
||||
commentInstance.setState({
|
||||
@ -278,7 +278,7 @@ describe('Compose Comment test', () => {
|
||||
expect(component.find('Button.compose-cancel').props().disabled).toBe(false);
|
||||
});
|
||||
|
||||
test('Mute Modal shows when muteOpen is true ', () => {
|
||||
test('Mute Modal shows when muteOpen is true', () => {
|
||||
const realDateNow = Date.now.bind(global.Date);
|
||||
global.Date.now = () => 0;
|
||||
const store = mockStore({
|
||||
@ -390,18 +390,18 @@ describe('Compose Comment test', () => {
|
||||
expect(component.find('MuteModal').exists()).toEqual(true);
|
||||
expect(component.find('MuteModal').props().showFeedback).toBe(false);
|
||||
});
|
||||
test('shouldShowMuteModal is false when muteStatus is undefined ', () => {
|
||||
test('shouldShowMuteModal is false when muteStatus is undefined', () => {
|
||||
const commentInstance = getComposeCommentWrapper({}).instance();
|
||||
expect(commentInstance.shouldShowMuteModal()).toBe(false);
|
||||
});
|
||||
|
||||
test('shouldShowMuteModal is false when list is undefined ', () => {
|
||||
test('shouldShowMuteModal is false when list is undefined', () => {
|
||||
const muteStatus = {};
|
||||
const commentInstance = getComposeCommentWrapper({}).instance();
|
||||
expect(commentInstance.shouldShowMuteModal(muteStatus)).toBe(false);
|
||||
});
|
||||
|
||||
test('shouldShowMuteModal is false when list empty ', () => {
|
||||
test('shouldShowMuteModal is false when list empty', () => {
|
||||
const muteStatus = {
|
||||
offenses: []
|
||||
};
|
||||
@ -409,7 +409,7 @@ describe('Compose Comment test', () => {
|
||||
expect(commentInstance.shouldShowMuteModal(muteStatus)).toBe(false);
|
||||
});
|
||||
|
||||
test('shouldShowMuteModal is true when only 1 recent offesnse ', () => {
|
||||
test('shouldShowMuteModal is true when only 1 recent offesnse', () => {
|
||||
const realDateNow = Date.now.bind(global.Date);
|
||||
global.Date.now = () => 0;
|
||||
// Since Date.now mocked to 0 above, we just need a small number to make
|
||||
@ -426,13 +426,13 @@ describe('Compose Comment test', () => {
|
||||
global.Date.now = realDateNow;
|
||||
});
|
||||
|
||||
test('shouldShowMuteModal is false when multiple offenses, even if 1 is recent ', () => {
|
||||
test('shouldShowMuteModal is false when multiple offenses, even if 1 is recent', () => {
|
||||
const offenses = [];
|
||||
const realDateNow = Date.now.bind(global.Date);
|
||||
global.Date.now = () => 0;
|
||||
// Since Date.now mocked to 0 above, we just need a small number to make
|
||||
// it look like it was created more than 2 minutes ago.
|
||||
let offense = {
|
||||
const offense = {
|
||||
expiresAt: '1000',
|
||||
createdAt: '-119' // just shy of two min ago
|
||||
};
|
||||
@ -453,7 +453,7 @@ describe('Compose Comment test', () => {
|
||||
global.Date.now = () => 0;
|
||||
// Since Date.now mocked to 0 above, we just need a small number to make
|
||||
// it look like it was created more than 2 minutes ago.
|
||||
let offense = {
|
||||
const offense = {
|
||||
expiresAt: '1000',
|
||||
createdAt: '-119' // just shy of two min ago
|
||||
};
|
||||
@ -469,7 +469,7 @@ describe('Compose Comment test', () => {
|
||||
global.Date.now = realDateNow;
|
||||
});
|
||||
|
||||
test('shouldShowMuteModal is false when the user is already muted, even when only 1 recent offesnse ', () => {
|
||||
test('shouldShowMuteModal is false when the user is already muted, even when only 1 recent offesnse', () => {
|
||||
const realDateNow = Date.now.bind(global.Date);
|
||||
global.Date.now = () => 0;
|
||||
// Since Date.now mocked to 0 above, we just need a small number to make
|
||||
@ -510,7 +510,7 @@ describe('Compose Comment test', () => {
|
||||
expect(commentInstance.getMuteModalStartStep()).toBe(0);
|
||||
});
|
||||
|
||||
test('getMuteModalStartStep: A reply that got them muted ', () => {
|
||||
test('getMuteModalStartStep: A reply that got them muted', () => {
|
||||
const commentInstance = getComposeCommentWrapper({isReply: true}).instance();
|
||||
commentInstance.setState({
|
||||
status: 'REJECTED_MUTE'
|
||||
@ -518,7 +518,7 @@ describe('Compose Comment test', () => {
|
||||
expect(commentInstance.getMuteModalStartStep()).toBe(0);
|
||||
});
|
||||
|
||||
test('getMuteModalStartStep: A reply click when already muted ', () => {
|
||||
test('getMuteModalStartStep: A reply click when already muted', () => {
|
||||
const commentInstance = getComposeCommentWrapper({isReply: true}).instance();
|
||||
commentInstance.setState({
|
||||
status: 'COMPOSE_DISALLOWED'
|
||||
@ -526,7 +526,7 @@ describe('Compose Comment test', () => {
|
||||
expect(commentInstance.getMuteModalStartStep()).toBe(1);
|
||||
});
|
||||
|
||||
test('isMuted: expiration is in the future ', () => {
|
||||
test('isMuted: expiration is in the future', () => {
|
||||
const realDateNow = Date.now.bind(global.Date);
|
||||
global.Date.now = () => 0; // Set "now" to 0 for easier testing.
|
||||
|
||||
@ -536,7 +536,7 @@ describe('Compose Comment test', () => {
|
||||
global.Date.now = realDateNow;
|
||||
});
|
||||
|
||||
test('isMuted: expiration is in the past ', () => {
|
||||
test('isMuted: expiration is in the past', () => {
|
||||
const realDateNow = Date.now.bind(global.Date);
|
||||
global.Date.now = () => 0;
|
||||
|
||||
@ -546,7 +546,7 @@ describe('Compose Comment test', () => {
|
||||
global.Date.now = realDateNow;
|
||||
});
|
||||
|
||||
test('isMuted: expiration is not set ', () => {
|
||||
test('isMuted: expiration is not set', () => {
|
||||
const realDateNow = Date.now.bind(global.Date);
|
||||
global.Date.now = () => 0;
|
||||
|
||||
|
@ -23,7 +23,7 @@ describe('DonateBannerTest', () => {
|
||||
expect(component.find('FormattedMessage[id="donatebanner.askSupport"]').exists()).toEqual(false);
|
||||
|
||||
});
|
||||
test('testing default message comes back after May 21 ', () => {
|
||||
test('testing default message comes back after May 21', () => {
|
||||
// Date after Scratch week
|
||||
global.Date.now = () => new Date(2022, 4, 22).getTime();
|
||||
const component = mountWithIntl(
|
||||
|
@ -19,7 +19,7 @@ const requestFailureResponse = {
|
||||
// lets us change where remoteRequestResponse points later, without actually changing
|
||||
// mockedValidateEmailRemotely.
|
||||
let remoteRequestResponse = requestSuccessResponse;
|
||||
let mockedValidateEmailRemotely = jest.fn(() => (
|
||||
const mockedValidateEmailRemotely = jest.fn(() => (
|
||||
/* eslint-disable no-undef */
|
||||
Promise.resolve(remoteRequestResponse)
|
||||
/* eslint-enable no-undef */
|
||||
|
@ -1,8 +1,7 @@
|
||||
import React from 'react';
|
||||
import {mountWithIntl} from '../../helpers/intl-helpers.jsx';
|
||||
import FormikSelect from '../../../src/components/formik-forms/formik-select.jsx';
|
||||
import {Formik} from 'formik';
|
||||
import {Field} from 'formik';
|
||||
import {Field, Formik} from 'formik';
|
||||
|
||||
describe('FormikSelect', () => {
|
||||
test('No validation message without an error', () => {
|
||||
|
@ -30,7 +30,7 @@ describe('InfoButton', () => {
|
||||
|
||||
// mouseOver info button
|
||||
component.find('div.info-button').simulate('mouseOver');
|
||||
setTimeout(function () { // necessary because mouseover uses debounce
|
||||
setTimeout(() => { // necessary because mouseover uses debounce
|
||||
// crucial: if we don't call update(), then find() below looks through an OLD
|
||||
// version of the DOM! see https://github.com/airbnb/enzyme/issues/1233#issuecomment-358915200
|
||||
component.update();
|
||||
@ -70,7 +70,7 @@ describe('InfoButton', () => {
|
||||
|
||||
// mouseLeave from info button
|
||||
component.find('div.info-button').simulate('mouseLeave');
|
||||
setTimeout(function () { // necessary because mouseover uses debounce
|
||||
setTimeout(() => { // necessary because mouseover uses debounce
|
||||
component.update();
|
||||
expect(component.find('div.info-button-message').exists()).toEqual(true);
|
||||
done();
|
||||
|
@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import {shallowWithIntl} from '../../helpers/intl-helpers.jsx';
|
||||
import {mountWithIntl} from '../../helpers/intl-helpers.jsx';
|
||||
import {mountWithIntl, shallowWithIntl} from '../../helpers/intl-helpers.jsx';
|
||||
import MuteModal from '../../../src/components/modal/mute/modal';
|
||||
import Modal from '../../../src/components/modal/base/modal';
|
||||
|
||||
|
@ -3,7 +3,7 @@ import {mountWithIntl} from '../../helpers/intl-helpers.jsx';
|
||||
import MuteStep from '../../../src/components/modal/mute/mute-step';
|
||||
|
||||
describe('MuteStepTest', () => {
|
||||
test('Mute Step with no images ', () => {
|
||||
test('Mute Step with no images', () => {
|
||||
const component = mountWithIntl(
|
||||
<MuteStep
|
||||
header="header text"
|
||||
@ -19,7 +19,7 @@ describe('MuteStepTest', () => {
|
||||
|
||||
});
|
||||
|
||||
test('Mute Step with side image ', () => {
|
||||
test('Mute Step with side image', () => {
|
||||
const component = mountWithIntl(
|
||||
<MuteStep
|
||||
sideImg="/path/to/img.png"
|
||||
@ -34,7 +34,7 @@ describe('MuteStepTest', () => {
|
||||
|
||||
});
|
||||
|
||||
test('Mute Step with bottom image ', () => {
|
||||
test('Mute Step with bottom image', () => {
|
||||
const component = mountWithIntl(
|
||||
<MuteStep
|
||||
bottomImg="/path/to/img.png"
|
||||
|
@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import {shallowWithIntl} from '../../helpers/intl-helpers.jsx';
|
||||
import {mountWithIntl} from '../../helpers/intl-helpers.jsx';
|
||||
import {mountWithIntl, shallowWithIntl} from '../../helpers/intl-helpers.jsx';
|
||||
import JoinFlowStep from '../../../src/components/join-flow/join-flow-step';
|
||||
import RegistrationErrorStep from '../../../src/components/join-flow/registration-error-step';
|
||||
|
||||
|
@ -54,7 +54,7 @@ describe('Studio comments', () => {
|
||||
});
|
||||
test('calling onOpen sets a class on the #viewEl and records in local storage', () => {
|
||||
const component = mountWithIntl(<StudioAdminPanel showAdminPanel />);
|
||||
let child = component.find(AdminPanel);
|
||||
const child = component.find(AdminPanel);
|
||||
expect(viewEl.classList.contains(adminPanelOpenClass)).toBe(false);
|
||||
// `act` is a test-util function for making react state updates sync
|
||||
act(child.prop('onOpen'));
|
||||
@ -69,7 +69,7 @@ describe('Studio comments', () => {
|
||||
showAdminPanel
|
||||
/>
|
||||
);
|
||||
let child = component.find('iframe');
|
||||
const child = component.find('iframe');
|
||||
expect(child.getDOMNode().src).toMatch('/scratch2-studios/123/adminpanel');
|
||||
});
|
||||
test('responds to closePanel MessageEvent from the iframe', () => {
|
||||
|
@ -17,7 +17,7 @@ const requestFailureResponse = {
|
||||
// lets us change where remoteRequestResponse points later, without actually changing
|
||||
// mockedValidateUsernameRemotely.
|
||||
let remoteRequestResponse = requestSuccessResponse;
|
||||
let mockedValidateUsernameRemotely = jest.fn(() => (
|
||||
const mockedValidateUsernameRemotely = jest.fn(() => (
|
||||
/* eslint-disable no-undef */
|
||||
Promise.resolve(remoteRequestResponse)
|
||||
/* eslint-enable no-undef */
|
||||
|
@ -6,7 +6,7 @@ describe('unit test lib/format-time.js', () => {
|
||||
const mockFormatExpression = {
|
||||
format: jest.fn()
|
||||
};
|
||||
beforeEach(() =>{
|
||||
beforeEach(() => {
|
||||
realDateNow = Date.now.bind(global.Date);
|
||||
global.Date.now = () => 0;
|
||||
_mockFormat = Intl.RelativeTimeFormat = jest
|
||||
@ -14,68 +14,68 @@ describe('unit test lib/format-time.js', () => {
|
||||
.mockImplementation(() => mockFormatExpression);
|
||||
|
||||
});
|
||||
afterEach(()=>{
|
||||
afterEach(() => {
|
||||
global.Date.now = realDateNow;
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
test('test timestamp that is 2 minutes in the future', () => {
|
||||
test('timestamp that is 2 minutes in the future', () => {
|
||||
const twoMin = 2 * 60 * 1000;
|
||||
mockFormatExpression.format.mockReturnValue('in 2 minutes');
|
||||
format.formatRelativeTime(twoMin, 'en');
|
||||
expect(mockFormatExpression.format).toHaveBeenCalledWith(2, 'minute');
|
||||
});
|
||||
|
||||
test('test timestamp that is 15 seconds in the future displays 1', () => {
|
||||
test('timestamp that is 15 seconds in the future displays 1', () => {
|
||||
const fifteenSec = 15 * 1000;
|
||||
mockFormatExpression.format.mockReturnValue('in 1 minute');
|
||||
format.formatRelativeTime(fifteenSec, 'en');
|
||||
expect(mockFormatExpression.format).toHaveBeenCalledWith(1, 'minute');
|
||||
});
|
||||
|
||||
test('test rounding timestamp that is 4.4 minutes rounds to 4', () => {
|
||||
test('rounding timestamp that is 4.4 minutes rounds to 4', () => {
|
||||
const fourPlusMin = 4.4 * 60 * 1000;
|
||||
mockFormatExpression.format.mockReturnValue('in 4 minutes');
|
||||
format.formatRelativeTime(fourPlusMin, 'en');
|
||||
expect(mockFormatExpression.format).toHaveBeenCalledWith(4, 'minute');
|
||||
});
|
||||
|
||||
test('test timestamp that is 95.25 minutes in the future', () => {
|
||||
test('timestamp that is 95.25 minutes in the future', () => {
|
||||
const ninetyFiveMin = 95.25 * 60 * 1000;
|
||||
mockFormatExpression.format.mockReturnValue('in 95 minutes');
|
||||
format.formatRelativeTime(ninetyFiveMin, 'en');
|
||||
expect(mockFormatExpression.format).toHaveBeenCalledWith(95, 'minute');
|
||||
});
|
||||
|
||||
test('test timestamp that is 119 minutes in the future', () => {
|
||||
test('timestamp that is 119 minutes in the future', () => {
|
||||
const ninetyFiveMin = 119 * 60 * 1000;
|
||||
mockFormatExpression.format.mockReturnValue('in 199 minutes');
|
||||
format.formatRelativeTime(ninetyFiveMin, 'en');
|
||||
expect(mockFormatExpression.format).toHaveBeenCalledWith(119, 'minute');
|
||||
});
|
||||
|
||||
test('test timestamp that is 48 hours in the future', () => {
|
||||
test('timestamp that is 48 hours in the future', () => {
|
||||
const fortyEightHrs = 48 * 60 * 60 * 1000;
|
||||
mockFormatExpression.format.mockReturnValue('in 48 hours');
|
||||
format.formatRelativeTime(fortyEightHrs, 'en');
|
||||
expect(mockFormatExpression.format).toHaveBeenCalledWith(48, 'hour');
|
||||
});
|
||||
|
||||
test('test timestamp that is 2.6 hours rounds to 3', () => {
|
||||
test('timestamp that is 2.6 hours rounds to 3', () => {
|
||||
const twoPlusHours = 2.6 * 60 * 60 * 1000;
|
||||
mockFormatExpression.format.mockReturnValue('in 3 hours');
|
||||
format.formatRelativeTime(twoPlusHours, 'en');
|
||||
expect(mockFormatExpression.format).toHaveBeenCalledWith(3, 'hour');
|
||||
});
|
||||
|
||||
test('test timestamp that is 4.2 hours in the future rounds to 4', () => {
|
||||
test('timestamp that is 4.2 hours in the future rounds to 4', () => {
|
||||
const fourPlusHours = 4.2 * 60 * 60 * 1000;
|
||||
mockFormatExpression.format.mockReturnValue('in 4 hours');
|
||||
format.formatRelativeTime(fourPlusHours, 'en');
|
||||
expect(mockFormatExpression.format).toHaveBeenCalledWith(4, 'hour');
|
||||
});
|
||||
|
||||
test('test timestamp that is 2 hours in the future is in hours', () => {
|
||||
test('timestamp that is 2 hours in the future is in hours', () => {
|
||||
const twoHours = 2 * 60 * 60 * 1000;
|
||||
mockFormatExpression.format.mockReturnValue('in 2 hours');
|
||||
format.formatRelativeTime(twoHours, 'en');
|
||||
|
@ -14,7 +14,7 @@ describe('unit test lib/jar.js', () => {
|
||||
expires: expect.anything() // not specifically matching the date because it is hard to mock
|
||||
}));
|
||||
});
|
||||
test('test with opts', () => {
|
||||
test('with opts', () => {
|
||||
jar.set('a', 'b', {option: 'one'});
|
||||
expect(cookie.serialize).toHaveBeenCalled();
|
||||
expect(cookie.serialize).toHaveBeenCalledWith('a', 'b',
|
||||
|
@ -7,20 +7,17 @@ describe('unit test lib/route.js', () => {
|
||||
});
|
||||
|
||||
test('getURIClassroomToken parses URI paths like /classes/21/register/r9n5f5xk', () => {
|
||||
let response;
|
||||
response = route.getURIClassroomToken('/classes/21/register/r9n5f5xk');
|
||||
const response = route.getURIClassroomToken('/classes/21/register/r9n5f5xk');
|
||||
expect(response).toEqual('r9n5f5xk');
|
||||
});
|
||||
|
||||
test('getURIClassroomToken parses URI paths like /signup/e2dcfkx95', () => {
|
||||
let response;
|
||||
response = route.getURIClassroomToken('/signup/e2dcfkx95');
|
||||
const response = route.getURIClassroomToken('/signup/e2dcfkx95');
|
||||
expect(response).toEqual('e2dcfkx95');
|
||||
});
|
||||
|
||||
test('getURIClassroomToken works with trailing slash', () => {
|
||||
let response;
|
||||
response = route.getURIClassroomToken('/signup/r9n5f5xk/');
|
||||
const response = route.getURIClassroomToken('/signup/r9n5f5xk/');
|
||||
expect(response).toEqual('r9n5f5xk');
|
||||
});
|
||||
});
|
||||
|
@ -1,16 +1,16 @@
|
||||
describe('session library', () => {
|
||||
// respond to session requests with empty session object
|
||||
let sessionNoUser = jest.fn((opts, callback) => {
|
||||
const sessionNoUser = jest.fn((opts, callback) => {
|
||||
callback(null, {}, {statusCode: 200});
|
||||
});
|
||||
// respond to session requests with session object that indicates
|
||||
// successfully logged-in user
|
||||
let sessionYesUser = jest.fn((opts, callback) => {
|
||||
const sessionYesUser = jest.fn((opts, callback) => {
|
||||
callback(null, {user: {username: 'test_username'}}, {statusCode: 200});
|
||||
});
|
||||
// respond to first two requests with empty session object; after that,
|
||||
// respond with user in object
|
||||
let sessionNoThenYes = jest.fn((opts, callback) => {
|
||||
const sessionNoThenYes = jest.fn((opts, callback) => {
|
||||
if (sessionNoThenYes.mock.calls.length <= 2) {
|
||||
callback(null, {}, {statusCode: 200});
|
||||
} else {
|
||||
@ -19,24 +19,22 @@ describe('session library', () => {
|
||||
});
|
||||
// respond to session requests with response code 404, indicating no session
|
||||
// found for that user
|
||||
let sessionNotFound = jest.fn((opts, callback) => {
|
||||
const sessionNotFound = jest.fn((opts, callback) => {
|
||||
callback(null, null, {statusCode: 404});
|
||||
});
|
||||
// respond to session requests with response code 503, indicating connection failure
|
||||
let sessionConnectFailure = jest.fn((opts, callback) => {
|
||||
const sessionConnectFailure = jest.fn((opts, callback) => {
|
||||
callback(null, null, {statusCode: 503});
|
||||
});
|
||||
|
||||
// by changing whichMockAPIRequest, we can simulate different api responses
|
||||
let whichMockAPIRequest = null;
|
||||
let mockAPIRequest = (opts, callback) => {
|
||||
const mockAPIRequest = (opts, callback) => {
|
||||
whichMockAPIRequest(opts, callback);
|
||||
};
|
||||
|
||||
// mock lib/api.js, and include our mocked version in lib/session.js
|
||||
jest.mock('../../../src/lib/api', () => {
|
||||
return mockAPIRequest;
|
||||
});
|
||||
jest.mock('../../../src/lib/api', () => mockAPIRequest);
|
||||
const sessionLib = require('../../../src/lib/session'); // eslint-disable-line global-require
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -173,7 +173,7 @@ describe('unit test lib/validate.js', () => {
|
||||
});
|
||||
|
||||
test('responseErrorMsg is null in case where there is no dedicated string for that case', () => {
|
||||
let response = validate.responseErrorMsg('username', 'some error that is not covered');
|
||||
const response = validate.responseErrorMsg('username', 'some error that is not covered');
|
||||
expect(response).toEqual(null);
|
||||
});
|
||||
});
|
||||
|
@ -121,7 +121,7 @@ describe('Infinite List redux module', () => {
|
||||
|
||||
describe('ERROR', () => {
|
||||
let action;
|
||||
let error = new Error();
|
||||
const error = new Error();
|
||||
beforeEach(() => {
|
||||
action = module.actions.error(error);
|
||||
});
|
||||
@ -145,7 +145,7 @@ describe('Infinite List redux module', () => {
|
||||
describe('action creators', () => {
|
||||
test('module contains actions creators', () => {
|
||||
// The actual action creators are tested above in the reducer tests
|
||||
for (let key in module.actions) {
|
||||
for (const key in module.actions) {
|
||||
expect(typeof module.actions[key]).toBe('function');
|
||||
}
|
||||
});
|
||||
|
@ -14,7 +14,7 @@ beforeEach(() => {
|
||||
});
|
||||
|
||||
describe('getTopLevelComments', () => {
|
||||
test('replies are only loaded for comments with a reply_count > 0', async () => {
|
||||
test('replies are only loaded for comments with a reply_count > 0', () => {
|
||||
api.mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/users/u/projects/123123/comments');
|
||||
const body = [
|
||||
@ -43,8 +43,8 @@ describe('getTopLevelComments', () => {
|
||||
expect(state.comments.replies[1]).toBeUndefined();
|
||||
expect(state.comments.replies[60]).toBeUndefined();
|
||||
});
|
||||
test('admin route is used correctly', async () => {
|
||||
api.mockImplementationOnce((opts) => {
|
||||
test('admin route is used correctly', () => {
|
||||
api.mockImplementationOnce(opts => {
|
||||
// NB: this route doesn't include the owner username
|
||||
expect(opts.uri).toBe('/admin/projects/123123/comments');
|
||||
expect(opts.authentication).toBe('a-token');
|
||||
@ -54,7 +54,7 @@ describe('getTopLevelComments', () => {
|
||||
});
|
||||
|
||||
describe('getCommentById', () => {
|
||||
test('getting a top level comment will not load replies if there arent any', async () => {
|
||||
test('getting a top level comment will not load replies if there arent any', () => {
|
||||
api.mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/users/u/projects/123123/comments/111');
|
||||
const body = {id: 111, parent_id: null, reply_count: 0};
|
||||
@ -66,8 +66,8 @@ describe('getCommentById', () => {
|
||||
expect(state.comments.replies[111]).toBeUndefined();
|
||||
});
|
||||
|
||||
test('admin route is used correctly', async () => {
|
||||
api.mockImplementationOnce((opts) => {
|
||||
test('admin route is used correctly', () => {
|
||||
api.mockImplementationOnce(opts => {
|
||||
// NB: this route doesn't include the owner username
|
||||
expect(opts.uri).toBe('/admin/projects/123123/comments/111');
|
||||
expect(opts.authentication).toBe('a-token');
|
||||
@ -75,7 +75,7 @@ describe('getCommentById', () => {
|
||||
store.dispatch(actions.getCommentById(123123, 111, 'u', true, 'a-token'));
|
||||
});
|
||||
|
||||
test('getting a top level comment will load replies', async () => {
|
||||
test('getting a top level comment will load replies', () => {
|
||||
api.mockImplementationOnce((opts, callback) => {
|
||||
expect(opts.uri).toBe('/users/u/projects/123123/comments/111');
|
||||
const body = {id: 111, parent_id: null, reply_count: 2};
|
||||
@ -91,7 +91,7 @@ describe('getCommentById', () => {
|
||||
expect(state.comments.replies[111].length).toBe(1);
|
||||
});
|
||||
|
||||
test('getting a reply comment will load the parent comment and its other replies', async () => {
|
||||
test('getting a reply comment will load the parent comment and its other replies', () => {
|
||||
// Expect 3 requests. First 111, which is a reply comment, maybe linked to from messages
|
||||
// Second is for 111's parent, which is 555.
|
||||
// Third is for 555's replies, which returns 111 and 112
|
||||
@ -121,5 +121,4 @@ describe.skip('addNewComment', () => { });
|
||||
describe.skip('deleteComment', () => { });
|
||||
describe.skip('reportComment', () => { });
|
||||
describe.skip('resetComments', () => { });
|
||||
describe.skip('reportComment', () => { });
|
||||
describe.skip('getReplies', () => { });
|
||||
|
@ -17,7 +17,7 @@ describe('session selectors', () => {
|
||||
});
|
||||
|
||||
test('user data', () => {
|
||||
let state = {session: getInitialState()};
|
||||
const state = {session: getInitialState()};
|
||||
const newSession = sessions.user1.session;
|
||||
state.session = sessionReducer(state.session, setSession(newSession));
|
||||
expect(selectUserId(state)).toBe(1);
|
||||
@ -28,7 +28,7 @@ describe('session selectors', () => {
|
||||
|
||||
describe('permissions', () => {
|
||||
test('selectIsAdmin', () => {
|
||||
let state = {session: getInitialState()};
|
||||
const state = {session: getInitialState()};
|
||||
const newSession = sessions.user1Admin.session;
|
||||
state.session = sessionReducer(state.session, setSession(newSession));
|
||||
expect(selectIsAdmin(state)).toBe(true);
|
||||
@ -37,7 +37,7 @@ describe('session selectors', () => {
|
||||
});
|
||||
|
||||
test('selectIsSocial', () => {
|
||||
let state = {session: getInitialState()};
|
||||
const state = {session: getInitialState()};
|
||||
const newSession = sessions.user1Social.session;
|
||||
state.session = sessionReducer(state.session, setSession(newSession));
|
||||
expect(selectIsSocial(state)).toBe(true);
|
||||
|
@ -12,7 +12,7 @@ beforeEach(() => {
|
||||
});
|
||||
|
||||
describe('getTopLevelComments', () => {
|
||||
test('replies are only loaded for comments with a reply_count > 0', async () => {
|
||||
test('replies are only loaded for comments with a reply_count > 0', () => {
|
||||
store = configureStore(reducers, {
|
||||
...initialState,
|
||||
studio: {id: 123123}
|
||||
@ -45,7 +45,7 @@ describe('getTopLevelComments', () => {
|
||||
expect(state.comments.replies[1]).toBeUndefined();
|
||||
expect(state.comments.replies[60]).toBeUndefined();
|
||||
});
|
||||
test('admin route is used when the session shows the user is an admin', async () => {
|
||||
test('admin route is used when the session shows the user is an admin', () => {
|
||||
store = configureStore(reducers, {
|
||||
...initialState,
|
||||
studio: {id: 123123},
|
||||
@ -56,7 +56,7 @@ describe('getTopLevelComments', () => {
|
||||
}
|
||||
}
|
||||
});
|
||||
api.mockImplementationOnce((opts) => {
|
||||
api.mockImplementationOnce(opts => {
|
||||
expect(opts.uri).toBe('/admin/studios/123123/comments');
|
||||
expect(opts.authentication).toBe('a-token');
|
||||
});
|
||||
@ -65,7 +65,7 @@ describe('getTopLevelComments', () => {
|
||||
});
|
||||
|
||||
describe('getCommentById', () => {
|
||||
test('getting a top level comment will not load replies if there arent any', async () => {
|
||||
test('getting a top level comment will not load replies if there arent any', () => {
|
||||
store = configureStore(reducers, {
|
||||
...initialState,
|
||||
studio: {id: 123123}
|
||||
@ -81,7 +81,7 @@ describe('getCommentById', () => {
|
||||
expect(state.comments.replies[111]).toBeUndefined();
|
||||
});
|
||||
|
||||
test('getting a top level comment will load replies', async () => {
|
||||
test('getting a top level comment will load replies', () => {
|
||||
store = configureStore(reducers, {
|
||||
...initialState,
|
||||
studio: {id: 123123}
|
||||
@ -101,7 +101,7 @@ describe('getCommentById', () => {
|
||||
expect(state.comments.replies[111].length).toBe(1);
|
||||
});
|
||||
|
||||
test('getting a reply comment will load the parent comment and its other replies', async () => {
|
||||
test('getting a reply comment will load the parent comment and its other replies', () => {
|
||||
store = configureStore(reducers, {
|
||||
...initialState,
|
||||
studio: {id: 123123}
|
||||
@ -135,5 +135,4 @@ describe.skip('addNewComment', () => { });
|
||||
describe.skip('deleteComment', () => { });
|
||||
describe.skip('reportComment', () => { });
|
||||
describe.skip('resetComments', () => { });
|
||||
describe.skip('reportComment', () => { });
|
||||
describe.skip('getReplies', () => { });
|
||||
|
@ -64,7 +64,7 @@ describe('loadManagers', () => {
|
||||
}
|
||||
}
|
||||
});
|
||||
api.mockImplementation((opts) => {
|
||||
api.mockImplementation(opts => {
|
||||
expect(opts.uri).toBe('/admin/studios/123123/managers/');
|
||||
expect(opts.authentication).toBe('a-token');
|
||||
});
|
||||
@ -120,7 +120,7 @@ describe('loadCurators', () => {
|
||||
}
|
||||
}
|
||||
});
|
||||
api.mockImplementation((opts) => {
|
||||
api.mockImplementation(opts => {
|
||||
expect(opts.uri).toBe('/admin/studios/123123/curators/');
|
||||
expect(opts.authentication).toBe('a-token');
|
||||
});
|
||||
|
@ -30,7 +30,7 @@ import {sessions, studios} from '../../helpers/state-fixtures.json';
|
||||
|
||||
let state;
|
||||
|
||||
const setStateByRole = (role) => {
|
||||
const setStateByRole = role => {
|
||||
switch (role) {
|
||||
case 'admin':
|
||||
state.session = sessions.user1Admin;
|
||||
@ -74,7 +74,7 @@ const setStateByRole = (role) => {
|
||||
state.session = sessions.user1Muted;
|
||||
break;
|
||||
default:
|
||||
throw new Error('Unknown user role in test: ' + role);
|
||||
throw new Error(`Unknown user role in test: ${role}`);
|
||||
}
|
||||
};
|
||||
|
||||
@ -588,7 +588,7 @@ describe('studio mute errors', () => {
|
||||
state.session = thisSession;
|
||||
expect(selectShowCommentsGloballyOffError(state)).toBe(true);
|
||||
});
|
||||
test('Do not show comments off error because feature flag is on ', () => {
|
||||
test('Do not show comments off error because feature flag is on', () => {
|
||||
const thisSession = {
|
||||
status: Status.FETCHED,
|
||||
session: {
|
||||
@ -600,7 +600,7 @@ describe('studio mute errors', () => {
|
||||
state.session = thisSession;
|
||||
expect(selectShowCommentsGloballyOffError(state)).toBe(false);
|
||||
});
|
||||
test('Do not show comments off error because session not fetched ', () => {
|
||||
test('Do not show comments off error because session not fetched', () => {
|
||||
const thisSession = {
|
||||
status: Status.NOT_FETCHED,
|
||||
session: {
|
||||
|
@ -52,7 +52,7 @@ describe('loadProjects', () => {
|
||||
}
|
||||
}
|
||||
});
|
||||
api.mockImplementation((opts) => {
|
||||
api.mockImplementation(opts => {
|
||||
expect(opts.uri).toBe('/admin/studios/123123/projects/');
|
||||
expect(opts.authentication).toBe('a-token');
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user