User-Routine is a JavaScript library to automate user routines on web pages. You can easily test features or create tutorials with actions such as click, await, and fill.
✨ See the Live Demo ✨
Example:
userRoutine([
'fill form>input.name Cory',
'click button.submit',
'await div.result',
'exists div With this text',
]);
Table of Contents
Options:
1. Install from NPM (npm install user-routine
) and import
import { userRoutine } from 'user-routine';
// OR
const { userRoutine } = require('user-routine');
2. Or include the User-Routine script file (user-routine.blob.js
) in your HTML:
<!-- Declares function `userRoutine` (CDN) -->
<script src="https://cdn.jsdelivr.net/gh/CoryLR/user-routine/dist/user-routine.blob.js"></script>
<!-- OR -->
<!-- Declares function `userRoutine` (local file) -->
<script src="./user-routine.blob.js"></script>
3. Or copy the portable template from here: user-routine.template.js
- ^ This works with zero setup if you copy-paste the contents into a browser console or into client-side JavaScript
User-Routine is served as a function named userRoutine
.
Run a test:
userRoutine([
'click button.btn', // Target using CSS selectors
'await div.result Result Text', // Await result text
], { message: 'Testing the button' });
Display a tutorial:
userRoutine([
'comment .some-form First, fill this out',
'comment .submit-button Then, hit Submit!',
], { message: 'Tutorial', tutorialMode: true });
Customize options to run quickly and quietly:
userRoutine([
'fill form>input Mock input text',
'click button.submit',
'await div.some-expected-result',
// etc...
], {
message: 'Testing the button',
displayProgress: false, // default is true
logProgress: false, // default is true
globalDelay: 50, // default is 500 (0.5 seconds)
awaitTimeout: 1500, // default is 15000 (15 seconds)
});
function userRoutine(actions: string[] OR string, options: UserRoutineOptions?)
- 1: Actions List (String (separate actions by new lines) or Array of strings/functions, required)
- Action strings & examples:
append
- Add text to the end of an element's textContent
'append section>p Appended text'
await
- Await for something to appear
'await .modal.success-message'
or'await h1 With This Text'
!await
- Await for something to disappear
'!await .spinner'
or'!await h1 This title should disappear'
click
- Click on something
'click button.submit'
or'click button With This Text'
comment
- Show a tooltip to point something out
'comment input.name Type your name here'
exists
- Check to see if something exists in any css selector matches
'exists .class-name'
or'exists h1 With This Text'
!exists
- Check to see if something doesn't exist in any css selector matches
'!exists h1 Incorrect text'
fill
- Fill the value attribute of a specific element
'fill form>input.name Cory Rahman'
log
- Record a message
'log Some message'
nav
- Use hash navigation
'nav #id'
or'nav #/some/hash/routing/path'
value
- Check the value attribute of a specific element
'value input.required'
or'value input.name Test User 1'
wait
- Wait for some time
'wait 3000'
(3 seconds)
write
- Overwrite textContent of an element
'write p Overwritten text'
- Selector:
- CSS selector like
button.class-name
- The CSS selector should not contain spaces by default. Either use
>>
instead of spaces likeawait .container>>div Result Text
) or pass a custom action stringseparator
in the Options
- CSS selector like
- Data:
- Required argument for
append
,comment
,fill
,log
,value
,wait
, andwrite
- Optional argument for
await
,click
,exists
, andvalue
- Required argument for
- Action strings & examples:
- 2: Options (Object, optional)
awaitTimeout
: (default: 15000) How long in milliseconds to wait for an element using the await commandcontinueOnFailure
: (default: false) Continue to run actions even if one failsdisplayMessage
: (default: true) Show message at the top of the pagedisplayProgress
: (default: true) Show animations of actions visually on the page using tooltipsdisplaySpeed
: (default: 1) Animation speed for displayProgress tooltips (0.5 = half speed, 2 = double speed, etc)globalDelay
: (default: 500) Time between actions in millisecondskeyboardControls
: (default: true) Enables play/pause/stop with space and escape keyslogCollapse
: (default: false) Initializes the console group collapsedlogProgress
: (default: true) Show real-time progress in the browser consolelogResult
: (default: true) Show the final result in the browser consolemessage
: (default: 'User-Routine') Label to show in the console and in the DOMmessageAttribution
: (default: 'User-Routine') Subtitle text shown when custom message is providedoverrideCss
: (default: '') Override default User-Routine CSS, target classes such as .user-routine-message, .user-routine-focus-box, or .user-routine-tooltipseparator
: (default: ' ' (space)) Choose different text to separate the different parts of the action string. For example, withseparator
set to'; '
, you could write an action string like'await; .container div[name="Result Box"]; Result Text'
.simultaneousAllowed
: (default: false) Allow the User-Routine to run even if one is already runningtutorialMode
: (default: false) Add a "Next" button to tooltips, and only show tooltips for "log" and "comment" actions
- The
userRoutine
function returns a Promise resolving to typeUserRoutineReturn
:export type UserRoutineReturn = { success: boolean, log: string[], message: string, configuration: UserRoutineOptions };
- Updates are also logged to the browser console like so:
[User-Routine] Message
* Filled the value of form>input.name to 'Cory'
* Clicked on button[type="submit"]
* Awaiting 'div.success-message'...
* ...Found 'div.success-message'
* Done, success: true
Result: { success: true, log: Array(4), message: 'Message' }
- Full documentation: https://github.com/CoryLR/user-routine#readme
- Live demo: https://corylr.github.io/user-routine/
✨ See the Live Demo ✨
See the user-routine.template.js for examples of running multiple sequential tests using async/await. This template also works with zero setup if you copy-paste the contents into a browser console or into client-side JavaScript
Fill inputs with fill
and interact with click
using Selectors:
userRoutine([
'fill input[type="text"] Hello, world!', // Fills in the input
'fill input[type="number"] 20',
'click button.some-class', // Clicks a button with class 'some-class'
'click div With certain text', // Clicks on the given text within a div
'click * With certain text', // Clicks on the given text regardless of containing element
'click body>>.nested-div', // Use `>>` instead of spaces in CSS selectors
]);
- Note: To use spaces in CSS selectors, either replace the spaces with
>>
(likebody>>.class
instead ofbody .class
) or define a custom separator using theseparator
option (likeseparator: '; '
).
Validate the DOM with exists
and value
:
userRoutine([
'exists p.some-class', // Checks for the existence of this element
'exists p.some-class With certain text', // Also checks if it includes certain text
'!exists p.some-class', // Validates that the element does not exist
'!exists p.some-class With certain text', // Validates that the element does not exist with certain text
'value input.required', // Validates that the element has any value
'value input.name Jane Doe', // Validates that the element has a value of "Jane Doe"
]);
Deal with timing using await
and wait
:
userRoutine([
'await div.some-popup', // Awaits the existence of this element
'await div.some-popup With certain text', // Awaits for it to include certain text
'!await div.some-spinner', // Awaits the non-existence of this element
'!await div.some-popup With certain text', // Awaits for it to not include certain text
'wait 3000', // waits 3 seconds
]);
- Note: The default await timeout is 15000 ms (15 seconds), overwrite using the
awaitTimeout
option.
Navigate within a single-page application using nav
:
userRoutine([
'nav #some-id',
'nav #/some/hash/routing/path',
'nav #', // Back to the top
]);
Add notes with append
, log
, and write
:
userRoutine([
'write h1 Testing successful!', // overwrites the h1's textContent
'append h1 - Testing successful!', // appends to the h1's textContent
'log The testing is complete.',
]);
Pass options as a second argument:
userRoutine([
'fill input.name Cory',
'click button[type="submit"]',
], { globalDelay: 1000 });
// ^ Options object with 1 second between actions
- Note: See Usage for a list of options
- Install dependencies for the Demo using
npm install
- Open the Demo with the
quick-regression-test
url parameter: docs/index.html?action=quick-regression-test
- Make changes to lib/user-routine.ts
- Run
npm run build-local
- If only editing the demo itself (
demo/
), you can just runnpm run build-demo
- If only editing the demo itself (
- To test changes, edit either demo/regression-tests.js or demo/script.js
- Open the Demo with the
quick-regression-test
url parameter: docs/index.html?action=quick-regression-test - Before each commit, run the full
npm run build
To publish:
- Bump the version number in the package.json
npm i
npm run build
- Test one last time
- Fix any issues then commit changes
npm publish --access public
TO DO:
- Add a tutorial walk-through to the demo page, using User-Routine to showcase User-Routine
- Improve tutorialMode by automating progress via
await
and other actions instead of relying on the Next button - Separate actions into externally-callable functions
- Add global case-sensitivity option
- (Maybe) Add count action to count instances of a particular CSS selector
- (Maybe) Add copy/paste actions
- (Maybe) Add ability to keybind User-Routine(s) to keys
- (Maybe) Add copy/paste actions