From cc749efd0656191e1b68efeac5d49292769cdef8 Mon Sep 17 00:00:00 2001 From: simonihmig Date: Thu, 22 Jul 2021 19:29:15 +0200 Subject: [PATCH] Remove jQuery usage from ember-testing As advised by feedback from core team, this removes all jQuery related testing helpers from ember-testing: * `find` * `findWithAssert` * `triggerEvent` * `keyEvent` * `click` * `fillIn` All remaining helpers remain untouched for future official deprecation. --- packages/ember-testing/index.js | 1 - packages/ember-testing/lib/events.js | 135 -- packages/ember-testing/lib/helpers.js | 12 - .../lib/helpers/-is-form-control.js | 16 - packages/ember-testing/lib/helpers/click.js | 36 - packages/ember-testing/lib/helpers/fill_in.js | 46 - packages/ember-testing/lib/helpers/find.js | 41 - .../lib/helpers/find_with_assert.js | 34 - .../ember-testing/lib/helpers/key_event.js | 36 - .../lib/helpers/trigger_event.js | 62 - .../ember-testing/lib/setup_for_testing.js | 16 - packages/ember-testing/lib/support.js | 62 - .../ember-testing/tests/acceptance_test.js | 480 ------- packages/ember-testing/tests/helpers_test.js | 1278 ----------------- .../ember-testing/tests/integration_test.js | 106 -- tests/docs/expected.js | 5 - yarn.lock | 10 +- 17 files changed, 5 insertions(+), 2371 deletions(-) delete mode 100644 packages/ember-testing/lib/events.js delete mode 100644 packages/ember-testing/lib/helpers/-is-form-control.js delete mode 100644 packages/ember-testing/lib/helpers/click.js delete mode 100644 packages/ember-testing/lib/helpers/fill_in.js delete mode 100644 packages/ember-testing/lib/helpers/find.js delete mode 100644 packages/ember-testing/lib/helpers/find_with_assert.js delete mode 100644 packages/ember-testing/lib/helpers/key_event.js delete mode 100644 packages/ember-testing/lib/helpers/trigger_event.js delete mode 100644 packages/ember-testing/lib/support.js delete mode 100644 packages/ember-testing/tests/acceptance_test.js delete mode 100644 packages/ember-testing/tests/helpers_test.js delete mode 100644 packages/ember-testing/tests/integration_test.js diff --git a/packages/ember-testing/index.js b/packages/ember-testing/index.js index 3f2b81f97e6..411e756bf72 100644 --- a/packages/ember-testing/index.js +++ b/packages/ember-testing/index.js @@ -3,7 +3,6 @@ export { default as Adapter } from './lib/adapters/adapter'; export { default as setupForTesting } from './lib/setup_for_testing'; export { default as QUnitAdapter } from './lib/adapters/qunit'; -import './lib/support'; // to handle various edge cases import './lib/ext/application'; import './lib/ext/rsvp'; // setup RSVP + run loop integration import './lib/helpers'; // adds helpers to helpers object in Test diff --git a/packages/ember-testing/lib/events.js b/packages/ember-testing/lib/events.js deleted file mode 100644 index 48cd654e1c1..00000000000 --- a/packages/ember-testing/lib/events.js +++ /dev/null @@ -1,135 +0,0 @@ -import { run } from '@ember/runloop'; -import isFormControl from './helpers/-is-form-control'; - -const DEFAULT_EVENT_OPTIONS = { canBubble: true, cancelable: true }; -const KEYBOARD_EVENT_TYPES = ['keydown', 'keypress', 'keyup']; -const MOUSE_EVENT_TYPES = [ - 'click', - 'mousedown', - 'mouseup', - 'dblclick', - 'mouseenter', - 'mouseleave', - 'mousemove', - 'mouseout', - 'mouseover', -]; - -export function focus(el) { - if (!el) { - return; - } - if (el.isContentEditable || isFormControl(el)) { - let type = el.getAttribute('type'); - if (type !== 'checkbox' && type !== 'radio' && type !== 'hidden') { - run(null, function () { - let browserIsNotFocused = document.hasFocus && !document.hasFocus(); - - // makes `document.activeElement` be `element`. If the browser is focused, it also fires a focus event - el.focus(); - - // Firefox does not trigger the `focusin` event if the window - // does not have focus. If the document does not have focus then - // fire `focusin` event as well. - if (browserIsNotFocused) { - // if the browser is not focused the previous `el.focus()` didn't fire an event, so we simulate it - fireEvent(el, 'focus', { - bubbles: false, - }); - - fireEvent(el, 'focusin'); - } - }); - } - } -} - -export function fireEvent(element, type, options = {}) { - if (!element) { - return; - } - let event; - if (KEYBOARD_EVENT_TYPES.indexOf(type) > -1) { - event = buildKeyboardEvent(type, options); - } else if (MOUSE_EVENT_TYPES.indexOf(type) > -1) { - let rect = element.getBoundingClientRect(); - let x = rect.left + 1; - let y = rect.top + 1; - let simulatedCoordinates = { - screenX: x + 5, - screenY: y + 95, - clientX: x, - clientY: y, - }; - event = buildMouseEvent(type, Object.assign(simulatedCoordinates, options)); - } else { - event = buildBasicEvent(type, options); - } - element.dispatchEvent(event); -} - -function buildBasicEvent(type, options = {}) { - let event = document.createEvent('Events'); - - // Event.bubbles is read only - let bubbles = options.bubbles !== undefined ? options.bubbles : true; - let cancelable = options.cancelable !== undefined ? options.cancelable : true; - - delete options.bubbles; - delete options.cancelable; - - event.initEvent(type, bubbles, cancelable); - Object.assign(event, options); - return event; -} - -function buildMouseEvent(type, options = {}) { - let event; - try { - event = document.createEvent('MouseEvents'); - let eventOpts = Object.assign({}, DEFAULT_EVENT_OPTIONS, options); - event.initMouseEvent( - type, - eventOpts.canBubble, - eventOpts.cancelable, - window, - eventOpts.detail, - eventOpts.screenX, - eventOpts.screenY, - eventOpts.clientX, - eventOpts.clientY, - eventOpts.ctrlKey, - eventOpts.altKey, - eventOpts.shiftKey, - eventOpts.metaKey, - eventOpts.button, - eventOpts.relatedTarget - ); - } catch (e) { - event = buildBasicEvent(type, options); - } - return event; -} - -function buildKeyboardEvent(type, options = {}) { - let event; - try { - event = document.createEvent('KeyEvents'); - let eventOpts = Object.assign({}, DEFAULT_EVENT_OPTIONS, options); - event.initKeyEvent( - type, - eventOpts.canBubble, - eventOpts.cancelable, - window, - eventOpts.ctrlKey, - eventOpts.altKey, - eventOpts.shiftKey, - eventOpts.metaKey, - eventOpts.keyCode, - eventOpts.charCode - ); - } catch (e) { - event = buildBasicEvent(type, options); - } - return event; -} diff --git a/packages/ember-testing/lib/helpers.js b/packages/ember-testing/lib/helpers.js index 24522ac9f48..edf10340e24 100644 --- a/packages/ember-testing/lib/helpers.js +++ b/packages/ember-testing/lib/helpers.js @@ -1,29 +1,17 @@ import { registerHelper as helper, registerAsyncHelper as asyncHelper } from './test/helpers'; import andThen from './helpers/and_then'; -import click from './helpers/click'; import currentPath from './helpers/current_path'; import currentRouteName from './helpers/current_route_name'; import currentURL from './helpers/current_url'; -import fillIn from './helpers/fill_in'; -import find from './helpers/find'; -import findWithAssert from './helpers/find_with_assert'; -import keyEvent from './helpers/key_event'; import { pauseTest, resumeTest } from './helpers/pause_test'; -import triggerEvent from './helpers/trigger_event'; import visit from './helpers/visit'; import wait from './helpers/wait'; asyncHelper('visit', visit); -asyncHelper('click', click); -asyncHelper('keyEvent', keyEvent); -asyncHelper('fillIn', fillIn); asyncHelper('wait', wait); asyncHelper('andThen', andThen); asyncHelper('pauseTest', pauseTest); -asyncHelper('triggerEvent', triggerEvent); -helper('find', find); -helper('findWithAssert', findWithAssert); helper('currentRouteName', currentRouteName); helper('currentPath', currentPath); helper('currentURL', currentURL); diff --git a/packages/ember-testing/lib/helpers/-is-form-control.js b/packages/ember-testing/lib/helpers/-is-form-control.js deleted file mode 100644 index f1419e44bdc..00000000000 --- a/packages/ember-testing/lib/helpers/-is-form-control.js +++ /dev/null @@ -1,16 +0,0 @@ -const FORM_CONTROL_TAGS = ['INPUT', 'BUTTON', 'SELECT', 'TEXTAREA']; - -/** - @private - @param {Element} element the element to check - @returns {boolean} `true` when the element is a form control, `false` otherwise -*/ -export default function isFormControl(element) { - let { tagName, type } = element; - - if (type === 'hidden') { - return false; - } - - return FORM_CONTROL_TAGS.indexOf(tagName) > -1; -} diff --git a/packages/ember-testing/lib/helpers/click.js b/packages/ember-testing/lib/helpers/click.js deleted file mode 100644 index c2780821e4a..00000000000 --- a/packages/ember-testing/lib/helpers/click.js +++ /dev/null @@ -1,36 +0,0 @@ -/** -@module ember -*/ -import { focus, fireEvent } from '../events'; - -/** - Clicks an element and triggers any actions triggered by the element's `click` - event. - - Example: - - ```javascript - click('.some-jQuery-selector').then(function() { - // assert something - }); - ``` - - @method click - @param {String} selector jQuery selector for finding element on the DOM - @param {Object} context A DOM Element, Document, or jQuery to use as context - @return {RSVP.Promise} - @public -*/ -export default function click(app, selector, context) { - let $el = app.testHelpers.findWithAssert(selector, context); - let el = $el[0]; - - fireEvent(el, 'mousedown'); - - focus(el); - - fireEvent(el, 'mouseup'); - fireEvent(el, 'click'); - - return app.testHelpers.wait(); -} diff --git a/packages/ember-testing/lib/helpers/fill_in.js b/packages/ember-testing/lib/helpers/fill_in.js deleted file mode 100644 index c667eac6164..00000000000 --- a/packages/ember-testing/lib/helpers/fill_in.js +++ /dev/null @@ -1,46 +0,0 @@ -/** -@module ember -*/ -import { focus, fireEvent } from '../events'; -import isFormControl from './-is-form-control'; - -/** - Fills in an input element with some text. - - Example: - - ```javascript - fillIn('#email', 'you@example.com').then(function() { - // assert something - }); - ``` - - @method fillIn - @param {String} selector jQuery selector finding an input element on the DOM - to fill text with - @param {String} text text to place inside the input element - @return {RSVP.Promise} - @public -*/ -export default function fillIn(app, selector, contextOrText, text) { - let $el, el, context; - if (text === undefined) { - text = contextOrText; - } else { - context = contextOrText; - } - $el = app.testHelpers.findWithAssert(selector, context); - el = $el[0]; - focus(el); - - if (isFormControl(el)) { - el.value = text; - } else { - el.innerHTML = text; - } - - fireEvent(el, 'input'); - fireEvent(el, 'change'); - - return app.testHelpers.wait(); -} diff --git a/packages/ember-testing/lib/helpers/find.js b/packages/ember-testing/lib/helpers/find.js deleted file mode 100644 index 74ffab24d0d..00000000000 --- a/packages/ember-testing/lib/helpers/find.js +++ /dev/null @@ -1,41 +0,0 @@ -/** -@module ember -*/ -import { get } from '@ember/-internals/metal'; -import { assert } from '@ember/debug'; -import { jQueryDisabled } from '@ember/-internals/views'; - -/** - Finds an element in the context of the app's container element. A simple alias - for `app.$(selector)`. - - Example: - - ```javascript - var $el = find('.my-selector'); - ``` - - With the `context` param: - - ```javascript - var $el = find('.my-selector', '.parent-element-class'); - ``` - - @method find - @param {String} selector jQuery selector for element lookup - @param {String} [context] (optional) jQuery selector that will limit the selector - argument to find only within the context's children - @return {Object} DOM element representing the results of the query - @public -*/ -export default function find(app, selector, context) { - if (jQueryDisabled) { - assert( - 'If jQuery is disabled, please import and use helpers from @ember/test-helpers [https://github.com/emberjs/ember-test-helpers]. Note: `find` is not an available helper.' - ); - } - let $el; - context = context || get(app, 'rootElement'); - $el = app.$(selector, context); - return $el; -} diff --git a/packages/ember-testing/lib/helpers/find_with_assert.js b/packages/ember-testing/lib/helpers/find_with_assert.js deleted file mode 100644 index 15863b70d14..00000000000 --- a/packages/ember-testing/lib/helpers/find_with_assert.js +++ /dev/null @@ -1,34 +0,0 @@ -/** -@module ember -*/ -/** - Like `find`, but throws an error if the element selector returns no results. - - Example: - - ```javascript - var $el = findWithAssert('.doesnt-exist'); // throws error - ``` - - With the `context` param: - - ```javascript - var $el = findWithAssert('.selector-id', '.parent-element-class'); // assert will pass - ``` - - @method findWithAssert - @param {String} selector jQuery selector string for finding an element within - the DOM - @param {String} [context] (optional) jQuery selector that will limit the - selector argument to find only within the context's children - @return {Object} jQuery object representing the results of the query - @throws {Error} throws error if object returned has a length of 0 - @public -*/ -export default function findWithAssert(app, selector, context) { - let $el = app.testHelpers.find(selector, context); - if ($el.length === 0) { - throw new Error('Element ' + selector + ' not found.'); - } - return $el; -} diff --git a/packages/ember-testing/lib/helpers/key_event.js b/packages/ember-testing/lib/helpers/key_event.js deleted file mode 100644 index bed4161a048..00000000000 --- a/packages/ember-testing/lib/helpers/key_event.js +++ /dev/null @@ -1,36 +0,0 @@ -/** -@module ember -*/ -/** - Simulates a key event, e.g. `keypress`, `keydown`, `keyup` with the desired keyCode - Example: - ```javascript - keyEvent('.some-jQuery-selector', 'keypress', 13).then(function() { - // assert something - }); - ``` - @method keyEvent - @param {String} selector jQuery selector for finding element on the DOM - @param {String} type the type of key event, e.g. `keypress`, `keydown`, `keyup` - @param {Number} keyCode the keyCode of the simulated key event - @return {RSVP.Promise} - @since 1.5.0 - @public -*/ -export default function keyEvent(app, selector, contextOrType, typeOrKeyCode, keyCode) { - let context, type; - - if (keyCode === undefined) { - context = null; - keyCode = typeOrKeyCode; - type = contextOrType; - } else { - context = contextOrType; - type = typeOrKeyCode; - } - - return app.testHelpers.triggerEvent(selector, context, type, { - keyCode, - which: keyCode, - }); -} diff --git a/packages/ember-testing/lib/helpers/trigger_event.js b/packages/ember-testing/lib/helpers/trigger_event.js deleted file mode 100644 index 4b6e0a04f0d..00000000000 --- a/packages/ember-testing/lib/helpers/trigger_event.js +++ /dev/null @@ -1,62 +0,0 @@ -/** -@module ember -*/ -import { fireEvent } from '../events'; -/** - Triggers the given DOM event on the element identified by the provided selector. - Example: - ```javascript - triggerEvent('#some-elem-id', 'blur'); - ``` - This is actually used internally by the `keyEvent` helper like so: - ```javascript - triggerEvent('#some-elem-id', 'keypress', { keyCode: 13 }); - ``` - @method triggerEvent - @param {String} selector jQuery selector for finding element on the DOM - @param {String} [context] jQuery selector that will limit the selector - argument to find only within the context's children - @param {String} type The event type to be triggered. - @param {Object} [options] The options to be passed to jQuery.Event. - @return {RSVP.Promise} - @since 1.5.0 - @public -*/ -export default function triggerEvent(app, selector, contextOrType, typeOrOptions, possibleOptions) { - let arity = arguments.length; - let context, type, options; - - if (arity === 3) { - // context and options are optional, so this is - // app, selector, type - context = null; - type = contextOrType; - options = {}; - } else if (arity === 4) { - // context and options are optional, so this is - if (typeof typeOrOptions === 'object') { - // either - // app, selector, type, options - context = null; - type = contextOrType; - options = typeOrOptions; - } else { - // or - // app, selector, context, type - context = contextOrType; - type = typeOrOptions; - options = {}; - } - } else { - context = contextOrType; - type = typeOrOptions; - options = possibleOptions; - } - - let $el = app.testHelpers.findWithAssert(selector, context); - let el = $el[0]; - - fireEvent(el, type, options); - - return app.testHelpers.wait(); -} diff --git a/packages/ember-testing/lib/setup_for_testing.js b/packages/ember-testing/lib/setup_for_testing.js index 39fea3b120f..91c615d5fdb 100644 --- a/packages/ember-testing/lib/setup_for_testing.js +++ b/packages/ember-testing/lib/setup_for_testing.js @@ -1,13 +1,7 @@ /* global self */ import { setTesting } from '@ember/debug'; -import { jQuery, jQueryDisabled } from '@ember/-internals/views'; import { getAdapter, setAdapter } from './test/adapter'; -import { - incrementPendingRequests, - decrementPendingRequests, - clearPendingRequests, -} from './test/pending_requests'; import Adapter from './adapters/adapter'; import QUnitAdapter from './adapters/qunit'; @@ -31,14 +25,4 @@ export default function setupForTesting() { if (!adapter) { setAdapter(typeof self.QUnit === 'undefined' ? Adapter.create() : QUnitAdapter.create()); } - - if (!jQueryDisabled) { - jQuery(document).off('ajaxSend', incrementPendingRequests); - jQuery(document).off('ajaxComplete', decrementPendingRequests); - - clearPendingRequests(); - - jQuery(document).on('ajaxSend', incrementPendingRequests); - jQuery(document).on('ajaxComplete', decrementPendingRequests); - } } diff --git a/packages/ember-testing/lib/support.js b/packages/ember-testing/lib/support.js deleted file mode 100644 index a45df0845ca..00000000000 --- a/packages/ember-testing/lib/support.js +++ /dev/null @@ -1,62 +0,0 @@ -import { warn } from '@ember/debug'; -import { jQuery, jQueryDisabled } from '@ember/-internals/views'; - -import { hasDOM } from '@ember/-internals/browser-environment'; - -/** - @module ember -*/ - -const $ = jQuery; - -/** - This method creates a checkbox and triggers the click event to fire the - passed in handler. It is used to correct for a bug in older versions - of jQuery (e.g 1.8.3). - - @private - @method testCheckboxClick -*/ -function testCheckboxClick(handler) { - let input = document.createElement('input'); - $(input) - .attr('type', 'checkbox') - .css({ position: 'absolute', left: '-1000px', top: '-1000px' }) - .appendTo('body') - .on('click', handler) - .trigger('click') - .remove(); -} - -if (hasDOM && !jQueryDisabled) { - $(function () { - /* - Determine whether a checkbox checked using jQuery's "click" method will have - the correct value for its checked property. - - If we determine that the current jQuery version exhibits this behavior, - patch it to work correctly as in the commit for the actual fix: - https://github.com/jquery/jquery/commit/1fb2f92. - */ - testCheckboxClick(function () { - if (!this.checked && !$.event.special.click) { - $.event.special.click = { - // For checkbox, fire native event so checked state will be right - trigger() { - if (this.nodeName === 'INPUT' && this.type === 'checkbox' && this.click) { - this.click(); - return false; - } - }, - }; - } - }); - - // Try again to verify that the patch took effect or blow up. - testCheckboxClick(function () { - warn("clicked checkboxes should be checked! the jQuery patch didn't work", this.checked, { - id: 'ember-testing.test-checkbox-click', - }); - }); - }); -} diff --git a/packages/ember-testing/tests/acceptance_test.js b/packages/ember-testing/tests/acceptance_test.js deleted file mode 100644 index c8d5f8bb171..00000000000 --- a/packages/ember-testing/tests/acceptance_test.js +++ /dev/null @@ -1,480 +0,0 @@ -import { moduleFor, AutobootApplicationTestCase, runTask } from 'internal-test-helpers'; - -import { later } from '@ember/runloop'; -import Test from '../lib/test'; -import QUnitAdapter from '../lib/adapters/qunit'; -import { Route } from '@ember/-internals/routing'; -import { RSVP } from '@ember/-internals/runtime'; -import { jQueryDisabled } from '@ember/-internals/views'; -import { getDebugFunction, setDebugFunction } from '@ember/debug'; - -const originalDebug = getDebugFunction('debug'); - -const originalConsoleError = console.error; // eslint-disable-line no-console -let testContext; - -if (!jQueryDisabled) { - moduleFor( - 'ember-testing Acceptance', - class extends AutobootApplicationTestCase { - constructor() { - setDebugFunction('debug', function () {}); - super(); - this._originalAdapter = Test.adapter; - - testContext = this; - - runTask(() => { - this.createApplication(); - this.router.map(function () { - this.route('posts'); - this.route('comments'); - - this.route('abort_transition'); - - this.route('redirect'); - }); - - this.indexHitCount = 0; - this.currentRoute = 'index'; - - this.add( - 'route:index', - Route.extend({ - model() { - testContext.indexHitCount += 1; - }, - }) - ); - - this.add( - 'route:posts', - Route.extend({ - setupController() { - testContext.currentRoute = 'posts'; - this._super(...arguments); - }, - }) - ); - - this.addTemplate( - 'posts', - ` -
- - -
- ` - ); - - this.add( - 'route:comments', - Route.extend({ - setupController() { - testContext.currentRoute = 'comments'; - this._super(...arguments); - }, - }) - ); - - this.addTemplate('comments', `
{{input type="text"}}
`); - - this.add( - 'route:abort_transition', - Route.extend({ - beforeModel(transition) { - transition.abort(); - }, - }) - ); - - this.add( - 'route:redirect', - Route.extend({ - beforeModel() { - expectDeprecation(() => { - this.transitionTo('comments'); - }, /Calling transitionTo on a route is deprecated/); - }, - }) - ); - - this.application.setupForTesting(); - - Test.registerAsyncHelper('slowHelper', () => { - return new RSVP.Promise((resolve) => later(resolve, 10)); - }); - - this.application.injectTestHelpers(); - }); - } - afterEach() { - console.error = originalConsoleError; // eslint-disable-line no-console - super.afterEach(); - } - - teardown() { - setDebugFunction('debug', originalDebug); - Test.adapter = this._originalAdapter; - Test.unregisterHelper('slowHelper'); - window.slowHelper = undefined; - testContext = undefined; - super.teardown(); - } - - [`@test helpers can be chained with then`](assert) { - assert.expect(6); - - window - .visit('/posts') - .then(() => { - assert.equal(this.currentRoute, 'posts', 'Successfully visited posts route'); - assert.equal(window.currentURL(), '/posts', 'posts URL is correct'); - return window.click('a:contains("Comments")'); - }) - .then(() => { - assert.equal(this.currentRoute, 'comments', 'visit chained with click'); - return window.fillIn('.ember-text-field', 'yeah'); - }) - .then(() => { - assert.equal( - document.querySelector('.ember-text-field').value, - 'yeah', - 'chained with fillIn' - ); - return window.fillIn('.ember-text-field', '#qunit-fixture', 'context working'); - }) - .then(() => { - assert.equal( - document.querySelector('.ember-text-field').value, - 'context working', - 'chained with fillIn' - ); - return window.click('.does-not-exist'); - }) - .catch((e) => { - assert.equal( - e.message, - 'Element .does-not-exist not found.', - 'Non-existent click exception caught' - ); - }); - } - - [`@test helpers can be chained to each other (legacy)`](assert) { - assert.expect(7); - - window - .visit('/posts') - .click('a:first', '#comments-link') - .fillIn('.ember-text-field', 'hello') - .then(() => { - assert.equal(this.currentRoute, 'comments', 'Successfully visited comments route'); - assert.equal(window.currentURL(), '/comments', 'Comments URL is correct'); - assert.equal( - document.querySelector('.ember-text-field').value, - 'hello', - 'Fillin successfully works' - ); - window.find('.ember-text-field').one('keypress', (e) => { - assert.equal(e.keyCode, 13, 'keyevent chained with correct keyCode.'); - assert.equal(e.which, 13, 'keyevent chained with correct which.'); - }); - }) - .keyEvent('.ember-text-field', 'keypress', 13) - .visit('/posts') - .then(() => { - assert.equal(this.currentRoute, 'posts', 'Thens can also be chained to helpers'); - assert.equal(window.currentURL(), '/posts', 'URL is set correct on chained helpers'); - }); - } - - [`@test helpers don't need to be chained`](assert) { - assert.expect(5); - - window.visit('/posts'); - - window.click('a:first', '#comments-link'); - - window.fillIn('.ember-text-field', 'hello'); - - window.andThen(() => { - assert.equal(this.currentRoute, 'comments', 'Successfully visited comments route'); - assert.equal(window.currentURL(), '/comments', 'Comments URL is correct'); - assert.equal( - window.find('.ember-text-field').val(), - 'hello', - 'Fillin successfully works' - ); - }); - - window.visit('/posts'); - - window.andThen(() => { - assert.equal(this.currentRoute, 'posts'); - assert.equal(window.currentURL(), '/posts'); - }); - } - - [`@test Nested async helpers`](assert) { - assert.expect(5); - - window.visit('/posts'); - - window.andThen(() => { - window.click('a:first', '#comments-link'); - window.fillIn('.ember-text-field', 'hello'); - }); - - window.andThen(() => { - assert.equal(this.currentRoute, 'comments', 'Successfully visited comments route'); - assert.equal(window.currentURL(), '/comments', 'Comments URL is correct'); - assert.equal( - window.find('.ember-text-field').val(), - 'hello', - 'Fillin successfully works' - ); - }); - - window.visit('/posts'); - - window.andThen(() => { - assert.equal(this.currentRoute, 'posts'); - assert.equal(window.currentURL(), '/posts'); - }); - } - - [`@test Multiple nested async helpers`](assert) { - assert.expect(3); - - window.visit('/posts'); - - window.andThen(() => { - window.click('a:first', '#comments-link'); - - window.fillIn('.ember-text-field', 'hello'); - window.fillIn('.ember-text-field', 'goodbye'); - }); - - window.andThen(() => { - assert.equal( - window.find('.ember-text-field').val(), - 'goodbye', - 'Fillin successfully works' - ); - assert.equal(this.currentRoute, 'comments', 'Successfully visited comments route'); - assert.equal(window.currentURL(), '/comments', 'Comments URL is correct'); - }); - } - - [`@test Helpers nested in thens`](assert) { - assert.expect(5); - - window.visit('/posts').then(() => { - window.click('a:first', '#comments-link'); - }); - - window.andThen(() => { - window.fillIn('.ember-text-field', 'hello'); - }); - - window.andThen(() => { - assert.equal(this.currentRoute, 'comments', 'Successfully visited comments route'); - assert.equal(window.currentURL(), '/comments', 'Comments URL is correct'); - assert.equal( - window.find('.ember-text-field').val(), - 'hello', - 'Fillin successfully works' - ); - }); - - window.visit('/posts'); - - window.andThen(() => { - assert.equal(this.currentRoute, 'posts'); - assert.equal(window.currentURL(), '/posts', 'Posts URL is correct'); - }); - } - - [`@test Aborted transitions are not logged via Ember.Test.adapter#exception`](assert) { - assert.expect(0); - - Test.adapter = QUnitAdapter.create({ - exception() { - assert.ok(false, 'aborted transitions are not logged'); - }, - }); - - window.visit('/abort_transition'); - } - - [`@test Unhandled exceptions are logged via Ember.Test.adapter#exception`](assert) { - assert.expect(2); - - console.error = () => {}; // eslint-disable-line no-console - let asyncHandled; - Test.adapter = QUnitAdapter.create({ - exception(error) { - assert.equal( - error.message, - 'Element .does-not-exist not found.', - 'Exception successfully caught and passed to Ember.Test.adapter.exception' - ); - // handle the rejection so it doesn't leak later. - asyncHandled.catch(() => {}); - }, - }); - - window.visit('/posts'); - - window.click('.invalid-element').catch((error) => { - assert.equal( - error.message, - 'Element .invalid-element not found.', - 'Exception successfully handled in the rejection handler' - ); - }); - - asyncHandled = window.click('.does-not-exist'); - } - - [`@test Unhandled exceptions in 'andThen' are logged via Ember.Test.adapter#exception`]( - assert - ) { - assert.expect(1); - - console.error = () => {}; // eslint-disable-line no-console - Test.adapter = QUnitAdapter.create({ - exception(error) { - assert.equal( - error.message, - 'Catch me', - 'Exception successfully caught and passed to Ember.Test.adapter.exception' - ); - }, - }); - - window.visit('/posts'); - - window.andThen(() => { - throw new Error('Catch me'); - }); - } - - [`@test should not start routing on the root URL when visiting another`](assert) { - assert.expect(4); - - window.visit('/posts'); - - window.andThen(() => { - assert.ok(window.find('#comments-link'), 'found comments-link'); - assert.equal(this.currentRoute, 'posts', 'Successfully visited posts route'); - assert.equal(window.currentURL(), '/posts', 'Posts URL is correct'); - assert.equal( - this.indexHitCount, - 0, - 'should not hit index route when visiting another route' - ); - }); - } - - [`@test only enters the index route once when visiting `](assert) { - assert.expect(1); - - window.visit('/'); - - window.andThen(() => { - assert.equal(this.indexHitCount, 1, 'should hit index once when visiting /'); - }); - } - - [`@test test must not finish while asyncHelpers are pending`](assert) { - assert.expect(2); - - let async = 0; - let innerRan = false; - - Test.adapter = QUnitAdapter.extend({ - asyncStart() { - async++; - this._super(); - }, - asyncEnd() { - async--; - this._super(); - }, - }).create(); - - this.application.testHelpers.slowHelper(); - - window.andThen(() => { - innerRan = true; - }); - - assert.equal(innerRan, false, 'should not have run yet'); - assert.ok(async > 0, 'should have told the adapter to pause'); - - if (async === 0) { - // If we failed the test, prevent zalgo from escaping and breaking - // our other tests. - Test.adapter.asyncStart(); - Test.resolve().then(() => { - Test.adapter.asyncEnd(); - }); - } - } - - [`@test visiting a URL that causes another transition should yield the correct URL`](assert) { - assert.expect(2); - - window.visit('/redirect'); - - window.andThen(() => { - assert.equal(window.currentURL(), '/comments', 'Redirected to Comments URL'); - }); - } - - [`@test visiting a URL and then visiting a second URL with a transition should yield the correct URL`]( - assert - ) { - assert.expect(3); - - window.visit('/posts'); - - window.andThen(function () { - assert.equal(window.currentURL(), '/posts', 'First visited URL is correct'); - }); - - window.visit('/redirect'); - - window.andThen(() => { - assert.equal(window.currentURL(), '/comments', 'Redirected to Comments URL'); - }); - } - } - ); - - moduleFor( - 'ember-testing Acceptance - teardown', - class extends AutobootApplicationTestCase { - [`@test that the setup/teardown happens correctly`](assert) { - assert.expect(2); - - runTask(() => { - this.createApplication(); - }); - this.application.injectTestHelpers(); - - assert.ok(typeof Test.Promise.prototype.click === 'function'); - - runTask(() => { - this.application.destroy(); - }); - - assert.equal(Test.Promise.prototype.click, undefined); - } - } - ); -} diff --git a/packages/ember-testing/tests/helpers_test.js b/packages/ember-testing/tests/helpers_test.js deleted file mode 100644 index 729fd6da46f..00000000000 --- a/packages/ember-testing/tests/helpers_test.js +++ /dev/null @@ -1,1278 +0,0 @@ -import { moduleFor, AutobootApplicationTestCase, runTask } from 'internal-test-helpers'; - -import { Route } from '@ember/-internals/routing'; -import Controller from '@ember/controller'; -import { RSVP } from '@ember/-internals/runtime'; -import { action } from '@ember/object'; -import { later } from '@ember/runloop'; -import { Component } from '@ember/-internals/glimmer'; -import { jQueryDisabled, jQuery } from '@ember/-internals/views'; - -import Test from '../lib/test'; -import setupForTesting from '../lib/setup_for_testing'; - -import { - pendingRequests, - incrementPendingRequests, - decrementPendingRequests, - clearPendingRequests, -} from '../lib/test/pending_requests'; -import { setAdapter, getAdapter } from '../lib/test/adapter'; -import { registerWaiter, unregisterWaiter } from '../lib/test/waiters'; -import { getDebugFunction, setDebugFunction } from '@ember/debug'; - -const originalInfo = getDebugFunction('info'); -const noop = function () {}; - -function registerHelper() { - Test.registerHelper('LeakyMcLeakLeak', () => {}); -} - -function assertHelpers(assert, application, helperContainer, expected) { - if (!helperContainer) { - helperContainer = window; - } - if (expected === undefined) { - expected = true; - } - - function checkHelperPresent(helper, expected) { - let presentInHelperContainer = Boolean(helperContainer[helper]); - let presentInTestHelpers = Boolean(application.testHelpers[helper]); - - assert.ok( - presentInHelperContainer === expected, - "Expected '" + helper + "' to be present in the helper container (defaults to window)." - ); - assert.ok( - presentInTestHelpers === expected, - "Expected '" + helper + "' to be present in App.testHelpers." - ); - } - - checkHelperPresent('visit', expected); - checkHelperPresent('click', expected); - checkHelperPresent('keyEvent', expected); - checkHelperPresent('fillIn', expected); - checkHelperPresent('wait', expected); - checkHelperPresent('triggerEvent', expected); -} - -function assertNoHelpers(assert, application, helperContainer) { - assertHelpers(assert, application, helperContainer, false); -} - -class HelpersTestCase extends AutobootApplicationTestCase { - constructor() { - super(); - this._originalAdapter = getAdapter(); - } - - teardown() { - setAdapter(this._originalAdapter); - document.removeEventListener('ajaxSend', incrementPendingRequests); - document.removeEventListener('ajaxComplete', decrementPendingRequests); - clearPendingRequests(); - if (this.application) { - this.application.removeTestHelpers(); - } - super.teardown(); - } -} - -class HelpersApplicationTestCase extends HelpersTestCase { - constructor() { - super(); - runTask(() => { - this.createApplication(); - this.application.setupForTesting(); - this.application.injectTestHelpers(); - }); - } -} - -if (!jQueryDisabled) { - moduleFor( - 'ember-testing: Helper setup', - class extends HelpersTestCase { - [`@test Ember.Application#injectTestHelpers/#removeTestHelper`](assert) { - runTask(() => { - this.createApplication(); - }); - - assertNoHelpers(assert, this.application); - - registerHelper(); - - this.application.injectTestHelpers(); - - assertHelpers(assert, this.application); - - assert.ok(Test.Promise.prototype.LeakyMcLeakLeak, 'helper in question SHOULD be present'); - - this.application.removeTestHelpers(); - - assertNoHelpers(assert, this.application); - - assert.equal( - Test.Promise.prototype.LeakyMcLeakLeak, - undefined, - 'should NOT leak test promise extensions' - ); - } - - [`@test Ember.Application#setupForTesting`](assert) { - runTask(() => { - this.createApplication(); - this.application.setupForTesting(); - }); - - let routerInstance = this.applicationInstance.lookup('router:main'); - assert.equal(routerInstance.location, 'none'); - } - - [`@test Ember.Application.setupForTesting sets the application to 'testing'`](assert) { - runTask(() => { - this.createApplication(); - this.application.setupForTesting(); - }); - - assert.equal(this.application.testing, true, 'Application instance is set to testing.'); - } - - [`@test Ember.Application.setupForTesting leaves the system in a deferred state.`](assert) { - runTask(() => { - this.createApplication(); - this.application.setupForTesting(); - }); - - assert.equal( - this.application._readinessDeferrals, - 1, - 'App is in deferred state after setupForTesting.' - ); - } - - [`@test App.reset() after Application.setupForTesting leaves the system in a deferred state.`]( - assert - ) { - runTask(() => { - this.createApplication(); - this.application.setupForTesting(); - }); - - assert.equal( - this.application._readinessDeferrals, - 1, - 'App is in deferred state after setupForTesting.' - ); - - this.application.reset(); - - assert.equal( - this.application._readinessDeferrals, - 1, - 'App is in deferred state after setupForTesting.' - ); - } - - [`@test Ember.Application#injectTestHelpers calls callbacks registered with onInjectHelpers`]( - assert - ) { - let injected = 0; - - Test.onInjectHelpers(() => { - injected++; - }); - - // bind(this) so Babel doesn't leak _this - // into the context onInjectHelpers. - runTask( - function () { - this.createApplication(); - this.application.setupForTesting(); - }.bind(this) - ); - - assert.equal(injected, 0, 'onInjectHelpers are not called before injectTestHelpers'); - - this.application.injectTestHelpers(); - - assert.equal(injected, 1, 'onInjectHelpers are called after injectTestHelpers'); - } - - [`@test Ember.Application#injectTestHelpers adds helpers to provided object.`](assert) { - let helpers = {}; - - runTask(() => { - this.createApplication(); - this.application.setupForTesting(); - }); - - this.application.injectTestHelpers(helpers); - - assertHelpers(assert, this.application, helpers); - - this.application.removeTestHelpers(); - - assertNoHelpers(assert, this.application, helpers); - } - - [`@test Ember.Application#removeTestHelpers resets the helperContainer's original values`]( - assert - ) { - let helpers = { visit: 'snazzleflabber' }; - - runTask(() => { - this.createApplication(); - this.application.setupForTesting(); - }); - - this.application.injectTestHelpers(helpers); - - assert.notEqual(helpers.visit, 'snazzleflabber', 'helper added to container'); - this.application.removeTestHelpers(); - - assert.equal(helpers.visit, 'snazzleflabber', 'original value added back to container'); - } - } - ); - - moduleFor( - 'ember-testing: Helper methods', - class extends HelpersApplicationTestCase { - [`@test 'wait' respects registerWaiters`](assert) { - assert.expect(3); - - let counter = 0; - function waiter() { - return ++counter > 2; - } - - let other = 0; - function otherWaiter() { - return ++other > 2; - } - - runTask(() => { - this.application.advanceReadiness(); - }); - - registerWaiter(waiter); - registerWaiter(otherWaiter); - - let { - application: { testHelpers }, - } = this; - return testHelpers - .wait() - .then(() => { - assert.equal(waiter(), true, 'should not resolve until our waiter is ready'); - unregisterWaiter(waiter); - counter = 0; - return testHelpers.wait(); - }) - .then(() => { - assert.equal(counter, 0, 'unregistered waiter was not checked'); - assert.equal(otherWaiter(), true, 'other waiter is still registered'); - }) - .finally(() => { - unregisterWaiter(otherWaiter); - }); - } - - [`@test 'visit' advances readiness.`](assert) { - assert.expect(2); - - assert.equal( - this.application._readinessDeferrals, - 1, - 'App is in deferred state after setupForTesting.' - ); - - return this.application.testHelpers.visit('/').then(() => { - assert.equal( - this.application._readinessDeferrals, - 0, - `App's readiness was advanced by visit.` - ); - }); - } - - [`@test 'wait' helper can be passed a resolution value`](assert) { - assert.expect(4); - - runTask(() => { - this.application.advanceReadiness(); - }); - - let promiseObjectValue = {}; - let objectValue = {}; - let { - application: { testHelpers }, - } = this; - return testHelpers - .wait('text') - .then((val) => { - assert.equal(val, 'text', 'can resolve to a string'); - return testHelpers.wait(1); - }) - .then((val) => { - assert.equal(val, 1, 'can resolve to an integer'); - return testHelpers.wait(objectValue); - }) - .then((val) => { - assert.equal(val, objectValue, 'can resolve to an object'); - return testHelpers.wait(RSVP.resolve(promiseObjectValue)); - }) - .then((val) => { - assert.equal(val, promiseObjectValue, 'can resolve to a promise resolution value'); - }); - } - - [`@test 'click' triggers appropriate events in order`](assert) { - assert.expect(5); - - this.add( - 'component:index-wrapper', - Component.extend({ - classNames: 'index-wrapper', - - didInsertElement() { - let wrapper = document.querySelector('.index-wrapper'); - wrapper.addEventListener('mousedown', (e) => events.push(e.type)); - wrapper.addEventListener('mouseup', (e) => events.push(e.type)); - wrapper.addEventListener('click', (e) => events.push(e.type)); - wrapper.addEventListener('focusin', (e) => events.push(e.type)); - }, - }) - ); - - this.add( - 'component:x-checkbox', - Component.extend({ - tagName: 'input', - attributeBindings: ['type'], - type: 'checkbox', - click() { - events.push('click:' + this.get('checked')); - }, - change() { - events.push('change:' + this.get('checked')); - }, - }) - ); - - this.addTemplate( - 'index', - ` - {{#index-wrapper}} - - {{x-checkbox type="checkbox"}} - {{textarea}} -
- {{/index-wrapper}}')); - ` - ); - - runTask(() => { - this.application.advanceReadiness(); - }); - - let events; - let { - application: { testHelpers }, - } = this; - return testHelpers - .wait() - .then(() => { - events = []; - return testHelpers.click('.index-wrapper'); - }) - .then(() => { - assert.deepEqual(events, ['mousedown', 'mouseup', 'click'], 'fires events in order'); - }) - .then(() => { - events = []; - return testHelpers.click('.index-wrapper input[type=text]'); - }) - .then(() => { - assert.deepEqual( - events, - ['mousedown', 'focusin', 'mouseup', 'click'], - 'fires focus events on inputs' - ); - }) - .then(() => { - events = []; - return testHelpers.click('.index-wrapper textarea'); - }) - .then(() => { - assert.deepEqual( - events, - ['mousedown', 'focusin', 'mouseup', 'click'], - 'fires focus events on textareas' - ); - }) - .then(() => { - events = []; - return testHelpers.click('.index-wrapper div'); - }) - .then(() => { - assert.deepEqual( - events, - ['mousedown', 'focusin', 'mouseup', 'click'], - 'fires focus events on contenteditable' - ); - }) - .then(() => { - events = []; - return testHelpers.click('.index-wrapper input[type=checkbox]'); - }) - .then(() => { - // i.e. mousedown, mouseup, change:true, click, click:true - // Firefox differs so we can't assert the exact ordering here. - // See https://bugzilla.mozilla.org/show_bug.cgi?id=843554. - assert.equal(events.length, 5, 'fires click and change on checkboxes'); - }); - } - - [`@test 'click' triggers native events with simulated X/Y coordinates`](assert) { - assert.expect(15); - - this.add( - 'component:index-wrapper', - Component.extend({ - classNames: 'index-wrapper', - - didInsertElement() { - let pushEvent = (e) => events.push(e); - this.element.addEventListener('mousedown', pushEvent); - this.element.addEventListener('mouseup', pushEvent); - this.element.addEventListener('click', pushEvent); - }, - }) - ); - - this.addTemplate( - 'index', - ` - {{#index-wrapper}}some text{{/index-wrapper}} - ` - ); - - runTask(() => { - this.application.advanceReadiness(); - }); - - let events; - let { - application: { - testHelpers: { wait, click }, - }, - } = this; - return wait() - .then(() => { - events = []; - return click('.index-wrapper'); - }) - .then(() => { - events.forEach((e) => { - assert.ok(e instanceof window.Event, 'The event is an instance of MouseEvent'); - assert.ok(typeof e.screenX === 'number', 'screenX is correct'); - assert.ok(typeof e.screenY === 'number', 'screenY is correct'); - assert.ok(typeof e.clientX === 'number', 'clientX is correct'); - assert.ok(typeof e.clientY === 'number', 'clientY is correct'); - }); - }); - } - - [`@test 'triggerEvent' with mouseenter triggers native events with simulated X/Y coordinates`]( - assert - ) { - assert.expect(5); - - let evt; - this.add( - 'component:index-wrapper', - Component.extend({ - classNames: 'index-wrapper', - didInsertElement() { - this.element.addEventListener('mouseenter', (e) => (evt = e)); - }, - }) - ); - - this.addTemplate('index', `{{#index-wrapper}}some text{{/index-wrapper}}`); - - runTask(() => { - this.application.advanceReadiness(); - }); - - let { - application: { - testHelpers: { wait, triggerEvent }, - }, - } = this; - return wait() - .then(() => { - return triggerEvent('.index-wrapper', 'mouseenter'); - }) - .then(() => { - assert.ok(evt instanceof window.Event, 'The event is an instance of MouseEvent'); - assert.ok(typeof evt.screenX === 'number', 'screenX is correct'); - assert.ok(typeof evt.screenY === 'number', 'screenY is correct'); - assert.ok(typeof evt.clientX === 'number', 'clientX is correct'); - assert.ok(typeof evt.clientY === 'number', 'clientY is correct'); - }); - } - - [`@test 'wait' waits for outstanding timers`](assert) { - assert.expect(1); - - runTask(() => { - this.application.advanceReadiness(); - }); - - let waitDone = false; - later(() => { - waitDone = true; - }, 20); - - return this.application.testHelpers.wait().then(() => { - assert.equal(waitDone, true, 'should wait for the timer to be fired.'); - }); - } - - [`@test 'wait' respects registerWaiters with optional context`](assert) { - assert.expect(3); - - let obj = { - counter: 0, - ready() { - return ++this.counter > 2; - }, - }; - - let other = 0; - function otherWaiter() { - return ++other > 2; - } - - runTask(() => { - this.application.advanceReadiness(); - }); - - registerWaiter(obj, obj.ready); - registerWaiter(otherWaiter); - - let { - application: { - testHelpers: { wait }, - }, - } = this; - return wait() - .then(() => { - assert.equal(obj.ready(), true, 'should not resolve until our waiter is ready'); - unregisterWaiter(obj, obj.ready); - obj.counter = 0; - return wait(); - }) - .then(() => { - assert.equal(obj.counter, 0, 'the unregistered waiter should still be at 0'); - assert.equal(otherWaiter(), true, 'other waiter should still be registered'); - }) - .finally(() => { - unregisterWaiter(otherWaiter); - }); - } - - [`@test 'wait' does not error if routing has not begun`](assert) { - assert.expect(1); - - return this.application.testHelpers.wait().then(() => { - assert.ok(true, 'should not error without `visit`'); - }); - } - - [`@test 'triggerEvent' accepts an optional options hash without context`](assert) { - assert.expect(3); - - let event; - this.add( - 'component:index-wrapper', - Component.extend({ - didInsertElement() { - let domElem = document.querySelector('.input'); - domElem.addEventListener('change', (e) => (event = e)); - domElem.addEventListener('keydown', (e) => (event = e)); - }, - }) - ); - - this.addTemplate('index', `{{index-wrapper}}`); - this.addTemplate( - 'components/index-wrapper', - ` - - ` - ); - - runTask(() => { - this.application.advanceReadiness(); - }); - - let { - application: { - testHelpers: { wait, triggerEvent }, - }, - } = this; - return wait() - .then(() => { - return triggerEvent('.input', 'keydown', { keyCode: 13 }); - }) - .then(() => { - assert.equal(event.keyCode, 13, 'options were passed'); - assert.equal(event.type, 'keydown', 'correct event was triggered'); - assert.equal( - event.target.getAttribute('id'), - 'scope', - 'triggered on the correct element' - ); - }); - } - - [`@test 'triggerEvent' can limit searching for a selector to a scope`](assert) { - assert.expect(2); - - let event; - this.add( - 'component:index-wrapper', - Component.extend({ - didInsertElement() { - let firstInput = document.querySelector('.input'); - firstInput.addEventListener('blur', (e) => (event = e)); - firstInput.addEventListener('change', (e) => (event = e)); - let secondInput = document.querySelector('#limited .input'); - secondInput.addEventListener('blur', (e) => (event = e)); - secondInput.addEventListener('change', (e) => (event = e)); - }, - }) - ); - - this.addTemplate( - 'components/index-wrapper', - ` - -
- -
- ` - ); - this.addTemplate('index', `{{index-wrapper}}`); - - runTask(() => { - this.application.advanceReadiness(); - }); - - let { - application: { - testHelpers: { wait, triggerEvent }, - }, - } = this; - return wait() - .then(() => { - return triggerEvent('.input', '#limited', 'blur'); - }) - .then(() => { - assert.equal(event.type, 'blur', 'correct event was triggered'); - assert.equal( - event.target.getAttribute('id'), - 'inside-scope', - 'triggered on the correct element' - ); - }); - } - - [`@test 'triggerEvent' can be used to trigger arbitrary events`](assert) { - assert.expect(2); - - let event; - this.add( - 'component:index-wrapper', - Component.extend({ - didInsertElement() { - let foo = document.getElementById('foo'); - foo.addEventListener('blur', (e) => (event = e)); - foo.addEventListener('change', (e) => (event = e)); - }, - }) - ); - - this.addTemplate( - 'components/index-wrapper', - ` - - ` - ); - this.addTemplate('index', `{{index-wrapper}}`); - - runTask(() => { - this.application.advanceReadiness(); - }); - - let { - application: { - testHelpers: { wait, triggerEvent }, - }, - } = this; - return wait() - .then(() => { - return triggerEvent('#foo', 'blur'); - }) - .then(() => { - assert.equal(event.type, 'blur', 'correct event was triggered'); - assert.equal( - event.target.getAttribute('id'), - 'foo', - 'triggered on the correct element' - ); - }); - } - - [`@test 'fillIn' takes context into consideration`](assert) { - assert.expect(2); - - this.addTemplate( - 'index', - `
- -
- ` - ); - - runTask(() => { - this.application.advanceReadiness(); - }); - - let { - application: { - testHelpers: { visit, fillIn, andThen, find }, - }, - } = this; - visit('/'); - fillIn('.current', '#parent', 'current value'); - - return andThen(() => { - assert.equal(find('#first')[0].value, 'current value'); - assert.equal(find('#second')[0].value, ''); - }); - } - - [`@test 'fillIn' focuses on the element`](assert) { - let wasFocused = false; - - this.add( - 'controller:index', - Controller.extend({ - wasFocused: action(function () { - wasFocused = true; - }), - }) - ); - - this.addTemplate( - 'index', - `
- -
'` - ); - - runTask(() => { - this.application.advanceReadiness(); - }); - - let { - application: { - testHelpers: { visit, fillIn, andThen, find, wait }, - }, - } = this; - visit('/'); - fillIn('#first', 'current value'); - andThen(() => { - assert.ok(wasFocused, 'focusIn event was triggered'); - - assert.equal(find('#first')[0].value, 'current value'); - }); - - return wait(); - } - - [`@test 'fillIn' fires 'input' and 'change' events in the proper order`](assert) { - assert.expect(1); - - let events = []; - this.add( - 'controller:index', - Controller.extend({ - actions: { - oninputHandler(e) { - events.push(e.type); - }, - onchangeHandler(e) { - events.push(e.type); - }, - }, - }) - ); - - this.addTemplate( - 'index', - `` - ); - - runTask(() => { - this.application.advanceReadiness(); - }); - - let { - application: { - testHelpers: { visit, fillIn, andThen, wait }, - }, - } = this; - - visit('/'); - fillIn('#first', 'current value'); - andThen(() => { - assert.deepEqual( - events, - ['input', 'change'], - '`input` and `change` events are fired in the proper order' - ); - }); - - return wait(); - } - - [`@test 'fillIn' only sets the value in the first matched element`](assert) { - this.addTemplate( - 'index', - ` - - - ` - ); - - runTask(() => { - this.application.advanceReadiness(); - }); - - let { - application: { - testHelpers: { visit, fillIn, find, andThen, wait }, - }, - } = this; - - visit('/'); - fillIn('input.in-test', 'new value'); - andThen(() => { - assert.equal(find('#first')[0].value, 'new value'); - assert.equal(find('#second')[0].value, ''); - }); - - return wait(); - } - - [`@test 'triggerEvent' accepts an optional options hash and context`](assert) { - assert.expect(3); - - let event; - this.add( - 'component:index-wrapper', - Component.extend({ - didInsertElement() { - let firstInput = document.querySelector('.input'); - firstInput.addEventListener('keydown', (e) => (event = e), false); - firstInput.addEventListener('change', (e) => (event = e), false); - let secondInput = document.querySelector('#limited .input'); - secondInput.addEventListener('keydown', (e) => (event = e), false); - secondInput.addEventListener('change', (e) => (event = e), false); - }, - }) - ); - - this.addTemplate( - 'components/index-wrapper', - ` - -
- -
- ` - ); - this.addTemplate('index', `{{index-wrapper}}`); - - runTask(() => { - this.application.advanceReadiness(); - }); - - let { - application: { - testHelpers: { wait, triggerEvent }, - }, - } = this; - return wait() - .then(() => { - return triggerEvent('.input', '#limited', 'keydown', { - keyCode: 13, - }); - }) - .then(() => { - assert.equal(event.keyCode, 13, 'options were passed'); - assert.equal(event.type, 'keydown', 'correct event was triggered'); - assert.equal( - event.target.getAttribute('id'), - 'inside-scope', - 'triggered on the correct element' - ); - }); - } - } - ); - - moduleFor( - 'ember-testing: debugging helpers', - class extends HelpersApplicationTestCase { - afterEach() { - super.afterEach(); - setDebugFunction('info', originalInfo); - } - - constructor() { - super(); - runTask(() => { - this.application.advanceReadiness(); - }); - } - - [`@test pauseTest pauses`](assert) { - assert.expect(1); - // overwrite info to suppress the console output (see https://github.com/emberjs/ember.js/issues/16391) - setDebugFunction('info', noop); - - let { andThen, pauseTest } = this.application.testHelpers; - - andThen(() => { - Test.adapter.asyncStart = () => { - assert.ok(true, 'Async start should be called after waiting for other helpers'); - }; - }); - - pauseTest(); - } - - [`@test resumeTest resumes paused tests`](assert) { - assert.expect(1); - // overwrite info to suppress the console output (see https://github.com/emberjs/ember.js/issues/16391) - setDebugFunction('info', noop); - - let { - application: { - testHelpers: { pauseTest, resumeTest }, - }, - } = this; - - later(() => resumeTest(), 20); - return pauseTest().then(() => { - assert.ok(true, 'pauseTest promise was resolved'); - }); - } - - [`@test resumeTest throws if nothing to resume`](assert) { - assert.expect(1); - - assert.throws(() => { - this.application.testHelpers.resumeTest(); - }, /Testing has not been paused. There is nothing to resume./); - } - } - ); - - moduleFor( - 'ember-testing: routing helpers', - class extends HelpersTestCase { - constructor() { - super(); - runTask(() => { - this.createApplication(); - this.application.setupForTesting(); - this.application.injectTestHelpers(); - this.router.map(function () { - this.route('posts', { resetNamespace: true }, function () { - this.route('new'); - this.route('edit', { resetNamespace: true }); - }); - }); - }); - runTask(() => { - this.application.advanceReadiness(); - }); - } - - [`@test currentRouteName for '/'`](assert) { - assert.expect(3); - - let { - application: { testHelpers }, - } = this; - return testHelpers.visit('/').then(() => { - assert.equal(testHelpers.currentRouteName(), 'index', `should equal 'index'.`); - assert.equal(testHelpers.currentPath(), 'index', `should equal 'index'.`); - assert.equal(testHelpers.currentURL(), '/', `should equal '/'.`); - }); - } - - [`@test currentRouteName for '/posts'`](assert) { - assert.expect(3); - - let { - application: { testHelpers }, - } = this; - return testHelpers.visit('/posts').then(() => { - assert.equal( - testHelpers.currentRouteName(), - 'posts.index', - `should equal 'posts.index'.` - ); - assert.equal(testHelpers.currentPath(), 'posts.index', `should equal 'posts.index'.`); - assert.equal(testHelpers.currentURL(), '/posts', `should equal '/posts'.`); - }); - } - - [`@test currentRouteName for '/posts/new'`](assert) { - assert.expect(3); - - let { - application: { testHelpers }, - } = this; - return testHelpers.visit('/posts/new').then(() => { - assert.equal(testHelpers.currentRouteName(), 'posts.new', `should equal 'posts.new'.`); - assert.equal(testHelpers.currentPath(), 'posts.new', `should equal 'posts.new'.`); - assert.equal(testHelpers.currentURL(), '/posts/new', `should equal '/posts/new'.`); - }); - } - - [`@test currentRouteName for '/posts/edit'`](assert) { - assert.expect(3); - - let { - application: { testHelpers }, - } = this; - return testHelpers.visit('/posts/edit').then(() => { - assert.equal(testHelpers.currentRouteName(), 'edit', `should equal 'edit'.`); - assert.equal(testHelpers.currentPath(), 'posts.edit', `should equal 'posts.edit'.`); - assert.equal(testHelpers.currentURL(), '/posts/edit', `should equal '/posts/edit'.`); - }); - } - } - ); - - moduleFor( - 'ember-testing: pendingRequests', - class extends HelpersApplicationTestCase { - trigger(type, xhr) { - jQuery(document).trigger(type, xhr); - } - - [`@test pendingRequests is maintained for ajaxSend and ajaxComplete events`](assert) { - let done = assert.async(); - assert.equal(pendingRequests(), 0); - - let xhr = { some: 'xhr' }; - - this.trigger('ajaxSend', xhr); - assert.equal(pendingRequests(), 1, 'Ember.Test.pendingRequests was incremented'); - - this.trigger('ajaxComplete', xhr); - setTimeout(function () { - assert.equal(pendingRequests(), 0, 'Ember.Test.pendingRequests was decremented'); - done(); - }, 0); - } - - [`@test pendingRequests is ignores ajaxComplete events from past setupForTesting calls`]( - assert - ) { - assert.equal(pendingRequests(), 0); - - let xhr = { some: 'xhr' }; - - this.trigger('ajaxSend', xhr); - assert.equal(pendingRequests(), 1, 'Ember.Test.pendingRequests was incremented'); - - setupForTesting(); - - assert.equal(pendingRequests(), 0, 'Ember.Test.pendingRequests was reset'); - - let altXhr = { some: 'more xhr' }; - - this.trigger('ajaxSend', altXhr); - assert.equal(pendingRequests(), 1, 'Ember.Test.pendingRequests was incremented'); - - this.trigger('ajaxComplete', xhr); - assert.equal( - pendingRequests(), - 1, - 'Ember.Test.pendingRequests is not impressed with your unexpected complete' - ); - } - - [`@test pendingRequests is reset by setupForTesting`](assert) { - incrementPendingRequests(); - - setupForTesting(); - - assert.equal(pendingRequests(), 0, 'pendingRequests is reset'); - } - } - ); - - moduleFor( - 'ember-testing: async router', - class extends HelpersTestCase { - constructor() { - super(); - - runTask(() => { - this.createApplication(); - - this.router.map(function () { - this.route('user', { resetNamespace: true }, function () { - this.route('profile'); - this.route('edit'); - }); - }); - - // Emulate a long-running unscheduled async operation. - let resolveLater = () => - new RSVP.Promise((resolve) => { - /* - * The wait() helper has a 10ms tick. We should resolve() after - * at least one tick to test whether wait() held off while the - * async router was still loading. 20ms should be enough. - */ - later(resolve, { firstName: 'Tom' }, 20); - }); - - this.add( - 'route:user', - Route.extend({ - model() { - return resolveLater(); - }, - }) - ); - - this.add( - 'route:user.profile', - Route.extend({ - beforeModel() { - return resolveLater().then(() => { - return expectDeprecation(() => { - return this.transitionTo('user.edit'); - }, /Calling transitionTo on a route is deprecated/); - }); - }, - }) - ); - - this.application.setupForTesting(); - }); - - this.application.injectTestHelpers(); - runTask(() => { - this.application.advanceReadiness(); - }); - } - - [`@test currentRouteName for '/user'`](assert) { - assert.expect(4); - - let { - application: { testHelpers }, - } = this; - return testHelpers.visit('/user').then(() => { - assert.equal(testHelpers.currentRouteName(), 'user.index', `should equal 'user.index'.`); - assert.equal(testHelpers.currentPath(), 'user.index', `should equal 'user.index'.`); - assert.equal(testHelpers.currentURL(), '/user', `should equal '/user'.`); - let userRoute = this.applicationInstance.lookup('route:user'); - assert.equal(userRoute.get('controller.model.firstName'), 'Tom', `should equal 'Tom'.`); - }); - } - - [`@test currentRouteName for '/user/profile'`](assert) { - assert.expect(5); - - let { - application: { testHelpers }, - } = this; - return testHelpers.visit('/user/profile').then(() => { - assert.equal(testHelpers.currentRouteName(), 'user.edit', `should equal 'user.edit'.`); - assert.equal(testHelpers.currentPath(), 'user.edit', `should equal 'user.edit'.`); - assert.equal(testHelpers.currentURL(), '/user/edit', `should equal '/user/edit'.`); - let userRoute = this.applicationInstance.lookup('route:user'); - assert.equal(userRoute.get('controller.model.firstName'), 'Tom', `should equal 'Tom'.`); - }); - } - } - ); - - moduleFor( - 'ember-testing: can override built-in helpers', - class extends HelpersTestCase { - constructor() { - super(); - runTask(() => { - this.createApplication(); - this.application.setupForTesting(); - }); - this._originalVisitHelper = Test._helpers.visit; - this._originalFindHelper = Test._helpers.find; - } - - teardown() { - Test._helpers.visit = this._originalVisitHelper; - Test._helpers.find = this._originalFindHelper; - super.teardown(); - } - - [`@test can override visit helper`](assert) { - assert.expect(1); - - Test.registerHelper('visit', () => { - assert.ok(true, 'custom visit helper was called'); - }); - - this.application.injectTestHelpers(); - - return this.application.testHelpers.visit(); - } - - [`@test can override find helper`](assert) { - assert.expect(1); - - Test.registerHelper('find', () => { - assert.ok(true, 'custom find helper was called'); - - return ['not empty array']; - }); - - this.application.injectTestHelpers(); - - return this.application.testHelpers.findWithAssert('.who-cares'); - } - } - ); -} diff --git a/packages/ember-testing/tests/integration_test.js b/packages/ember-testing/tests/integration_test.js deleted file mode 100644 index 0256518968c..00000000000 --- a/packages/ember-testing/tests/integration_test.js +++ /dev/null @@ -1,106 +0,0 @@ -import { moduleFor, AutobootApplicationTestCase, runTask } from 'internal-test-helpers'; -import Test from '../lib/test'; - -import { A as emberA } from '@ember/-internals/runtime'; -import { Route } from '@ember/-internals/routing'; -import { jQueryDisabled } from '@ember/-internals/views'; - -moduleFor( - 'ember-testing Integration tests of acceptance', - class extends AutobootApplicationTestCase { - constructor() { - super(); - - this.modelContent = []; - this._originalAdapter = Test.adapter; - - runTask(() => { - this.createApplication(); - - this.addTemplate( - 'people', - ` -
- {{#each @model as |person|}} -
{{person.firstName}}
- {{/each}} -
- ` - ); - - this.router.map(function () { - this.route('people', { path: '/' }); - }); - - this.add( - 'route:people', - Route.extend({ - model: () => this.modelContent, - }) - ); - - this.application.setupForTesting(); - }); - - runTask(() => { - this.application.reset(); - }); - - this.application.injectTestHelpers(); - } - - teardown() { - super.teardown(); - Test.adapter = this._originalAdapter; - } - - [`@test template is bound to empty array of people`](assert) { - if (!jQueryDisabled) { - runTask(() => this.application.advanceReadiness()); - window.visit('/').then(() => { - let rows = window.find('.name').length; - assert.equal(rows, 0, 'successfully stubbed an empty array of people'); - }); - } else { - runTask(() => this.application.advanceReadiness()); - window.visit('/').then(() => { - expectAssertion( - () => window.find('.name'), - 'If jQuery is disabled, please import and use helpers from @ember/test-helpers [https://github.com/emberjs/ember-test-helpers]. Note: `find` is not an available helper.' - ); - }); - } - } - - [`@test template is bound to array of 2 people`](assert) { - if (!jQueryDisabled) { - this.modelContent = emberA([]); - this.modelContent.pushObject({ firstName: 'x' }); - this.modelContent.pushObject({ firstName: 'y' }); - - runTask(() => this.application.advanceReadiness()); - window.visit('/').then(() => { - let rows = window.find('.name').length; - assert.equal(rows, 2, 'successfully stubbed a non empty array of people'); - }); - } else { - assert.expect(0); - } - } - - [`@test 'visit' can be called without advanceReadiness.`](assert) { - if (!jQueryDisabled) { - window.visit('/').then(() => { - let rows = window.find('.name').length; - assert.equal( - rows, - 0, - 'stubbed an empty array of people without calling advanceReadiness.' - ); - }); - } else { - assert.expect(0); - } - } - } -); diff --git a/tests/docs/expected.js b/tests/docs/expected.js index efbb3376ffc..4bda343c9a2 100644 --- a/tests/docs/expected.js +++ b/tests/docs/expected.js @@ -217,14 +217,12 @@ module.exports = { 'extend', 'factoryFor', 'fallback', - 'fillIn', 'filter', 'filterBy', 'finally', 'find', 'findBy', 'findModel', - 'findWithAssert', 'firstObject', 'flushWatchers', 'fn', @@ -331,7 +329,6 @@ module.exports = { 'join', 'jQuery', 'keyDown', - 'keyEvent', 'keyPress', 'keyUp', 'knownForType', @@ -543,7 +540,6 @@ module.exports = { 'teardownViews', 'templateName', 'templateOnly', - 'testCheckboxClick', 'testHelpers', 'testing', 'textarea', @@ -561,7 +557,6 @@ module.exports = { 'translateToContainerFullname', 'trigger', 'triggerAction', - 'triggerEvent', 'trySet', 'type', 'typeInjection', diff --git a/yarn.lock b/yarn.lock index 872fa81464b..f3d896edc08 100644 --- a/yarn.lock +++ b/yarn.lock @@ -955,6 +955,8 @@ version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.12.1.tgz#07640f28867ed16f9511c99c888291f560921cfa" integrity sha512-Zaeq10naAsuHo7heQvyV0ptj4dlZJwZgNAtBYBnu5nNKJoW62m0zKcIEyVECrUKErkUkg6ajMy4ZfnVZciSBhg== + dependencies: + "@babel/helper-plugin-utils" "^7.10.4" "@babel/plugin-transform-for-of@^7.9.0": version "7.9.0" @@ -5232,6 +5234,9 @@ find-babel-config@^1.1.0: version "1.2.0" resolved "https://registry.yarnpkg.com/find-babel-config/-/find-babel-config-1.2.0.tgz#a9b7b317eb5b9860cda9d54740a8c8337a2283a2" integrity sha512-jB2CHJeqy6a820ssiqwrKMeyC6nNdmrcgkKWJWmpoxpE8RKciYJXCcXRq1h2AzCo5I5BJeN2tkGEO3hLTuePRA== + dependencies: + json5 "^0.5.1" + path-exists "^3.0.0" find-index@^1.1.0: version "1.1.0" @@ -6601,11 +6606,6 @@ json-stringify-safe@~5.0.0: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" -json5@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - integrity sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= - json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"