first commit
This commit is contained in:
@@ -0,0 +1,23 @@
|
||||
module.exports.assertion = function(expected) {
|
||||
this.message = `Testing if "${expected}" deprecation error has been triggered`;
|
||||
this.expected = expected;
|
||||
this.pass = deprecationMessages => deprecationMessages.includes(expected);
|
||||
this.value = result => {
|
||||
const sessionStorageEntries = JSON.parse(result.value);
|
||||
const deprecationMessages =
|
||||
sessionStorageEntries !== null
|
||||
? sessionStorageEntries.filter(message =>
|
||||
new RegExp('[Deprecation]').test(message),
|
||||
)
|
||||
: [];
|
||||
|
||||
return deprecationMessages.map(message =>
|
||||
message.replace('[Deprecation] ', ''),
|
||||
);
|
||||
};
|
||||
this.command = callback =>
|
||||
// eslint-disable-next-line prefer-arrow-callback
|
||||
this.api.execute(function() {
|
||||
return window.sessionStorage.getItem('js_deprecation_log_test.warnings');
|
||||
}, callback);
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
module.exports.assertion = function() {
|
||||
this.message = 'Ensuring no deprecation errors have been triggered';
|
||||
this.expected = '';
|
||||
this.pass = deprecationMessages => deprecationMessages.length === 0;
|
||||
this.value = result => {
|
||||
const sessionStorageEntries = JSON.parse(result.value);
|
||||
const deprecationMessages =
|
||||
sessionStorageEntries !== null
|
||||
? sessionStorageEntries.filter(message =>
|
||||
new RegExp('[Deprecation]').test(message),
|
||||
)
|
||||
: [];
|
||||
|
||||
return deprecationMessages.map(message =>
|
||||
message.replace('[Deprecation] ', ''),
|
||||
);
|
||||
};
|
||||
this.command = callback =>
|
||||
// eslint-disable-next-line prefer-arrow-callback
|
||||
this.api.execute(function() {
|
||||
return window.sessionStorage.getItem('js_deprecation_log_test.warnings');
|
||||
}, callback);
|
||||
};
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Creates role with given permissions.
|
||||
*
|
||||
* @param {object} settings
|
||||
* Settings object
|
||||
* @param {array} settings.permissions
|
||||
* The list of roles granted for the user.
|
||||
* @param {string} [settings.name=null]
|
||||
* The role name.
|
||||
* @param {function} callback
|
||||
* A callback which will be called, when creating the role is finished.
|
||||
* @return {object}
|
||||
* The drupalCreateRole command.
|
||||
*/
|
||||
exports.command = function drupalCreateRole(
|
||||
{ permissions, name = null },
|
||||
callback,
|
||||
) {
|
||||
const self = this;
|
||||
const roleName =
|
||||
name ||
|
||||
Math.random()
|
||||
.toString(36)
|
||||
.substring(2, 15);
|
||||
|
||||
let machineName;
|
||||
this.drupalLoginAsAdmin(() => {
|
||||
this.drupalRelativeURL('/admin/people/roles/add')
|
||||
.setValue('input[name="label"]', roleName)
|
||||
// Wait for the machine name to appear so that it can be used later to
|
||||
// select the permissions from the permission page.
|
||||
.expect.element('.user-role-form .machine-name-value')
|
||||
.to.be.visible.before(2000);
|
||||
|
||||
this.perform(done => {
|
||||
this.getText('.user-role-form .machine-name-value', element => {
|
||||
machineName = element.value;
|
||||
done();
|
||||
});
|
||||
})
|
||||
.submitForm('#user-role-form')
|
||||
.drupalRelativeURL('/admin/people/permissions')
|
||||
.perform((client, done) => {
|
||||
Promise.all(
|
||||
permissions.map(
|
||||
permission =>
|
||||
new Promise(resolve => {
|
||||
client.click(
|
||||
`input[name="${machineName}[${permission}]"]`,
|
||||
() => {
|
||||
resolve();
|
||||
},
|
||||
);
|
||||
}),
|
||||
),
|
||||
).then(() => {
|
||||
done();
|
||||
});
|
||||
})
|
||||
.submitForm('#user-admin-permissions');
|
||||
}).perform(() => {
|
||||
if (typeof callback === 'function') {
|
||||
callback.call(self, machineName);
|
||||
}
|
||||
});
|
||||
|
||||
return this;
|
||||
};
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Logs into Drupal as the given user.
|
||||
*
|
||||
* @param {object} settings
|
||||
* Settings object
|
||||
* @param {string} settings.name
|
||||
* The user name.
|
||||
* @param {string} settings.password
|
||||
* The user password.
|
||||
* @param {array} [settings.permissions=[]]
|
||||
* The list of permissions granted for the user.
|
||||
* @param {function} callback
|
||||
* A callback which will be called when creating the user is finished.
|
||||
* @return {object}
|
||||
* The drupalCreateUser command.
|
||||
*/
|
||||
exports.command = function drupalCreateUser(
|
||||
{ name, password, permissions = [] },
|
||||
callback,
|
||||
) {
|
||||
const self = this;
|
||||
|
||||
let role;
|
||||
this.perform((client, done) => {
|
||||
if (permissions) {
|
||||
client.drupalCreateRole({ permissions, name: null }, newRole => {
|
||||
role = newRole;
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
}).drupalLoginAsAdmin(() => {
|
||||
this.drupalRelativeURL('/admin/people/create')
|
||||
.setValue('input[name="name"]', name)
|
||||
.setValue('input[name="pass[pass1]"]', password)
|
||||
.setValue('input[name="pass[pass2]"]', password)
|
||||
.perform((client, done) => {
|
||||
if (role) {
|
||||
client.click(`input[name="roles[${role}]`, () => {
|
||||
done();
|
||||
});
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
})
|
||||
.submitForm('#user-register-form')
|
||||
.assert.containsText(
|
||||
'[data-drupal-messages]',
|
||||
'Created a new user account',
|
||||
`User "${name}" was created successfully.`,
|
||||
);
|
||||
});
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback.call(self);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
@@ -0,0 +1,64 @@
|
||||
import { execSync } from 'child_process';
|
||||
import { URL } from 'url';
|
||||
import { commandAsWebserver } from '../globals';
|
||||
|
||||
/**
|
||||
* Installs a Drupal test site.
|
||||
*
|
||||
* @param {object} [settings={}]
|
||||
* Settings object
|
||||
* @param {string} [settings.setupFile='']
|
||||
* Setup file used by TestSiteApplicationTest
|
||||
* @param {string} [settings.installProfile='']
|
||||
* The install profile to use.
|
||||
* @param {string} [settings.langcode='']
|
||||
* The language to install the site in.
|
||||
* @param {function} callback
|
||||
* A callback which will be called, when the installation is finished.
|
||||
* @return {object}
|
||||
* The 'browser' object.
|
||||
*/
|
||||
exports.command = function drupalInstall(
|
||||
{ setupFile = '', installProfile = 'nightwatch_testing', langcode = '' } = {},
|
||||
callback,
|
||||
) {
|
||||
const self = this;
|
||||
|
||||
try {
|
||||
setupFile = setupFile ? `--setup-file "${setupFile}"` : '';
|
||||
installProfile = `--install-profile "${installProfile}"`;
|
||||
const langcodeOption = langcode ? `--langcode "${langcode}"` : '';
|
||||
const dbOption =
|
||||
process.env.DRUPAL_TEST_DB_URL.length > 0
|
||||
? `--db-url ${process.env.DRUPAL_TEST_DB_URL}`
|
||||
: '';
|
||||
const install = execSync(
|
||||
commandAsWebserver(
|
||||
`php ./scripts/test-site.php install ${setupFile} ${installProfile} ${langcodeOption} --base-url ${process.env.DRUPAL_TEST_BASE_URL} ${dbOption} --json`,
|
||||
),
|
||||
);
|
||||
const installData = JSON.parse(install.toString());
|
||||
this.globals.drupalDbPrefix = installData.db_prefix;
|
||||
this.globals.drupalSitePath = installData.site_path;
|
||||
const url = new URL(process.env.DRUPAL_TEST_BASE_URL);
|
||||
this.url(process.env.DRUPAL_TEST_BASE_URL).setCookie({
|
||||
name: 'SIMPLETEST_USER_AGENT',
|
||||
// Colons need to be URL encoded to be valid.
|
||||
value: encodeURIComponent(installData.user_agent),
|
||||
path: url.pathname,
|
||||
domain: url.host,
|
||||
});
|
||||
} catch (error) {
|
||||
this.assert.fail(error);
|
||||
}
|
||||
|
||||
// Nightwatch doesn't like it when no actions are added in a command file.
|
||||
// https://github.com/nightwatchjs/nightwatch/issues/1792
|
||||
this.pause(1);
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback.call(self);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Ends the browser session and logs the console log if there were any errors.
|
||||
* See globals.js.
|
||||
*
|
||||
* @param {Object}
|
||||
* (optional) Settings object
|
||||
* @param onlyOnError
|
||||
* (optional) Only writes out the console log file if the test failed.
|
||||
* @param {function} callback
|
||||
* A callback which will be called.
|
||||
* @return {object}
|
||||
* The 'browser' object.
|
||||
*/
|
||||
exports.command = function drupalLogAndEnd({ onlyOnError = true }, callback) {
|
||||
const self = this;
|
||||
this.drupalLogConsole = true;
|
||||
this.drupalLogConsoleOnlyOnError = onlyOnError;
|
||||
|
||||
// Nightwatch doesn't like it when no actions are added in a command file.
|
||||
// https://github.com/nightwatchjs/nightwatch/issues/1792
|
||||
this.pause(1);
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback.call(self);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Logs into Drupal as the given user.
|
||||
*
|
||||
* @param {string} name
|
||||
* The user name.
|
||||
* @param {string} password
|
||||
* The user password.
|
||||
* @return {object}
|
||||
* The drupalUserIsLoggedIn command.
|
||||
*/
|
||||
exports.command = function drupalLogin({ name, password }) {
|
||||
this.drupalUserIsLoggedIn(sessionExists => {
|
||||
// Log the current user out if necessary.
|
||||
if (sessionExists) {
|
||||
this.drupalLogout();
|
||||
}
|
||||
// Log in with the given credentials.
|
||||
this.drupalRelativeURL('/user/login')
|
||||
.setValue('input[name="name"]', name)
|
||||
.setValue('input[name="pass"]', password)
|
||||
.submitForm('#user-login-form');
|
||||
// Assert that a user is logged in.
|
||||
this.drupalUserIsLoggedIn(sessionExists => {
|
||||
this.assert.equal(
|
||||
sessionExists,
|
||||
true,
|
||||
`The user "${name}" was logged in.`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
return this;
|
||||
};
|
||||
@@ -0,0 +1,41 @@
|
||||
import { execSync } from 'child_process';
|
||||
import { URL } from 'url';
|
||||
import { commandAsWebserver } from '../globals';
|
||||
|
||||
/**
|
||||
* Logs in as the admin user.
|
||||
*
|
||||
* @param {function} callback
|
||||
* A callback which will allow running commands as an administrator.
|
||||
* @return {object}
|
||||
* The drupalLoginAsAdmin command.
|
||||
*/
|
||||
exports.command = function drupalLoginAsAdmin(callback) {
|
||||
const self = this;
|
||||
this.drupalUserIsLoggedIn(sessionExists => {
|
||||
if (sessionExists) {
|
||||
this.drupalLogout();
|
||||
}
|
||||
const userLink = execSync(
|
||||
commandAsWebserver(
|
||||
`php ./scripts/test-site.php user-login 1 --site-path ${this.globals.drupalSitePath}`,
|
||||
),
|
||||
);
|
||||
|
||||
this.drupalRelativeURL(userLink.toString());
|
||||
|
||||
this.drupalUserIsLoggedIn(sessionExists => {
|
||||
if (!sessionExists) {
|
||||
throw new Error('Logging in as an admin user failed.');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback.call(self);
|
||||
}
|
||||
|
||||
this.drupalLogout({ silent: true });
|
||||
|
||||
return this;
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
import { execSync } from 'child_process';
|
||||
import { URL } from 'url';
|
||||
|
||||
/**
|
||||
* Logs out from a Drupal site.
|
||||
*
|
||||
* @param {object} [settings={}]
|
||||
* The settings object.
|
||||
* @param {boolean} [settings.silent=false]
|
||||
* If the command should be run silently.
|
||||
* @param {function} callback
|
||||
* A callback which will be called, when the logout is finished.
|
||||
* @return {object}
|
||||
* The drupalLogout command.
|
||||
*/
|
||||
exports.command = function drupalLogout({ silent = false } = {}, callback) {
|
||||
const self = this;
|
||||
|
||||
this.drupalRelativeURL('/user/logout');
|
||||
|
||||
this.drupalUserIsLoggedIn(sessionExists => {
|
||||
if (silent) {
|
||||
if (sessionExists) {
|
||||
throw new Error('Logging out failed.');
|
||||
}
|
||||
} else {
|
||||
this.assert.equal(sessionExists, false, 'The user was logged out.');
|
||||
}
|
||||
});
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback.call(self);
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Concatenate a DRUPAL_TEST_BASE_URL variable and a pathname.
|
||||
*
|
||||
* This provides a custom command, .relativeURL()
|
||||
*
|
||||
* @param {string} pathname
|
||||
* The relative path to append to DRUPAL_TEST_BASE_URL
|
||||
* @param {function} callback
|
||||
* A callback which will be called.
|
||||
* @return {object}
|
||||
* The 'browser' object.
|
||||
*/
|
||||
exports.command = function drupalRelativeURL(pathname, callback) {
|
||||
const self = this;
|
||||
this.url(`${process.env.DRUPAL_TEST_BASE_URL}${pathname}`);
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback.call(self);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
@@ -0,0 +1,46 @@
|
||||
import { execSync } from 'child_process';
|
||||
import { commandAsWebserver } from '../globals';
|
||||
|
||||
/**
|
||||
* Uninstalls a test Drupal site.
|
||||
*
|
||||
* @param {function} callback
|
||||
* A callback which will be called, when the uninstallation is finished.
|
||||
* @return {object}
|
||||
* The 'browser' object.
|
||||
*/
|
||||
exports.command = function drupalUninstal(callback) {
|
||||
const self = this;
|
||||
const prefix = this.globals.drupalDbPrefix;
|
||||
|
||||
// Check for any existing errors, because running this will cause Nightwatch to hang.
|
||||
if (!this.currentTest.results.errors && !this.currentTest.results.failed) {
|
||||
const dbOption =
|
||||
process.env.DRUPAL_TEST_DB_URL.length > 0
|
||||
? `--db-url ${process.env.DRUPAL_TEST_DB_URL}`
|
||||
: '';
|
||||
try {
|
||||
if (!prefix || !prefix.length) {
|
||||
throw new Error(
|
||||
'Missing database prefix parameter, unable to uninstall Drupal (the initial install was probably unsuccessful).',
|
||||
);
|
||||
}
|
||||
execSync(
|
||||
commandAsWebserver(
|
||||
`php ./scripts/test-site.php tear-down ${prefix} ${dbOption}`,
|
||||
),
|
||||
);
|
||||
} catch (error) {
|
||||
this.assert.fail(error);
|
||||
}
|
||||
}
|
||||
|
||||
// Nightwatch doesn't like it when no actions are added in a command file.
|
||||
// https://github.com/nightwatchjs/nightwatch/issues/1792
|
||||
this.pause(1);
|
||||
|
||||
if (typeof callback === 'function') {
|
||||
callback.call(self);
|
||||
}
|
||||
return this;
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Checks if a user is logged in.
|
||||
*
|
||||
* @param {function} callback
|
||||
* A callback which will be called, when the login status has been checked.
|
||||
* @return {object}
|
||||
* The drupalUserIsLoggedIn command.
|
||||
*/
|
||||
exports.command = function drupalUserIsLoggedIn(callback) {
|
||||
if (typeof callback === 'function') {
|
||||
this.getCookies(cookies => {
|
||||
const sessionExists = cookies.value.some(cookie =>
|
||||
cookie.name.match(/^S?SESS/),
|
||||
);
|
||||
|
||||
callback.call(this, sessionExists);
|
||||
});
|
||||
}
|
||||
|
||||
return this;
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
module.exports = {
|
||||
props: {
|
||||
text: 'Test page text',
|
||||
timeout: 1000,
|
||||
},
|
||||
elements: {
|
||||
body: {
|
||||
selector: 'body',
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
module.exports = {
|
||||
'@tags': ['core'],
|
||||
before(browser) {
|
||||
browser.drupalInstall({
|
||||
setupFile: 'core/tests/Drupal/TestSite/TestSiteInstallTestScript.php',
|
||||
});
|
||||
},
|
||||
after(browser) {
|
||||
browser.drupalUninstall();
|
||||
},
|
||||
'Test page': browser => {
|
||||
browser
|
||||
.drupalRelativeURL('/test-page')
|
||||
.waitForElementVisible('body', 1000)
|
||||
.assert.containsText('body', 'Test page text')
|
||||
.drupalLogAndEnd({ onlyOnError: false });
|
||||
},
|
||||
'Page objects test page': browser => {
|
||||
const testPage = browser.page.TestPage();
|
||||
|
||||
testPage
|
||||
.drupalRelativeURL('/test-page')
|
||||
.waitForElementVisible('@body', testPage.props.timeout)
|
||||
.assert.containsText('@body', testPage.props.text)
|
||||
.assert.noDeprecationErrors()
|
||||
.drupalLogAndEnd({ onlyOnError: false });
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,19 @@
|
||||
module.exports = {
|
||||
'@tags': ['core'],
|
||||
before(browser) {
|
||||
browser.drupalInstall({
|
||||
setupFile: 'core/tests/Drupal/TestSite/TestSiteInstallTestScript.php',
|
||||
installProfile: 'demo_umami',
|
||||
});
|
||||
},
|
||||
after(browser) {
|
||||
browser.drupalUninstall();
|
||||
},
|
||||
'Test umami profile': browser => {
|
||||
browser
|
||||
.drupalRelativeURL('/test-page')
|
||||
.waitForElementVisible('body', 1000)
|
||||
.assert.elementPresent('#block-umami-branding')
|
||||
.drupalLogAndEnd({ onlyOnError: false });
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,254 @@
|
||||
const deprecatedMessageSuffix = `is deprecated in Drupal 9.0.0 and will be removed in Drupal 10.0.0. Use the core/js-cookie library instead. See https://www.drupal.org/node/3104677`;
|
||||
// Nightwatch suggests non-ES6 functions when using the execute method.
|
||||
// eslint-disable-next-line func-names, prefer-arrow-callback
|
||||
const getJqueryCookie = function(cookieName) {
|
||||
return undefined !== cookieName ? jQuery.cookie(cookieName) : jQuery.cookie();
|
||||
};
|
||||
// eslint-disable-next-line func-names, prefer-arrow-callback
|
||||
const setJqueryCookieWithOptions = function(
|
||||
cookieName,
|
||||
cookieValue,
|
||||
options = {},
|
||||
) {
|
||||
return jQuery.cookie(cookieName, cookieValue, options);
|
||||
};
|
||||
module.exports = {
|
||||
'@tags': ['core'],
|
||||
before(browser) {
|
||||
browser.drupalInstall().drupalLoginAsAdmin(() => {
|
||||
browser
|
||||
.drupalRelativeURL('/admin/modules')
|
||||
.setValue('input[type="search"]', 'JS Cookie Test')
|
||||
.waitForElementVisible(
|
||||
'input[name="modules[js_cookie_test][enable]"]',
|
||||
1000,
|
||||
)
|
||||
.click('input[name="modules[js_cookie_test][enable]"]')
|
||||
.click('input[type="submit"]'); // Submit module form.
|
||||
});
|
||||
},
|
||||
after(browser) {
|
||||
browser.drupalUninstall();
|
||||
},
|
||||
'Test jquery.cookie Shim Simple Value and jquery.removeCookie': browser => {
|
||||
browser
|
||||
.drupalRelativeURL('/js_cookie_with_shim_test')
|
||||
.waitForElementVisible('.js_cookie_test_add_button', 1000)
|
||||
.click('.js_cookie_test_add_button')
|
||||
// prettier-ignore
|
||||
.execute(getJqueryCookie, ['js_cookie_test'], result => {
|
||||
browser.assert.equal(
|
||||
result.value,
|
||||
'red panda',
|
||||
'$.cookie returns cookie value',
|
||||
);
|
||||
})
|
||||
.waitForElementVisible('.js_cookie_test_remove_button', 1000)
|
||||
.click('.js_cookie_test_remove_button')
|
||||
.execute(getJqueryCookie, ['js_cookie_test_remove'], result => {
|
||||
browser.assert.equal(result.value, null, 'cookie removed');
|
||||
})
|
||||
.drupalLogAndEnd({ onlyOnError: false });
|
||||
},
|
||||
'Test jquery.cookie Shim Empty Value': browser => {
|
||||
browser
|
||||
.setCookie({
|
||||
name: 'js_cookie_test_empty',
|
||||
value: '',
|
||||
})
|
||||
// prettier-ignore
|
||||
.execute(getJqueryCookie, ['js_cookie_test_empty'], result => {
|
||||
browser.assert.equal(
|
||||
result.value,
|
||||
'',
|
||||
'$.cookie returns empty cookie value',
|
||||
);
|
||||
})
|
||||
.getCookie('js_cookie_test_empty', result => {
|
||||
browser.assert.equal(result.value, '', 'Cookie value is empty.');
|
||||
})
|
||||
.drupalLogAndEnd({ onlyOnError: false });
|
||||
},
|
||||
'Test jquery.cookie Shim Undefined': browser => {
|
||||
browser
|
||||
.deleteCookie('js_cookie_test_undefined', () => {
|
||||
browser.execute(
|
||||
getJqueryCookie,
|
||||
['js_cookie_test_undefined'],
|
||||
result => {
|
||||
browser.assert.equal(
|
||||
result.value,
|
||||
undefined,
|
||||
'$.cookie returns undefined cookie value',
|
||||
);
|
||||
},
|
||||
);
|
||||
})
|
||||
.drupalLogAndEnd({ onlyOnError: false });
|
||||
},
|
||||
'Test jquery.cookie Shim Decode': browser => {
|
||||
browser
|
||||
.setCookie({
|
||||
name: encodeURIComponent(' js_cookie_test_encoded'),
|
||||
value: encodeURIComponent(' red panda'),
|
||||
})
|
||||
.execute(getJqueryCookie, [' js_cookie_test_encoded'], result => {
|
||||
browser.assert.equal(
|
||||
result.value,
|
||||
' red panda',
|
||||
'$.cookie returns decoded cookie value',
|
||||
);
|
||||
})
|
||||
.setCookie({
|
||||
name: 'js_cookie_test_encoded_plus_to_space',
|
||||
value: 'red+panda',
|
||||
})
|
||||
.execute(
|
||||
getJqueryCookie,
|
||||
['js_cookie_test_encoded_plus_to_space'],
|
||||
result => {
|
||||
browser.assert.equal(
|
||||
result.value,
|
||||
'red panda',
|
||||
'$.cookie returns decoded plus to space in cookie value',
|
||||
);
|
||||
},
|
||||
)
|
||||
.drupalLogAndEnd({ onlyOnError: false });
|
||||
},
|
||||
'Test jquery.cookie Shim With raw': browser => {
|
||||
browser
|
||||
.drupalRelativeURL('/js_cookie_with_shim_test')
|
||||
.waitForElementVisible('.js_cookie_test_add_raw_button', 1000)
|
||||
.click('.js_cookie_test_add_raw_button')
|
||||
.execute(getJqueryCookie, ['js_cookie_test_raw'], result => {
|
||||
browser.assert.equal(
|
||||
result.value,
|
||||
'red%20panda',
|
||||
'$.cookie returns raw cookie value',
|
||||
);
|
||||
})
|
||||
.drupalLogAndEnd({ onlyOnError: false });
|
||||
},
|
||||
'Test jquery.cookie Shim With JSON': browser => {
|
||||
browser
|
||||
.drupalRelativeURL('/js_cookie_with_shim_test')
|
||||
.waitForElementVisible('.js_cookie_test_add_json_button', 1000)
|
||||
.click('.js_cookie_test_add_json_button')
|
||||
.execute(getJqueryCookie, ['js_cookie_test_json'], result => {
|
||||
browser.assert.deepEqual(
|
||||
result.value,
|
||||
{ panda: 'red' },
|
||||
'Stringified JSON is returned as JSON.',
|
||||
);
|
||||
})
|
||||
.getCookie('js_cookie_test_json', result => {
|
||||
browser.assert.equal(
|
||||
result.value,
|
||||
'%7B%22panda%22%3A%22red%22%7D',
|
||||
'Cookie value is encoded backwards-compatible with jquery.cookie.',
|
||||
);
|
||||
})
|
||||
.execute(getJqueryCookie, ['js_cookie_test_json_simple'], result => {
|
||||
browser.assert.equal(
|
||||
result.value,
|
||||
'red panda',
|
||||
'$.cookie returns simple cookie value with JSON enabled',
|
||||
);
|
||||
})
|
||||
.waitForElementVisible('.js_cookie_test_add_json_string_button', 1000)
|
||||
.click('.js_cookie_test_add_json_string_button')
|
||||
.execute(getJqueryCookie, ['js_cookie_test_json_string'], result => {
|
||||
browser.assert.deepEqual(
|
||||
result.value,
|
||||
'[object Object]',
|
||||
'JSON used without json option is return as a string.',
|
||||
);
|
||||
})
|
||||
.getCookie('js_cookie_test_json_string', result => {
|
||||
browser.assert.equal(
|
||||
result.value,
|
||||
'%5Bobject%20Object%5D',
|
||||
'Cookie value is encoded backwards-compatible with jquery.cookie.',
|
||||
);
|
||||
})
|
||||
.drupalLogAndEnd({ onlyOnError: false });
|
||||
},
|
||||
'Test jquery.cookie Shim invalid URL encoding': browser => {
|
||||
browser
|
||||
.setCookie({
|
||||
name: 'js_cookie_test_bad',
|
||||
value: 'red panda%',
|
||||
})
|
||||
.execute(getJqueryCookie, ['js_cookie_test_bad'], result => {
|
||||
browser.assert.equal(
|
||||
result.value,
|
||||
undefined,
|
||||
'$.cookie won`t throw exception, returns undefined',
|
||||
);
|
||||
})
|
||||
.drupalLogAndEnd({ onlyOnError: false });
|
||||
},
|
||||
'Test jquery.cookie Shim Read all when there are cookies or return empty object': browser => {
|
||||
browser
|
||||
.getCookie('SIMPLETEST_USER_AGENT', simpletestCookie => {
|
||||
const simpletestCookieValue = simpletestCookie.value;
|
||||
browser
|
||||
.drupalRelativeURL('/js_cookie_with_shim_test')
|
||||
.deleteCookies(() => {
|
||||
browser
|
||||
.execute(getJqueryCookie, [], result => {
|
||||
browser.assert.deepEqual(
|
||||
result.value,
|
||||
{},
|
||||
'$.cookie() returns empty object',
|
||||
);
|
||||
})
|
||||
.setCookie({
|
||||
name: 'js_cookie_test_first',
|
||||
value: 'red panda',
|
||||
})
|
||||
.setCookie({
|
||||
name: 'js_cookie_test_second',
|
||||
value: 'second red panda',
|
||||
})
|
||||
.setCookie({
|
||||
name: 'js_cookie_test_third',
|
||||
value: 'third red panda id bad%',
|
||||
})
|
||||
.execute(getJqueryCookie, [], result => {
|
||||
browser.assert.deepEqual(
|
||||
result.value,
|
||||
{
|
||||
js_cookie_test_first: 'red panda',
|
||||
js_cookie_test_second: 'second red panda',
|
||||
},
|
||||
'$.cookie() returns object containing all cookies',
|
||||
);
|
||||
})
|
||||
.setCookie({
|
||||
name: 'SIMPLETEST_USER_AGENT',
|
||||
value: simpletestCookieValue,
|
||||
});
|
||||
});
|
||||
})
|
||||
.drupalLogAndEnd({ onlyOnError: false });
|
||||
},
|
||||
'Test jquery.cookie Shim expires option as Date instance': browser => {
|
||||
const sevenDaysFromNow = new Date();
|
||||
sevenDaysFromNow.setDate(sevenDaysFromNow.getDate() + 7);
|
||||
browser
|
||||
.execute(
|
||||
setJqueryCookieWithOptions,
|
||||
['c', 'v', { expires: sevenDaysFromNow }],
|
||||
result => {
|
||||
browser.assert.equal(
|
||||
result.value,
|
||||
`c=v; expires=${sevenDaysFromNow.toUTCString()}`,
|
||||
'should write the cookie string with expires',
|
||||
);
|
||||
},
|
||||
)
|
||||
.drupalLogAndEnd({ onlyOnError: false });
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,32 @@
|
||||
module.exports = {
|
||||
'@tags': ['core'],
|
||||
before(browser) {
|
||||
browser.drupalInstall().drupalLoginAsAdmin(() => {
|
||||
browser
|
||||
.drupalRelativeURL('/admin/modules')
|
||||
.setValue('input[type="search"]', 'JS Deprecation test')
|
||||
.waitForElementVisible(
|
||||
'input[name="modules[js_deprecation_test][enable]"]',
|
||||
1000,
|
||||
)
|
||||
.click('input[name="modules[js_deprecation_test][enable]"]')
|
||||
.click('input[type="submit"]'); // Submit module form.
|
||||
});
|
||||
},
|
||||
after(browser) {
|
||||
browser.drupalUninstall();
|
||||
},
|
||||
'Test JavaScript deprecations': browser => {
|
||||
browser
|
||||
.drupalRelativeURL('/js_deprecation_test')
|
||||
.waitForElementVisible('body', 1000)
|
||||
.assert.containsText('h1', 'JsDeprecationTest')
|
||||
.assert.deprecationErrorExists(
|
||||
'This function is deprecated for testing purposes.',
|
||||
)
|
||||
.assert.deprecationErrorExists(
|
||||
'This property is deprecated for testing purposes.',
|
||||
)
|
||||
.drupalLogAndEnd({ onlyOnError: false });
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
module.exports = {
|
||||
'@tags': ['core'],
|
||||
before(browser) {
|
||||
browser.drupalInstall({
|
||||
setupFile: 'core/tests/Drupal/TestSite/TestSiteInstallTestScript.php',
|
||||
langcode: 'fr',
|
||||
});
|
||||
},
|
||||
after(browser) {
|
||||
browser.drupalUninstall();
|
||||
},
|
||||
'Test page with langcode': browser => {
|
||||
browser
|
||||
.drupalRelativeURL('/test-page')
|
||||
.assert.attributeEquals('html', 'lang', 'fr')
|
||||
.drupalLogAndEnd({ onlyOnError: false });
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
module.exports = {
|
||||
'@tags': ['core'],
|
||||
|
||||
before(browser) {
|
||||
browser.drupalInstall();
|
||||
},
|
||||
after(browser) {
|
||||
browser.drupalUninstall();
|
||||
},
|
||||
|
||||
'Test login': browser => {
|
||||
browser
|
||||
.drupalCreateUser({
|
||||
name: 'user',
|
||||
password: '123',
|
||||
permissions: ['access site reports'],
|
||||
})
|
||||
.drupalLogin({ name: 'user', password: '123' })
|
||||
.drupalRelativeURL('/admin/reports')
|
||||
.waitForElementVisible('body', 1000)
|
||||
.assert.containsText('h1', 'Reports')
|
||||
.assert.noDeprecationErrors();
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,24 @@
|
||||
module.exports = {
|
||||
'@tags': ['core'],
|
||||
before(browser) {
|
||||
browser.drupalInstall().drupalLoginAsAdmin(() => {
|
||||
browser
|
||||
.drupalRelativeURL('/admin/modules')
|
||||
.setValue('input[type="search"]', 'FormAPI')
|
||||
.waitForElementVisible('input[name="modules[form_test][enable]"]', 1000)
|
||||
.click('input[name="modules[form_test][enable]"]')
|
||||
.click('input[type="submit"]') // Submit module form.
|
||||
.click('input[type="submit"]'); // Confirm installation of dependencies.
|
||||
});
|
||||
},
|
||||
after(browser) {
|
||||
browser.drupalUninstall();
|
||||
},
|
||||
'Test form with state API': browser => {
|
||||
browser
|
||||
.drupalRelativeURL('/form-test/javascript-states-form')
|
||||
.waitForElementVisible('body', 1000)
|
||||
.waitForElementNotVisible('input[name="textfield"]', 1000)
|
||||
.assert.noDeprecationErrors();
|
||||
},
|
||||
};
|
||||
@@ -0,0 +1,67 @@
|
||||
import { spawn } from 'child_process';
|
||||
import path from 'path';
|
||||
import fs from 'fs';
|
||||
import mkdirp from 'mkdirp';
|
||||
import chromedriver from 'chromedriver';
|
||||
import nightwatchSettings from './nightwatch.conf';
|
||||
|
||||
export const commandAsWebserver = command => {
|
||||
if (process.env.DRUPAL_TEST_WEBSERVER_USER) {
|
||||
return `sudo -u ${process.env.DRUPAL_TEST_WEBSERVER_USER} ${command}`;
|
||||
}
|
||||
return command;
|
||||
};
|
||||
|
||||
export const drupalDbPrefix = null;
|
||||
export const drupalSitePath = null;
|
||||
|
||||
module.exports = {
|
||||
before: done => {
|
||||
if (JSON.parse(process.env.DRUPAL_TEST_CHROMEDRIVER_AUTOSTART)) {
|
||||
chromedriver.start();
|
||||
}
|
||||
done();
|
||||
},
|
||||
after: done => {
|
||||
if (JSON.parse(process.env.DRUPAL_TEST_CHROMEDRIVER_AUTOSTART)) {
|
||||
chromedriver.stop();
|
||||
}
|
||||
done();
|
||||
},
|
||||
afterEach: (browser, done) => {
|
||||
// Writes the console log - used by the "logAndEnd" command.
|
||||
if (
|
||||
browser.drupalLogConsole &&
|
||||
(!browser.drupalLogConsoleOnlyOnError ||
|
||||
browser.currentTest.results.errors > 0 ||
|
||||
browser.currentTest.results.failed > 0)
|
||||
) {
|
||||
const resultPath = path.join(
|
||||
__dirname,
|
||||
`../../../${nightwatchSettings.output_folder}/consoleLogs/${browser.currentTest.module}`,
|
||||
);
|
||||
const status =
|
||||
browser.currentTest.results.errors > 0 ||
|
||||
browser.currentTest.results.failed > 0
|
||||
? 'FAILED'
|
||||
: 'PASSED';
|
||||
mkdirp.sync(resultPath);
|
||||
const now = new Date().toString().replace(/[\s]+/g, '-');
|
||||
const testName = (
|
||||
browser.currentTest.name || browser.currentTest.module
|
||||
).replace(/[\s/]+/g, '-');
|
||||
browser
|
||||
.getLog('browser', logEntries => {
|
||||
const browserLog = JSON.stringify(logEntries, null, ' ');
|
||||
fs.writeFileSync(
|
||||
`${resultPath}/${testName}_${status}_${now}_console.json`,
|
||||
browserLog,
|
||||
);
|
||||
})
|
||||
.end(done);
|
||||
} else {
|
||||
browser.end(done);
|
||||
}
|
||||
},
|
||||
commandAsWebserver,
|
||||
};
|
||||
@@ -0,0 +1,105 @@
|
||||
import path from 'path';
|
||||
import glob from 'glob';
|
||||
|
||||
// Find directories which have Nightwatch tests in them.
|
||||
const regex = /(.*\/?tests\/?.*\/Nightwatch)\/.*/g;
|
||||
const collectedFolders = {
|
||||
Tests: [],
|
||||
Commands: [],
|
||||
Assertions: [],
|
||||
Pages: [],
|
||||
};
|
||||
const searchDirectory = process.env.DRUPAL_NIGHTWATCH_SEARCH_DIRECTORY || '';
|
||||
const defaultIgnore = ['vendor/**'];
|
||||
|
||||
glob
|
||||
.sync('**/tests/**/Nightwatch/**/*.js', {
|
||||
cwd: path.resolve(process.cwd(), `../${searchDirectory}`),
|
||||
ignore: process.env.DRUPAL_NIGHTWATCH_IGNORE_DIRECTORIES
|
||||
? process.env.DRUPAL_NIGHTWATCH_IGNORE_DIRECTORIES.split(',').concat(
|
||||
defaultIgnore,
|
||||
)
|
||||
: defaultIgnore,
|
||||
})
|
||||
.forEach(file => {
|
||||
let m = regex.exec(file);
|
||||
while (m !== null) {
|
||||
// This is necessary to avoid infinite loops with zero-width matches.
|
||||
if (m.index === regex.lastIndex) {
|
||||
regex.lastIndex += 1;
|
||||
}
|
||||
|
||||
const key = `../${m[1]}`;
|
||||
Object.keys(collectedFolders).forEach(folder => {
|
||||
if (file.includes(`Nightwatch/${folder}`)) {
|
||||
collectedFolders[folder].push(`${searchDirectory}${key}/${folder}`);
|
||||
}
|
||||
});
|
||||
m = regex.exec(file);
|
||||
}
|
||||
});
|
||||
|
||||
// Remove duplicate folders.
|
||||
Object.keys(collectedFolders).forEach(folder => {
|
||||
collectedFolders[folder] = Array.from(new Set(collectedFolders[folder]));
|
||||
});
|
||||
|
||||
module.exports = {
|
||||
src_folders: collectedFolders.Tests,
|
||||
output_folder: process.env.DRUPAL_NIGHTWATCH_OUTPUT,
|
||||
custom_commands_path: collectedFolders.Commands,
|
||||
custom_assertions_path: collectedFolders.Assertions,
|
||||
page_objects_path: collectedFolders.Pages,
|
||||
globals_path: 'globals.js',
|
||||
selenium: {
|
||||
start_process: false,
|
||||
},
|
||||
test_settings: {
|
||||
default: {
|
||||
selenium_port: process.env.DRUPAL_TEST_WEBDRIVER_PORT,
|
||||
selenium_host: process.env.DRUPAL_TEST_WEBDRIVER_HOSTNAME,
|
||||
default_path_prefix: process.env.DRUPAL_TEST_WEBDRIVER_PATH_PREFIX || '',
|
||||
desiredCapabilities: {
|
||||
browserName: 'chrome',
|
||||
acceptSslCerts: true,
|
||||
chromeOptions: {
|
||||
w3c: false,
|
||||
args: process.env.DRUPAL_TEST_WEBDRIVER_CHROME_ARGS
|
||||
? process.env.DRUPAL_TEST_WEBDRIVER_CHROME_ARGS.split(' ')
|
||||
: [],
|
||||
},
|
||||
},
|
||||
screenshots: {
|
||||
enabled: true,
|
||||
on_failure: true,
|
||||
on_error: true,
|
||||
path: `${process.env.DRUPAL_NIGHTWATCH_OUTPUT}/screenshots`,
|
||||
},
|
||||
end_session_on_fail: false,
|
||||
},
|
||||
local: {
|
||||
webdriver: {
|
||||
start_process: process.env.DRUPAL_TEST_CHROMEDRIVER_AUTOSTART,
|
||||
port: process.env.DRUPAL_TEST_WEBDRIVER_PORT,
|
||||
server_path: 'node_modules/.bin/chromedriver',
|
||||
},
|
||||
desiredCapabilities: {
|
||||
browserName: 'chrome',
|
||||
acceptSslCerts: true,
|
||||
chromeOptions: {
|
||||
w3c: false,
|
||||
args: process.env.DRUPAL_TEST_WEBDRIVER_CHROME_ARGS
|
||||
? process.env.DRUPAL_TEST_WEBDRIVER_CHROME_ARGS.split(' ')
|
||||
: [],
|
||||
},
|
||||
},
|
||||
screenshots: {
|
||||
enabled: true,
|
||||
on_failure: true,
|
||||
on_error: true,
|
||||
path: `${process.env.DRUPAL_NIGHTWATCH_OUTPUT}/screenshots`,
|
||||
},
|
||||
end_session_on_fail: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user