style(test): enable ES6 and Jest eslint rules for tests

This commit is contained in:
Christopher Willis-Ford 2023-10-24 11:22:28 -07:00
parent 2356a93122
commit 9a97535168
51 changed files with 1151 additions and 911 deletions

271
package-lock.json generated
View file

@ -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",

View file

@ -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",

View file

@ -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
}
],
}
};

View file

@ -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: {}});

View file

@ -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;
}));
}
}

View file

@ -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')));
});

View file

@ -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();
});

View file

@ -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();
});

View file

@ -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();
});

View file

@ -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();
});

View file

@ -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();
});

View file

@ -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();

View file

@ -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();
});

View file

@ -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);
});
});
});

View file

@ -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\/?$/);
});

View file

@ -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);
});
});

View file

@ -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');
});
});

View file

@ -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);
});

View file

@ -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);
});

View file

@ -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);
});
});

View file

@ -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$/);
});
});

View file

@ -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;
}

View file

@ -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.');
});
});

View file

@ -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);
});
});

View file

@ -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);
});
});

View file

@ -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] = [];

View file

@ -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);
});

View file

@ -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/)" && ' +

View file

@ -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()

View file

@ -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;

View file

@ -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(

View file

@ -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 */

View file

@ -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', () => {

View file

@ -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();

View file

@ -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';

View file

@ -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"

View file

@ -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';

View file

@ -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', () => {

View file

@ -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 */

View file

@ -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');

View file

@ -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',

View file

@ -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');
});
});

View file

@ -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(() => {

View file

@ -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);
});
});

View file

@ -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');
}
});

View file

@ -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', () => { });

View file

@ -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);

View file

@ -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', () => { });

View file

@ -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');
});

View file

@ -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: {

View file

@ -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');
});