Git Product home page Git Product logo

ember-native-dom-helpers's Introduction

Build Status

IMPORTANT: You probably don't need this addon.

In Ember, since ember-(cli-)qunit 3.X (around late 2017) there is a new testing API that already provides almost identical test helpers from the ones in this addon.

This addon was used as an experiment that helped bikeshed the API of the helpers that are now part of default testing API, like click, tap, fillIn and others.

The only two helpers in this addon that are not part of the default set of helpers that ship with Ember's test harness are scrollTo(selectorOrHTMLElement, x, y) and selectFiles(selectorOrHTMLElement, files = []).

Unless you want to use those, you are better served using the helpers provided by @ember/test-helpers.

ember-native-dom-helpers

Test helpers for integration tests that mimic the behaviour of the acceptance test helpers provided by Ember.

Use this addon as a way to start the gradual migration towards the future "testing unification" RFC, which proposes only native DOM.

See the Grand Testing Unification RFC

Status: (Pre) 1.0, although we have a good idea about what the needs are for test helpers, we are working through a few points on what changes are needed when using only standard DOM APIs (i.e. without jQuery).

Usage

Integration tests

import { click, fillIn, find, findAll, keyEvent, triggerEvent } from 'ember-native-dom-helpers';

moduleForComponent('my-component', 'Integration | Component | my-component', {
  integration: true
});


test('I can interact with my component', async function(assert) {
  this.render(hbs```
    {{my-component}}
  ```);

  await fillIn('.some-input', 'some text');
  await click('.main-button');
  await keyEvent('.other-input', 'keyup', 40); // down arrow
  await triggerEvent('.some-drop-area', 'mouseenter');

  assert.ok(find('.result-of-event-happened'));
  assert.equal(findAll('.result-list-item').length, 3);
})

Acceptance tests

You can use the exact same helpers for your acceptance tests. All interaction helpers like click, fillIn, et al., return a promise that fullfils when "the world has settled" (that is, there are no pending requests or promises, and the runloop has been drained), which is what the andThen acceptance helper used to do. However, this helper can now be replaced by the async/await syntax in ES2017, yielding easier-to-read tests:

import { visit, click, find, fillIn } from 'ember-native-dom-helpers';

moduleForAcceptance('Acceptance | Sign up');

test('Usage awaiting the world to settle', async function(assert) {
  await visit('/sign-up');

  await fillIn('.first-name', 'Chuck');
  await fillIn('.last-name', 'Berry');
  await click('.submit-btn');

  assert.ok(find('.welcome-msg'), 'There is a welcome banner');
  assert.equal(find('.welcome-msg-name'), 'Chuck');
});

Advantages compared with this.$(selector).click()

The main advantages are:

  • Fires native events: In Ember, when adding events with the onclick={{action "foo"}} syntax, dispatching jQuery events leads to the action being called twice. Additionally, there are subtle differences between jQuery and Native events that can bite you. Firing native events fixes that problem, but they are very verbose and there are browser incompatibilities. This addon makes firing native events a no-brainer.

  • Runloop aware: These helpers automatically spawn a runloop, so you don't need to wrap every interaction with Ember.run(() => /* interact with element */ );.

  • wait by default: All the helpers return the wait() promise, making it possible to wait for asynchronous side-effects with async/await. (Note that for using async/await in browsers without native support you must install ember-maybe-import-regenerator).

    test('some test', async function(assert) {
      this.render(hbs```{{my-component}}```);
    
      await click('.my-button');
    
      assert.ok('something happened');
    });
  • More realistic behaviour: When a user clicks on an element, click is not the only event fired. In a real click, the sequence of events is mousedown, focus, mouseup, click. When a user fills in an input the sequence of events is focus, <mutate-value>, input, and change. The helpers provided by this addon fire those events in the right order, simulating more closely how a real user would interact with the page.

Standard DOM elements returned using a find/findAll helpers

  • The find helper uses document.querySelector and will return a single HTMLElement or null.
  • The findAll helper uses document.querySelectorAll and returns an Array with zero or more elements.
  • Both find and findAll helpers query the DOM within #ember-testing.
  • To use a different value from your config/environment.js settings, add to tests/test-helper.js
import { settings } from 'ember-native-dom-helpers';
import config from '../config/environment';
const { APP: { rootElement } } = config;

settings.rootElement = rootElement || settings.rootElement;

What if I prefer jQuery collections over native DOM?

