Coder Social home page Coder Social logo

bigtestjs / interactor Goto Github PK

View Code? Open in Web Editor NEW
25.0 25.0 5.0 851 KB

All BigTest development has moved to https://github.com/thefrontside/bigtest

Home Page: https://github.com/thefrontside/bigtest

License: MIT License

JavaScript 100.00%
convergence interaction interactor javascript-testing testing testing-framework testing-tools

interactor's People

Contributors

cowboyd avatar giancorzo avatar josemarluedke avatar minkimcello avatar omjadas avatar robdel12 avatar samkeathley avatar taras avatar wwilsman 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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

interactor's Issues

Fix `find` docs example

Looking over a recent fix for these docs, I realized that the example is actually incorrect. The find property creator returns a getter, so the example should not be .getHeader(), but .header instead.

Complex nested interactor functions do not work as expected

Given these interactors:

@interactor class SignInInteractor {
  fillName = fillable('[data-test-name-input]')
  fillEmail = fillable('[data-test-email-input]')
  submit = clickable('[data-test-submit]')
  fillAndSubmit(name, email) {
    return this
      .fillName(name)
      .fillEmail(email)
      .submit()
  }
}

@interactor class PageInteractor {
  signInForm = new SignInInteractor('[data-test-signin-form]')
}

I would expect this to work:

new PageInteractor()
  .signInForm.fillAndSubmit('Wil', '[email protected]')

But instead, an error is throw that might look like this:

PageInteractor.fillEmail is not a function

This is because when an interactor is nested, it's methods return new instances of the parent interactor. So fillName() in SignInInteractor will return a new PageInteractor.

We should have a way to break out of this nested structure for complex methods such as this. Something like this.pure(), this.scoped(), or something akin to return an un-nested interactor.

Throw better error message when redefining a property

It's not obvious that there are default properties on an interactor like isVisible. If you set a property on an interactor with the same key you'll get an error like:

Uncaught Error: cannot redefine existing property "isVisible"

In an ideal world we should throw an error saying something like "Interactor already has a property named isVisible, please choose a new name"

Or something that says that interactor provides this. I spent ~5 mins looking for a duplicate until I realized what was going on.

Element is not defined

import { setupAppForTesting } from '@bigtest/react';
import {
  Interactor,
  clickable, fillable, blurrable
} from '@bigtest/interactor';

import Application from '@ui/application';


class TodoMVCPage extends Interactor {
  clickFirstTodo = clickable('ul.todo-list li:first-child');
  fillName = fillable('ul.todo-list li:first-child input');
}

describe('Acceptance | todo editing', () => {
  let app;

  beforeEach(async () => {
    app = await setupAppForTesting(Application);
  });

  it('the initial todo can be edited', () => {
    const page = new TodoMVCPage()
      .clickFirstTodo();

    const edits = app.find('.editable');
    const classes = edits[0].classList;

    expect(classes).to.contain('editing');
  });

and then I get this error:

  1) Acceptance | todo editing
       the initial todo can be edited:
     ReferenceError: Element is not defined
      at new Interactor (node_modules/@bigtest/interactor/dist/umd/index.js:855:59)
      at new TodoMVCPage (tests/acceptance/todo-editing-test.ts:8:9)
      at Context.it (tests/acceptance/todo-editing-test.ts:25:18)
      at <anonymous>

Configure ES modules properly

It is common in a webpack environment when using babel to not transform modules within the node_modules directory. Our package's "module" field points directly to the src files, which are typically compiled with @babel/preset-env. When babel is configured to not compile our packages within node_modules, bundles that use our packages can end up broken.

This can be seen in @bigtest/interaction tests by removing the (!?/@bigtest) regexp within the babel-loader exclude option in the karma.config.js file. This causes the package to fail to properly extend the convergence class and thereby causes every test to fail.

(moved from thefrontside/bigtest#55)

Deprecate `@bigtest/interaction` package

Originally, the interactors were published under the @bigtest/interaction package.

We accidentally installed it and were . We should probably publish a version with a deprecation message like

"DID YOU MEAN @bigtest/interactor`?

Using `hasClass` with CSS Modules

On an app using CSS Modules, what should be the strategy for using the hasClass() page object property?

  1. Import the CSS file with the style into the page object as styles so you can check for hasClass(styles.hasError, '#idThatWouldHaveError').

  2. Modify hasClass() to accept a regex as the className - that way a class .hasError--{hash} can be found with hasClass('^has-Error--.*$', '#idThatWouldHaveError').

Option 1 seems more bulletproof, but should page objects be dealing with CSS like that? Option 2 would be a nice option, even if it wouldn't work for apps using CSS Modules that don't leave part of the original class name.

Comments:

Option 1 seems like the more proper way with modules. I do like option 2 because that can allow you to match multiple classes and seems more robust.

I'll also introduce option 3:

is('[class*="has-Error--"]', '#idThatWouldHaveError')

I think the artifact for this ticket is we update the docs for usage with CSS guides. We can use option 1 today I believe and option 3 works for sure.

When you import styles into a js file its basically an object with the real class name as the key & the value is the CSS module class name.

// ...
import styles from 'styles.css';

@page class MyPage {
  // styles --> { hasError: 'hasError--hbQY8' }
 thingHasError =  hasClass(styles.hasError)
}

(moved from thefrontside/bigtest#52)

Group common property helpers

While working with interaction page objects, I'm seeing stuff similar to this a lot:

hasField = isPresent('input[data-test-field]');
focusField = focusable('input[data-test-field]');
fillField = fillable('input[data-test-field]');
blurField = blurable('input[data-test-field]');

What if we simplified that with a single property helper?

field = input('input[data-test-field]');

That has a predetermined set of properties...

page
  .field.focus()
  .field.fill('value')
  .field.blur()

We could do something similar with other properties as well.

error = element('[data-test-error]');

...

expect(page.error.exists).to.be.true
expect(page.error.text).to.equal('some error')

And maybe even a way to compose these common properties?

field = element('[data-some-thing]').focusable().blurable().fillable()

(moved from thefrontside/bigtest#80)

Helper for checking every member of a collection against a predicate

It would be nice to have a way to check every member of a collection against a predicate that returns the results &&ed together.

Given a collection such:

  items = collection($selector, {
    isSelected: hasClass('selected', $child)
  });

The ability to add something like the following property would be boss:

  allItemsSelected = all(this.items(), item => item.isSelected);

(moved from thefrontside/bigtest#65)

Add `select`/`selectable` interaction method

This would work with <select> elements by selecting the option containing the text.

Currently, we can use fill/fillable to set the value of a <select> element. However, in practice we typically select an option based on it's text value.

The fill/fillable method does not fail when the value is not present in the list of options, so this can lead to some confusing failed tests. The select/selectable method should fail when it cannot find the option with the specified text.

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.