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 stringseparatorin 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, withseparatorset 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
userRoutinefunction 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>>.classinstead ofbody .class) or define a custom separator using theseparatoroption (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
awaitTimeoutoption.
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-testurl 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-testurl 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 inpm 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
awaitand 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