Fear not. If you prefer to use jQuery, just wrap the result and do your thing:

assert.equal($(find('.my-class')).attr('aria-owns'), '#id123')

Testing an unsettled world

There is one new helper in this addon that enables some testing patterns that weren't previously easy to perform using traditional methods.

Since the andThen helper waits for the app to settle (no pending requests or promises), and every integration test interaction is wrapped in Ember.run, there is no easy way to test transient state, like loading substates or the state of a component, while some promise is pending, without an awkward setup of timeouts.

Now, however, thanks to explicit usage of promises and the waitUntil helper, you can perform assertions on unsettled states:

import { visit, click, find, fillIn, waitUntil, currentURL } from 'ember-native-dom-helpers';

moduleForAcceptance('Acceptance | Sign up');

test('Usage awaiting the world to settle', async function(assert) {
  await visit('/login');

  await fillIn('.email', '[email protected]');
  await fillIn('.password', 'goldeneye');
  let promise = click('.submit-btn');

  // We wait until the loading substate, that takes 200ms to appear, is displayed
  await waitUntil(() => find('.substate-spinner'));
  assert.equal(find('.loading-substate-header').textContent.trim(), 'Loading mission. Please wait, Mr. Bond');

  await promise; // now we wait until the dashboard is fully loaded
  assert.equal(currentURL(), '/dashboard');
  assert.equal(find('.section-header').textContent, 'Main dashboard');
});

I WANT IT NOW, IS THERE A SHORTCUT?

Yes, there is a codemod that will help you transform your test suite to this new style "automatically". Check https://github.com/simonihmig/ember-native-dom-helpers-codemod.

The codemod can't make a perfect conversion, but it will do most of the work for you.

