Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to send keypress events to component element #312

Open
kriswill opened this issue May 19, 2017 · 2 comments
Open

Ability to send keypress events to component element #312

kriswill opened this issue May 19, 2017 · 2 comments

Comments

@kriswill
Copy link

Hi, I have the need to drive an ember-power-select component during acceptance tests, to simulate it's fuzzy searching capabilities. Using the triggerable property is very cumbersome, and it's input element doesn't respond to simple fillable value changes.

Ideally, I would like to do something like this:

modal: {
    scope: '[data-test-modal]',
    name: fillable('[data-test-name] input'),
    clickAddEmails: clickable('[data-test-add-email]'),
    addEmailInput: keypress( '.ember-power-select-trigger-multiple-input'),
    emails: collection({
        itemScope: '.ember-power-select-option',
        item: {
            email: text(),
            click: clickable()
        }
    }),
    cancel: clickable('[data-test-cancel]'),
    submit: clickable('[data-test-submit]')
},

from the acceptance test:

it('can add an entry, with emails', () => {
    page.visit();
    andThen(() => {
        page.clickAddEntry();
    });
    const modal = page.modal;
    modal.name('Acceptance Test Entry');
    modal.clickAddEmails();
    andThen(() => {
        modal.addEmailInput('@gmail');
        const email1 = modal.emails(0);
    })
});

using the keypress property would send keypress events to the element.

I could always hack around it with jQuery, but a declarative property on the page object would be a lot cleaner.

P.S., I tried making my own property function using extend, but had trouble using getCurrentContext, which is private.

@mistahenry
Copy link

mistahenry commented Jan 21, 2019

ember-power-select provides its own test helpers that make interacting with it possible from page-objects. Here is my current power-select page:

import { clickable, text, attribute} from 'ember-cli-page-object';
import { buildSelector } from 'ember-cli-page-object/extend';
import { assign } from '@ember/polyfills';
import { getExecutionContext } from 'ember-cli-page-object/test-support/-private/execution_context';
import { typeInSearch, clickTrigger as _clickTrigger, findContains as _findContains, selectChoose as _selectChoose } from 'ember-power-select/test-support/helpers';
import { assert } from '@ember/debug';

export default function (scope) {
    return {
        scope: scope || '.ui-filter-multi-select',

        select: selectChoose(),
        clickTrigger: clickTrigger(),
        find: findContains(),
        typeInSearch(text) {
            typeInSearch(text);
            return this;
        },
        placeholder: text('.ember-power-select-placeholder'),
        selected: text('.ember-power-select-selected-item'),
        clear: clickable('.ember-power-select-clear-btn'),
        currentSearchValue: currentSearchValue(),
        isOpen: attribute('aria-expanded', '.ember-power-select-trigger')
    };
}

export var clickTrigger = function (selector, userOptions = {}) {
    return {
        isDescriptor: true,

        get(key) {
            return function () {
                let executionContext = getExecutionContext(this);
                let options = assign({ pageObjectKey: `${key}()` }, userOptions);

                return executionContext.runAsync(() => {
                    let fullSelector = buildSelector(this, selector, options);
                    return _clickTrigger(fullSelector);
                });
            };

        }
    }
};
export var selectChoose = function (selector, userOptions = {}) {
    return {
        isDescriptor: true,

        get(key) {
            return function(value){
                let executionContext = getExecutionContext(this);
                let options = assign({ pageObjectKey: `${key}()` }, userOptions);

                return executionContext.runAsync(() => {
                    let fullSelector = buildSelector(this, selector, options);
                    return _selectChoose(fullSelector, value);
                });       
            }
        }
    };
};

export var findContains = function(selector, userOptions = {}) {
    return {
        isDescriptor: true,

        get(key) {
            return function(text){
                let executionContext = getExecutionContext(this);
                let options = assign({ pageObjectKey: `${key}()` }, userOptions);

                return executionContext.runAsync(() => {
                    let fullSelector = buildSelector(this, selector, options);
                    return _findContains(fullSelector, text);
                });
            }
        }
    };
};

export var currentSearchValue = function() {
    return {
        isDescriptor: true,

        get() {
            // TODO: get this merged into ember-power-select
            let selectors = [
                '.ember-power-select-search-input',
                '.ember-power-select-search input',
                '.ember-power-select-trigger-multiple-input',
                'input[type="search"]'
            ].map((selector) => `${selector}`).join(', ');
            let searchInput = document.querySelector(selectors);
            assert("power-select search exists", searchInput);
            return searchInput.value;
        }
    };
};

A test that required selecting an item would look like

await page.clickTrigger()
    .typeInSearch("Foo")
    .select("Foo")

This works both for acceptance and integration tests.

@ro0gr is there anyway to have done this without relying on the private API for getExecutionContext?

@ro0gr
Copy link
Collaborator

ro0gr commented Jan 21, 2019

I think integrating of the new @ember/test-helpers typeIn helper should resolve the issue.

@mistahenry there is no public way to define a full featured custom action yet. You can keep using public APIs only, but w/o chaining support at least.

I'm currently working on decoupling of actions from the execution context, which, I think, would make us closer to the custom actions goal.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants