npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

automagic-ui

v2.8.1

Published

Automagic ui driver for web interfaces

Downloads

38

Readme

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 .foo[bar=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)

  • Do findUi(semanticLabel[, type])
  • Sort by likelyness that the element would be the recipient of a click: (Weighting here)[https://github.com/MatthewLarner/automagic-ui/blob/master/index.js#L6]
  • .click() the matched element.

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);
})