2.8.1 • Published 6 years ago

automagic-ui v2.8.1

Weekly downloads
5
License
MIT
Repository
github
Last release
6 years ago

automagic-ui

Automagic ui driver for web interfaces

User interface integration tests are notoriously brittle.

automagic-ui attempts to ease the pain by providing a descriptive api for user interactions.

Usage

var driver = require('automagic-ui');

driver.init({
    // Scope to a different document or window such as inside an iframe
    documentScope: // defaults to document
    windowScope: // defaults to window

    // Set a delay before executing commands, also sets a default for driver.wait
    runDelay: // defaults to 0

    // Set a delay between key-presses
    keyPressDelay: // defaults to 50
});

Chain some simple interactions

driver()
    .click('I am a button')
    .pressKey('1')
    .pressKey('a')
    .click('I am a button')
    //execute the sequence of interactions
    .go(function(error, result) {
        // This would be a good place to write some tests.
        // result is the last element automagic-ui interacted with
    });

Create some interactions and execute them later

function findLoginForm() {
    driver()
        .findUi('login', 'field'),
        .findUi('password', 'field'),
        .findUi('submit', 'button')
}

driver()
    .do(findLoginForm())
    .focus('login')
    .pressKeys('admin')
    .focus('password')
    .pressKeys('drowssap')
    .click('submit', 'button')
    .go(function(error, result) {
        // Check stuff
    })

Target elements by RegExp

driver()
    .findUi(/Welcome .*/)
    .go(function(error, result) {
        // Welcome message for some user found
    })

Philosophy

automagic-ui acts like a human tester, you described things like you would describe them to a human. If automagic-ui can't test your UI, your UI might have some usability issues, especially for users that are sight-limited.

Why can't I use class/id/attribute selectors?

Muliple reasons:

  • Users can't see DOM attributes, you woudln't say "Click .foobar=3 > *:first-child" to a person.
  • The DOM structure of your application is not coupled to it's usability. When tests use dom-selectors to assert things, they break when the implementation changes, and they often continue to pass even when the UI is broken. If you set a button to display: none, a person cannot click it, but your tests will still pass.
  • If you can't target an element by semantic labels, you need to improve your application.

API

navigate(location)

Set's window.url to location.

findUi(semanticLabel, type, returnArray)

Elements will first be filtered by type where type is one of:

  • button: <button>, <a>, ...
  • label: <label>, <span>, ...
  • heading: [role=heading], <h1>, <h2>, ...
  • image: <img>, <svg>, [role=img] ...
  • field: <input>, <textarea>, <select>, <label>
  • ...
  • text: Anything.
  • all: Anything.

And then filtered where they semantically match semanticLabel where semanticLabel can be the elements text, title, placeholder, aria-label, value, or alt if the element is an IMG.

Also finds elements that have a referenced <label for="{elementName}"> by the same method.

A list of all the types can be found at elementTypes.js

Matched elements will then by sorted by how likely they are what you are after.

By default, returns the best-match element, but you can get all of the ordered elements by passing true for returnArray

getLocation()

Get's window.location

focus(semanticLabel, type)

Do findUi(semanticLabel[, type]) and .focus() the matched element.

blur()

Blur the currently focused element.

click(value, type)

pressKey(character)

Emulates a key-press on a keyboard. Usually used after calling .focus()

pressKeys(string)

Emulates multiple key-presses on a keyboard. Usually used after calling .focus()

the delay between each keypress is configurable during initialisation.

changeValue(semanticLabel, type, text)

  • Do .focus(semanticLabel[, type])
  • Then .pressKeys(text)
  • Then .blur()
  • Then trigger a change event on the target element for good measure.

setValue(semanticLabel, type, text)

  • Do .focus(semanticLabel[, type])
  • Then set element.value = text

getValue(semanticLabel, type, text)

  • Do .focus(semanticLabel[, type])
  • Then get element.value if it has a value property or otherwise element.textContent

wait(time)

Waits for time

do(driver)

execute all the actions from another driver

check(action)

Do some custom action.

action will be called with action(lastResult, callback)

if(semanticLabel, type, addSubTasks)

Caution! This function is not inteded to be used for any case other than UI's that are specifically built with random interface elements, such as those used in security flows. It is not recommended that you use it to predict state based on the presence of UI.

  • Do findUi(semanticLabel[, type])
  • Ff the UI could not be found, skip the rest
  • Create a new driver
  • Then call addSubTasks(newDriver)
  • Then execute that driver.

in(semanticLabel, type, addSubTasks)

  • Do findUi(semanticLabel[, type])
  • Then create a new driver who's context is set to the result
  • Then call addSubTasks(newDriver)
  • Then execute that driver.

scrollTo(semanticLabel, type)

  • Do findUi(semanticLabel[, type])
  • Scroll the resultant element into view

waitFor(semanticLabel, type)

go(callback)

Execute the driver

.go(function(error, result){
    if(error){
        return console.log('one of the steps failed:', error);
    }

    console.log('Successfully completed all steps. Last result was:', result);
})
2.8.1

6 years ago

2.8.0

6 years ago

2.7.0

6 years ago

2.6.1

6 years ago

2.6.0

6 years ago

2.5.3

6 years ago

2.5.2

6 years ago

2.5.1

6 years ago

2.5.0

6 years ago

2.4.0

6 years ago

2.3.0

6 years ago

2.2.0

6 years ago

2.1.0

6 years ago

2.0.0

6 years ago

1.3.1

6 years ago

1.3.0

6 years ago

1.2.2

6 years ago

1.2.1

7 years ago

1.2.0

8 years ago

1.1.0

9 years ago

1.0.2

9 years ago

1.0.1

9 years ago

1.0.0

9 years ago