Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/corylr/user-routine
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.
https://github.com/corylr/user-routine
application automated click e2e end-to-end javascript routine single-page spa spa-check test testing typescript user user-routine userflow
Last synced: about 3 hours ago
JSON representation
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.
- Host: GitHub
- URL: https://github.com/corylr/user-routine
- Owner: CoryLR
- License: mit
- Created: 2022-10-04T20:42:27.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-08-03T17:22:55.000Z (6 months ago)
- Last Synced: 2025-01-09T09:27:28.659Z (27 days ago)
- Topics: application, automated, click, e2e, end-to-end, javascript, routine, single-page, spa, spa-check, test, testing, typescript, user, user-routine, userflow
- Language: TypeScript
- Homepage: https://corylr.github.io/user-routine/
- Size: 4.15 MB
- Stars: 10
- Watchers: 3
- Forks: 1
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# User-Routine
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](https://corylr.github.io/user-routine/) ✨
Example:
```javascript
userRoutine([
'fill form>input.name Cory',
'click button.submit',
'await div.result',
'exists div With this text',
]);
```**Table of Contents**
- [User-Routine](#user-routine)
- [Access](#access)
- [Usage](#usage)
- [Simple Examples](#simple-examples)
- [Input Parameter Details](#input-parameter-details)
- [Output Details](#output-details)
- [More Resources](#more-resources)
- [Examples](#examples)
- [Live Demo](#live-demo)
- [Template](#template)
- [Use-cases](#use-cases)
- [Development](#development)
- [Maintainers](#maintainers)
- [Getting Started](#getting-started)
- [Continuous Development](#continuous-development)# Access
Options:
**1.** Install from NPM (`npm install user-routine`) and import
```javascript
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:
```html
```
**3.** Or copy the portable template from here: [user-routine.template.js](./dist/user-routine.template.js)
* ^ This works with zero setup if you copy-paste the contents into a browser console or into client-side JavaScript
# Usage
User-Routine is served as a function named `userRoutine`.
## Simple Examples
Run a test:
```javascript
userRoutine([
'click button.btn', // Target using CSS selectors
'await div.result Result Text', // Await result text
], { message: 'Testing the button' });
```Display a tutorial:
```javascript
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:
```javascript
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)
});
```## Input Parameter Details
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 like `await .container>>div Result Text`) or pass a custom action string `separator` in the Options
* Data:
* Required argument for `append`, `comment`, `fill`, `log`, `value`, `wait`, and `write`
* Optional argument for `await`, `click`, `exists`, and `value`
* 2: Options (*Object*, optional)
* `awaitTimeout`: (*default: 15000*) How long in milliseconds to wait for an element using the await command
* `continueOnFailure`: (*default: false*) Continue to run actions even if one fails
* `displayMessage`: (*default: true*) Show message at the top of the page
* `displayProgress`: (*default: true*) Show animations of actions visually on the page using tooltips
* `displaySpeed`: (*default: 1*) Animation speed for displayProgress tooltips (0.5 = half speed, 2 = double speed, etc)
* `globalDelay`: (*default: 500*) Time between actions in milliseconds
* `keyboardControls`: (*default: true*) Enables play/pause/stop with space and escape keys
* `logCollapse`: (*default: false*) Initializes the console group collapsed
* `logProgress`: (*default: true*) Show real-time progress in the browser console
* `logResult`: (*default: true*) Show the final result in the browser console
* `message`: (*default: 'User-Routine'*) Label to show in the console and in the DOM
* `messageAttribution`: (*default: 'User-Routine'*) Subtitle text shown when custom message is provided
* `overrideCss`: (*default: ''*) Override default User-Routine CSS, target classes such as .user-routine-message, .user-routine-focus-box, or .user-routine-tooltip
* `separator`: (*default: ' ' (space)*) Choose different text to separate the different parts of the action string. For example, with `separator` 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 running
* `tutorialMode`: (*default: false*) Add a "Next" button to tooltips, and only show tooltips for "log" and "comment" actions## Output Details
* The `userRoutine` function returns a Promise resolving to type `UserRoutineReturn`:
* `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' }
```## More Resources
* Full documentation: https://github.com/CoryLR/user-routine#readme
* Live demo: https://corylr.github.io/user-routine/# Examples
## Live Demo
✨ See the [Live Demo](https://corylr.github.io/user-routine/) ✨
## Template
See the [user-routine.template.js](./dist/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
## Use-cases
**Fill inputs with `fill` and interact with `click` using Selectors:**
```javascript
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 `>>` (like `body>>.class` instead of `body .class`) or define a custom separator using the `separator` option (like `separator: '; '`).
**Validate the DOM with `exists` and `value`:**
```javascript
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`:**
```javascript
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`:**
```javascript
userRoutine([
'nav #some-id',
'nav #/some/hash/routing/path',
'nav #', // Back to the top
]);
```**Add notes with `append`, `log`, and `write`:**
```javascript
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:**
```javascript
userRoutine([
'fill input.name Cory',
'click button[type="submit"]',
], { globalDelay: 1000 });
// ^ Options object with 1 second between actions
```* Note: See [Usage](#Usage) for a list of options
# Development
## Maintainers
### Getting Started
* 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](./docs/index.html?action=quick-regression-test)### Continuous Development
* Make changes to [lib/user-routine.ts](./lib/user-routine.ts)
* Run `npm run build-local`
* If only editing the demo itself (`demo/`), you can just run `npm run build-demo`
* To test changes, edit either [demo/regression-tests.js](./demo/regression-tests.js) or [demo/script.js](./demo/script.js)
* Open the Demo with the `quick-regression-test` url parameter: [docs/index.html?action=quick-regression-test](./docs/index.html?action=quick-regression-test)
* Before each commit, run the full `npm run build`To publish:
1. Bump the version number in the [package.json](./package.json)
2. `npm i`
3. `npm run build`
4. Test one last time
5. Fix any issues then commit changes
6. `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