Helpers

  • click(selectorOrHTMLElement, contextHTMLElement, eventOptions)
  • tap(selectorOrHTMLElement, eventOptions)
  • fillIn(selectorOrHTMLElement, text)
  • find(selector, contextHTMLElement) (query for an element in test DOM, #ember-testing)
  • findAll(selector, contextHTMLElement) (query for elements in test DOM, #ember-testing)
  • findWithAssert(selector, contextHTMLElement) (same as find, but raises an Error if no result)
  • keyEvent(selectorOrHTMLElement, type, keyCode, modifiers) (type being keydown, keyup or keypress, modifiers being object with { ctrlKey: false, altKey: false, shiftKey: false, metaKey: false })
  • triggerEvent(selectorOrHTMLElement, type, options)
  • focus(selectorOrHTMLElement)
  • blur(selectorOrHTMLElement)
  • scrollTo(selectorOrHTMLElement, x, y)
  • selectFiles(selectorOrHTMLElement, files = []) (selects the file(s)/Blob(s) to the given input[type=file]. Example
  • visit(url) (only available in acceptance. Raises an error in integration.)
  • waitUntil(function, options) (Polls the page until the given callback returns a truthy value, or timesout after 1s)
  • waitFor(selector, options) (Convenience for the most common use-case of waitUntil. It polls the page until the element with the given selector is on the page, or timesout after 1s. It accepts a count: 3 option to await a specific number of matches.)
  • currentURL() Identical to the one provided by Ember.
  • currentPath() Identical to the one provided by Ember.
  • currentRouteName() Identical to the one provided by Ember.

Notes of tap

In order for tap to work, your browser has to support touch events. Desktop Chrome and Firefox have touch events disabled unless the device emulation mode is on. To enable touch events in your CI, you need to configure testem like the testem.js file on this repo.

ember-native-dom-helpers's People

Contributors

2hu12 avatar acorncom avatar alexander-alvarez avatar brandynbennett avatar cibernox avatar deepflame avatar ember-tomster avatar jacefarm avatar jrowlingson avatar locks avatar nlfurniss avatar pixelhandler avatar ro0gr avatar robbiethewagner avatar rwjblue avatar sergeastapov avatar simonihmig avatar turbo87 avatar villander avatar webark avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ember-native-dom-helpers's Issues

Implement `current**` helpers?

Should this repo "shim" the currentPath, currentRouteName and currentURL helpers the same way we shim the visit helper (and throw in integration)?

This would allow people to import those helpers and remove them from the list of globals of the jshintrc/eslintrc.

Support `:contains()` pseudoselector

In jQuery land this pseudoselector is used frequently. It is not a real selector supported by document.querySelector or document.querySelectorAll, just some addition added by jQuery that became popular.

I use it frequently to do things like

typeInSearch('tal');
assert.ok($('.power-select-option:contains("Italy")').hasClass('highlighted'), 'The first marching result is highlighted');

I leave this open so people can decide (:+1:/:-1:) if we should support this at all, and if we do, with what approach (leave comment):

  • A new findByContent('content', optionalButRecomendableSelectorToNarrowTheSearch)
    (e.g: findByContent('Italy', '.power-select-option')

  • Make find/findAll support this psudoselector like jquery does:
    (e.g: find('.power-select-option:contains("Italy")'))

With either API the implementation is quite simple. jQuery basically removes the /:contains(.*)/ part, uses the rest of the selector, and then filters the results by checking if the textContent.indexOf($1) > -1.

Issues Setting Up Cloned Project

yarn install fails (so I fell back on npm install)

error An unexpected error occurred: "https://registry.yarnpkg.com/broccoli-babel-transpiler-6.0.0-alpha.3.tgz: Request failed \"404 Not Found\"".
info If you think this is a bug, please open a bug report with the information provided in "ember-native-dom-helpers/yarn-error.log".

ember s fails

Could not require 'ember-cli-build.js': Block-scoped declarations (let, const, function, class) not yet supported outside strict mode
SyntaxError: Could not require 'ember-cli-build.js': Block-scoped declarations (let, const, function, class) not yet supported outside strict mode
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:373:25)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
    at module.exports (ember-native-dom-helpers/node_modules/ember-cli/lib/utilities/find-build-file.js:18:17)
    at Builder.setupBroccoliBuilder (ember-native-dom-helpers/node_modules/ember-cli/lib/models/builder.js:50:21)
    at new Builder (ember-native-dom-helpers/node_modules/ember-cli/lib/models/builder.js:30:10)

Requirements to use this package?

What are the requirements to use this package? I've tried with a brand new ember new app and I get this exception:

Died on test #1     at Module.callback (http://localhost:7357/assets/tests.js:145:24)
    at Module.exports (http://localhost:7357/assets/vendor.js:119:32)
    at requireModule (http://localhost:7357/assets/vendor.js:34:18)
    at TestLoader.require (http://localhost:7357/assets/test-support.js:7672:7)
    at TestLoader.loadModules (http://localhost:7357/assets/test-support.js:7664:14)
    at Function.TestLoader.load (http://localhost:7357/assets/test-support.js:7694:22)
    at http://localhost:7357/assets/test-support.js:7577:18: regeneratorRuntime is not defined@ 24 ms
Expected: 	
null
Message: 	Diff suppressed as the expected and actual results have an equivalent serialization
Source: 	
ReferenceError: regeneratorRuntime is not defined
    at Object.callee$0$0 (http://localhost:7357/assets/tests.js:146:5)
    at runTest (http://localhost:7357/assets/test-support.js:3852:30)
    at Test.run (http://localhost:7357/assets/test-support.js:3838:6)
    at http://localhost:7357/assets/test-support.js:4030:12
    at Object.advance (http://localhost:7357/assets/test-support.js:3515:26)
    at begin (http://localhost:7357/assets/test-support.js:5206:20)
    at http://localhost:7357/assets/test-support.js:4400:6

I'm assuming that it's because ember-cli 2.12.x doesn't have the new beta version of babel 6?

If there is documentation somewhere on this, I'm happy to create a PR to more clearly state what the requirements are to use this package in the README.md or another file.

Steps:

ember new new-test-app

ember-cli: 2.12.2
node: 4.8.2
os: darwin x64

ember install ember-native-dom-helpers
ember g component foo-bar
ember t -s
import { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
import { click } from 'ember-native-dom-helpers';

moduleForComponent('foo-bar', 'Integration | Component | foo bar', {
  integration: true
});

test('it works with endh', async function(assert) {
  this.render(hbs`{{foo-bar}}`);
  await click('button');
});

Doesn't Work With IE11

Running tests with IE11 I see the following error:

screen shot 2017-09-27 at 2 35 58 pm

The problem seems to be that the regenerator runtime assumes that Promise is natively defined by the browser, which is sadly not the case in IE11.

Different rootElement than in jQuery based tests

Not sure if this is an issue or designed like that by intention, but at least it leads to some CSS selectors not working the same as in jQuery-based tests.

When rendering a component in integration tests, the resulting DOM will look like this:

<div id="ember-testing" class="ember-application">
  <div id="ember139" class="ember-view">
    <div id="ember187" class="my-component"></div>
  </div>
</div>

For find the rootElement is explicitly set to #ember-testing, while for this.$() the equivalent is the #ember139 view. This results in the following incompatible difference when using the :first-child selector:

find(':first-child') -> #ember139 (the wrapping view)
this.$(':first-child') -> #ember187 (the actual component under test)

So when migrating, one would have to rewrite all those selectors. I would assume that it should actually behave the same, at least that would make migrating more straightforward. (I actually used this selector in ember-bootstrap quite often)

Would you consider this a bug? If not it should probably be documented. Also relates to #51, could make an automatic migration if this is not considered a bug and will stay like this...

find && contains text helper

Would it be useful to have a method that returns the element that contains text, similar to jQuery? Some combination of querySelectorAll and Regex. I can imagine with a list of elements that one might not know at the outset what index the item they are finding is at. Any thoughts?

Simulating Cmd + Delete on Acceptance test

I am trying to do a control + delete on one of my elements. I queried it on SO. My code is not deleting the element:

test('multi-press', async function(assert){
await click();
await triggerEvent(, "keydown", {ctrlKey: true, keyCode: 46});
await triggerEvent(, "keyup", {ctrlKey: false, keyCode: 46});}

Please suggest!

Behaviour of `find` when no element matches the result

At the moment the logic is that if the helper finds only one element matching the selector, it will return the Node but if there is more it will returns a NodeList. So far so good.

But when there is no results, right now it returns an empty NodeList. I wonder if this is expected or it should return undefined/null in that case.

/cc @rwjblue @pixelhandler What do you think it's better/more intuitive?

Update `waitUntil` signature to support selectors.

I find that the most common thing I do in a waitUntil is something like:

await waitUntil(() => find('.some-selector'))

I am proposing that we allow the following:

await waitUntil('.some-selector');

This would work by detecting a string argument, and expanding it into the () => find(selector)) version.

Thoughts?

fillIn should fire onKeyUp and onKeyDown events

Hey

Current implementation of fillIn helper doesn't trigger onKeyUp and onKeyDown events. This is how users actually interact with forms, and if there is logic implemented to run after those events, fillIn can't be used.

I would like to suggest, that fillIn is extended to do the following:

  1. First, clean up the input entirely, run input and change events on this state
  2. Write one character at a time, run onKeyUp and onKeyDown events as needed
  3. Only after the entire content was written, run input and change events on the entire written input

Would you accept an MR with those changes?

EDIT

Since that would be backwards incompatible for people that count number of called events in tests, a new function called writeIn with this behavior could be added. fillIn would simulate copy-paste vehavior, and writeIn would more closely match user writing down.

Allow to pass `HTMLElement`s to helpers (click, tap, fillIn...)

Right now helpers expect a selector as first argument that they use to query the DOM and get the HTMLElements. It would be useful if they could receive the HTMLElement itself.

Result:

let input = find('.my-text-input');
click(input);
fillIn(input);
keyEvent(input, 'keydown', 13);

👍/👎

keypress key vs keyCode inconsistency across browsers

This works in Chrome/Firefox but in IE11 and phantomJS:

    find('input').addEventListener('keypress', e => {
      assert.equal(e.keyCode, 13);
    });

    triggerEvent(find('input'), 'keypress', {
      key: 13,
      // keyCode: 13 results to NaN
    });

works in IE11 but not in Chrome:

    find('input').addEventListener('keypress', e => {
      assert.equal(e.keyCode, 13);
    });

    triggerEvent(find('input'), 'keypress', {
      keyCode: 13 // <=
      // key: 13 results to undefined
    });

In case of IE this assert fails with the following qunit message:

Expected: 13
Result: undefined

also there are failures in phantomJS I think it's similar to IE.

I can see several tricks around keyCode in triggerEvent but I don't 100% follow what happens here yet.
One thing I'm interested in is that this keyPress stuff happens only for the "happy path" when new KeyboardEvent(type, eventOpts); succeeds.

Here is a demo app with a reproduction

Support drag event

I am trying to have a test that drags an element around and cannot find any solution using ember-native-dom-helpers. Though this is not a common case, I think ember-native-dom-helpers should support this operation.

Focus event ordering is incorrect.

Demo: https://output.jsbin.com/vilumo

    let element = document.createElement('input');

    ['mousedown', 'mouseup', 'click', 'focus', 'focusin'].forEach(type => {
      element.addEventListener(type, () => {
        console.log('event:', type);
      });
    });

    document.body.appendChild(element);

Tested on MS Edge, FireFox, Chrome, and Safari the output is:

event: mousedown
event: focus
event: focusin
event: mouseup
event: click

However, our utility function fires them as mousedown, focusin, focus, mouseup, click. I noticed this while migrating the implementation to @ember/test-helpers and writing unit tests for the behavior of click.

Poll: New `findByText()` helper?

After migrating a few codebases to async/await and ember-native-dom-helpers, the single most annoying pattern to transform is selectors that use the :contains("text") pseudoselector from jQuery.

I proposed supporting a subset of sizzle pseudoselectors in #32, but I kind of agree that we shouldn't, because even those selectors are going to be deprecated in jQuery itself.

The question is wether or not we want to add some sort of utility to make finding elements with a certain text easier. A tentative method and signature could be findByText('.selector', 'text', context?).

Now vs this helper:

findAll('h1').find((el) => el.textContent.includes('Tomster')) vs findByText('h1', 'Tomster')

The pros are obviously, ergonomics.
The const are one more helper to learn and arguably by making it more convenient we are encouraging a testing pattern that many people see as dubious or harmful (test selectors could be a better)

Babel 6 upgrade?

Hello,

We are using your package on an enterprise-level web application and I was wondering... why was this package upgraded to use a beta version of Babel 6 and released as a patch semversion?

I would think that using an unstable, unofficial beta version would warrant a major (or even minor) version bump.

Also, was there a reason it was added to dependencies in package.json rather than to devDependencies?

triggerEvent(form, 'reset') event does not seem to work

I have a test that looks like

it('resets the form', async function(assert) {
  this.set('originalName', 'Sam')

  this.render(hbs`
    <form>
      {{my-reset-aware-input
        initialValue=originalName
        change=(action (mut name))}}
    </form>
  `)

  const input = this.$('input')[0]
  
  await fillIn(input, 'value', 'Not Sam')

  assert.equal(this.get('originalName'), 'Sam', 'initialValue ignores change')
  assert.equal(this.get('name'), 'Not Sam', 'input fires change action')

  await triggerEvent(input.form, 'reset')

  assert.equal(input.value, 'Sam', 'resets to initialValue')
})

But the reset doesn't seem to fire.

The test works if I change that line to

Ember.run(this.$(input.form), 'trigger', 'reset') // fire the event

or to

Ember.run(input.form, 'reset') // reset the form, which fires the event

Support for sizzle-selectors

I've decided to unify #26 and #23 into this single issue.

I've tried to adapt the test suites of ember-basic-dropdown, ember-power-select and ember-calendar to use this library and I've found a few places where this library cannot be a drop-in replacement because CSS3 selectors are more limited than those availables in jquery (which uses the sizzle selector engine)

Those cases include:

  • $('.option:contains("Portugal")').click() !== click('.option:contains("Portugal")')
  • $optionsRoot.find('> .options-group-name') !== find('> .options-group-name', optionsRoot)
  • $('.select-option:eq(2)') !== find('.select-option:eq(2)') (although === to findAll('.select-option')[2]

Other cases I don't use but I also know that are not supported:

  • :even/:odd
  • [attr!=value]
  • :has(subSelector)

The question is whether or not we want to stick to basic CSS3 selectors only or allow the superset that sizzles supports to ease the transition from jquery-based selectors. Sizzle would only be included in the test-support tree, so it would not impact the size of the app itself.
The returned results would still be native HTMLElements or NodeLists.

Follow up on focus event helper function

@rwjblue there is one other point to chat about at some point too, the focus method in the existing test helpers has an issue with Firefox and focus on window or not. I was able to resolve that in this library as I added test running via Chrome, Firefox on Travis as well.

See…

https://github.com/cibernox/ember-native-dom-helpers/blob/master/addon-test-support/helpers.js#L11-L31

vs.

https://github.com/emberjs/ember.js/blob/7819409b7b6559e9fc0300a29e66a16356fb67a7/packages/ember-testing/lib/events.js#L8-L27

Return JS array from findAll()

According to https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll the querySelectorAll() method used by findAll() returns "a non-live NodeList of element objects". A NodeList unfortunately is missing some of the methods on the Array prototype which makes it hard to do something like findAll('.foo').map(element => element.textContent).

I would like to propose to automatically convert the NodeList to an Array within the findAll() function to improve the ergonomics of using it.

Use typescript

The more I use VSCode the more I value the little helps that the type definitions (even those defined externally like momentjs / lodash).

Although Ember's flexibility limit the effectiveness of types, this barely relies in Ember. Many of the arguments and return types (e.g NodeList) can be known in advance.

It is possible to develop addons in typescript already? Shall we?

el.contenteditable check that we use in isFocusable and in focus() need a revamp

We do use el.contenteditable to check if we can focus an element and when we issue focus action. The issue with that is, that contenteditable always has a value, and this value is inherit (https://www.w3.org/TR/html5/editing.html#sequential-focus-navigation-and-the-tabindex-attribute). But for the real element to be focused, it should have contenteditable === true.

And as a separate thing, it's not enough just to fix that contenteditable === true, we should also add a check for the existence of tabindex.

I am kinda guilty of just copying this code without truly testing it through :)

https://github.com/cibernox/ember-native-dom-helpers/blob/master/addon-test-support/-private/is-focusable.js#L9

Implement `pauseTest` and `resumeTest` helpers

This would be nice for debugging, and consistent with the acceptance test APIs. What do you think?

Implementation can be something like

await wait();
Ember.run.begin();
await wait();

Simulate Ctrl + Delete in Acceptance tests

I am trying to do a control + delete on one of my elements. I queried it on SO. My code is not deleting the element:

test('multi-press', async function(assert){
await click();
await triggerEvent(, "keydown", {ctrlKey: true, keyCode: 46});
await triggerEvent(, "keyup", {ctrlKey: false, keyCode: 46});}

Please suggest! Help Needed!

Flaky tests for focusout

I am not sure what this all means, but given a component that listens for focusout I get these results:

  • this.$('input').trigger('focusout') always works
  • this.$('input').trigger('blur') always works
  • triggerEvent('input', 'focusout') never works
  • triggerEvent('input', 'blur') always works
  • blur('input') sometimes works

I created a reproduction repo here: https://github.com/simonihmig/ember-native-helpers-demo/blob/master/tests/integration/components/foo-bar-test.js

Regarding the blur flakiness: it seems it does work when having a fresh test run, or pressing enter on ember t -s:

image

As soon as I reload the Chrome browser window, the test fails:

image

Seems related to the browser-has-focus handling in blur.js: as soon as it hits this line (https://github.com/cibernox/ember-native-dom-helpers/blob/master/addon-test-support/blur.js#L32) it seems to work. I patched that helper locally to always call fireEvent and not el.blur(), and then it seems to work just fine for me.

Don't know if that makes sense? Also why triggerEvent('input', 'focusout') does not work at all...

Clicking on TAB and SHIFT+TAB should also fire a blur event

When firing a keyboard TAB event (eg. press TAB button). Browsers behavior is, to throw a keyboard event and also, blur the current document.activeElement.

Currently, we are not doing that in ember-native-dom-helpers. It caused a bit of confusion to understand what's going on, so I think it might be worth to add it as a default behavior.

Thoughts?

Add a `pressKey` helper?

How about adding a pressKey helper which fires keydown, keypress and then keyup?

EDIT: Updated helper name.

RFC: add `text` helper

Just a convenience method:

find('[data-test-product-banner]').textContent.trim() => text('[data-test-product-banner]')

I'm cool if you don't want it.

Add a codemod

Has anybody thought/worked on a codemod already to automatically refactor jQuery based tests?

Would like to get rid off jQuery from ember-bootstrap (@cibernox thanks for the awesome blog post btw!), but refactoring the test suite manually is probably the most work.

Certainly it would be next to impossible to cover all possible cases of chainable jQuery code, but at least for the 90% of very common cases (assertions based on .length, .text(), .hasClass()) there could be some solution that relieves us at least from most of the work.

Have not worked with AST before, but would be a good use case to learn something new, unless there is already some work going into that direction?

selectFiles Seems Broken in Chrome Canary

Given:

  await selectFiles(
    '.some-selector',
    [
      new Blob(['test-test'], {
        name: 'foo.jpg',
        type: 'image/jpeg'
      }),
    ]
  );

I see the following error message in Chrome Canary (v62):

screen shot 2017-08-08 at 1 04 49 pm

Support clicking (querying) svg element

Currently, I get the following error:

Error: Failed to execute 'querySelector' on 'Document': '#ember-testing [object SVGPathElement]' is not a valid selector.

keyEvent does not seem to trigger events in tests using input helper

Hello, thanks for creating this package!

Currently, using keyEvent(), particularly for ENTER or ESC keycodes (13 and 27 respectively), on an {{input}} element in a component while running a phantomJS test does not fire the event.

Take the following test:

test('test does not work', function(assert) {
  this.set('escPressed', () => {
    // never called
    console.log('keyup called!');
    assert.ok(true);
  });
  this.render(hbs`{{input escape-press=(action escPressed)}}`);
  let input = find('input');
  focus(input);
  keyEvent(input, 'keyup', 27); // esc
});

After doing a bit of research, it appears that when creating events using KeyboardEvents or KeyEvents in the fire-event.js, PhantomJS assigns all keyCode property on events to 0, for reasons I'm not too sure of. As a result, Ember is not able to correctly detect the pressed key because keyCode is being set to 0 by PhantomJS.

A workaround was to create an event in a legacy way. For instance, instead of using keyEvent, triggering an event like this works.

   let evt = document.createEvent('CustomEvent');
   evt.initEvent('keyup', true, false);
   evt.keyCode = 27;
   input.dispatchEvent(evt);

This may be something that phantomjs may be able to fix in its package, but I was thinking it wouldn't be unreasonable for this package to support this?

Clicking certain coordinates within an element

I'd like to be able to do something like click('.my-map', { xOffset: 5, yOffset: 5 }), since there isn't usually anything to select on to click on a map if you are doing testing that requires drawing on the map, and not clicking existing objects.

Migrate `find` / `findAll` to wait for selectors.

I am working up updates to the testing RFC (thanks to this library pushing things forward), and am beginning to incorporate the changes suggested by @machty in emberjs/rfcs#119 (comment).

The crux of his proposal is that we make find and findAll (and therefore all the other helpers that use them to sanitize selector inputs) wait for the selector to return a match. It would wait until either the selector is present or wait() completes (whichever happens first). The change to consumers are fairly small (in most cases apps wouldn't even be aware of the distinction), but the impact has the potential to be quite large for many edge cases.

Conveniently @machty has already done a ton of work in this area (custom find helper implemented in ember-concurrency), that we can take advantage of.

Again, to reiterate what I mentioned above, the 90% use case for folks does not change (other than making find an async operation).

Support `:eq(NUMBER)` pseudoselector

Another pseudoselector in jQuery that is pretty useful is the :eq(N). It returns the Nth occurence of a selector in the dom.

For some usages like assert.equal($('.user:eq(2)').text().trim(), 'James') it can be easily replaced by assert.equal(findAll('.user')[2].textContent.trim(), 'James').

However, this doesn't work for selectors like click('.profile-link:eq(2)').

An scape valve would be to allow helpers to receive HTMLElements instead of selectors, and do click(findAll('.profile-link')[0]).
That is my next issue.

Avoid using MouseEvent.initMouseEvent

In https://github.com/cibernox/ember-native-dom-helpers/blob/master/addon-test-support/helpers.js#L69
we use MouseEvent.initMouseEvent() which is deprecated in favor of the plain constructor: https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/MouseEvent

Might have issues down the line.

Also curious about the undocumented +1, +5, +95 here https://github.com/cibernox/ember-native-dom-helpers/blob/master/addon-test-support/helpers.js#L42

I can change out to use the constructors when I get the chance

Clicking on disabled input checkbox modify checked value

I create a component my-input-component.hbs:

<input type="checkbox"
   checked={{checked}}
   disabled={{disabled}}>

and I add a integration test:

import { click, find } from 'ember-native-dom-helpers';
//...
test('disabled state', async function(assert) {
   await render(hbs`{{my-input-component disabled=true checked=false}}`);
   assert.notOk(find('input[type="checkbox"]').checked);

   await click('input[type="checkbox"]');
   assert.notOk(find('input[type="checkbox"]').checked);
});

The second assert.notOk fails, find('input[type="checkbox"]').checked returns true.

If I replace click helper by something like that, it's working:

Ember.run(() => document.querySelector('input[type="checkbox"]').click());

Do you have any idea about why click has this behaviour? Thanks.

`this.$()` equivalent?

Is it possible? Should find(null, this) work? Or is all this support lost in the new test helper world?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.