UNPKG

nightwatch

Version:

Easy to use Node.js based End-to-End testing solution for browser based apps and websites, using the W3C WebDriver API.

248 lines (199 loc) 6 kB
const Utils = require('../../utils'); const Common = require('./common.js'); /* describe('test suite', function() { this.timeout(1000); }); */ class DescribeInstance { constructor({describeTitle, instance}) { this['[instance]'] = instance; this['[attributes]'] = {}; this.define('@name', describeTitle); } ///////////////////////////////////////////////// // Attributes ///////////////////////////////////////////////// get name() { return this['[attributes]']['@name']; } set tags(value) { this.define('@tags', value); } get tags() { return this['[attributes]']['@tags']; } set unitTest(value) { this.define('@unitTest', value); } get unitTest() { return this['[attributes]']['@unitTest']; } set endSessionOnFail(value) { this.define('@endSessionOnFail', value); } get endSessionOnFail() { return this['[attributes]']['@endSessionOnFail']; } set skipTestcasesOnFail(value) { this.define('@skipTestcasesOnFail', value); } get skipTestcasesOnFail() { return this['[attributes]']['@skipTestcasesOnFail']; } set disabled(value) { this.define('@disabled', value); } get disabled() { return this['[attributes]']['@disabled']; } set desiredCapabilities(value) { this.define('@desiredCapabilities', value); } get desiredCapabilities() { return this['[attributes]']['@desiredCapabilities']; } ///////////////////////////////////////////////// // Getters ///////////////////////////////////////////////// get page() { if (!this.client) { return null; } return this.client.page; } get globals() { return this.settings.globals; } get settings() { return this['[instance]'].settings; } timeout(value) { this.globals.waitForConditionTimeout = value; this.globals.retryAssertionTimeout = value; this.globals.unitTestsTimeout = value; } retryInterval(value) { this.globals.waitForConditionPollInterval = value; } retries(n) { this['[instance]'].setTestcaseRetries(n); } suiteRetries(n) { this['[instance]'].setSuiteRetries(n); } define(name, value) { this['[attributes]'][name] = value; const isAttributeValid = Object.keys(Common.DEFAULT_ATTRIBUTES).includes(name) || Object.keys(Common.DEFAULT_ATTRIBUTES).includes(`@${name}`); if (isAttributeValid) { if (!name.startsWith('@')) { name = `@${name}`; } return this['[instance]'].setAttribute(name, value); } console.warn(`Attribute "${name}" is not a valid attribute. Valid attributes are: ${Object.keys(Common.DEFAULT_ATTRIBUTES).join(', ')}.`); } } class Describe extends Common { constructor(instance) { super(instance); this.describeFn = null; this.describeInstance = null; this.describeTitle = null; this.instance.on('pre-require', (context) => this.createInterface(context)); } createInstance(runOnly) { if (!Utils.isFunction(this.describeFn)) { throw new Error(`The describe/context must be a function. ${typeof this.describeFn} given.`); } const {describeTitle, instance, describeFn} = this; this.describeInstance = new DescribeInstance({ describeTitle, instance }); const {describeInstance} = this; describeFn.call(describeInstance); this.instance.setDescribeContext({describeTitle, describeInstance, runOnly}); } /** * Adds before, after, beforeEach, afterEach hooks to test suite * * @param context */ addHooks(context) { const hooksContext = Common.TestHooks.reduce((prev, hookName) => { prev[hookName] = hookFn => { this.instance.addTestHook(hookName, hookFn, this.describeInstance); }; return prev; }, {}); Object.assign(context, hooksContext); } addRun(context) { context.run = function() { // TODO: implement } } createTestsuite({title, describeFn, runOnly = false}) { this.describeFn = describeFn; this.describeTitle = title; if (this.describeFn) { this.createInstance(); } } addDescribe(context) { context.xmodule = {}; context.describe = context.context = (title, describeFn) => { this.createTestsuite({ title, describeFn }); }; context.xdescribe = context.xcontext = context.describe.skip = (title, describeFn) => { this.instance.once('module-loaded', () => { // in case tests have been declared using other interfaces (e.g. exports) if (this.instance.tests.length === 0) { this.instance.setAttribute('@disabled', true); } }); }; context.describe.only = (title, describeFn) => { this.createTestsuite({ title, describeFn, runOnly: true }); }; } addTest(context) { context.it = context.specify = context.test = (testName, testFn) => { this.instance.addTestCase({testName, testFn, describeInstance: this.describeInstance}); }; context.xit = context.xspecify = context.xtest = context.it.skip = context.test.skip = (testName) => { this.instance.addTestCase({testName, testFn: function() {}, describeInstance: this.describeInstance}); }; context.it.only = context.specify.only = context.test.only = (testName, testFn) => { this.instance.addTestCase({testName, testFn, describeInstance: this.describeInstance, runOnly: true}); }; } createInterface(context) { // for suiteRetries to work with describe interface we need to re-require the file and clear the require cache if (require.cache && require.cache[this.instance.modulePath] && this.instance.shouldReloadModuleCache()) { delete require.cache[this.instance.modulePath]; } this.addHooks(context); this.addRun(context); this.addDescribe(context); this.addTest(context); } } module.exports = Describe;