{"id":25016386,"url":"https://github.com/corylr/user-routine","last_synced_at":"2025-04-13T00:35:37.322Z","repository":{"id":61188378,"uuid":"545700307","full_name":"CoryLR/user-routine","owner":"CoryLR","description":"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.","archived":false,"fork":false,"pushed_at":"2025-02-15T13:12:19.000Z","size":4344,"stargazers_count":10,"open_issues_count":3,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-13T00:35:27.673Z","etag":null,"topics":["application","automated","click","e2e","end-to-end","javascript","routine","single-page","spa","spa-check","test","testing","typescript","user","user-routine","userflow"],"latest_commit_sha":null,"homepage":"https://corylr.github.io/user-routine/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/CoryLR.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-10-04T20:42:27.000Z","updated_at":"2024-09-05T09:54:05.000Z","dependencies_parsed_at":"2025-02-05T09:39:48.359Z","dependency_job_id":null,"html_url":"https://github.com/CoryLR/user-routine","commit_stats":null,"previous_names":["codewithcory/user-routine","corylr/user-routine"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CoryLR%2Fuser-routine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CoryLR%2Fuser-routine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CoryLR%2Fuser-routine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/CoryLR%2Fuser-routine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/CoryLR","download_url":"https://codeload.github.com/CoryLR/user-routine/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248650451,"owners_count":21139671,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["application","automated","click","e2e","end-to-end","javascript","routine","single-page","spa","spa-check","test","testing","typescript","user","user-routine","userflow"],"created_at":"2025-02-05T09:29:18.014Z","updated_at":"2025-04-13T00:35:37.288Z","avatar_url":"https://github.com/CoryLR.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# User-Routine\n\nUser-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.\n\n✨ See the [Live Demo](https://corylr.github.io/user-routine/) ✨\n\nExample:\n\n```javascript\nuserRoutine([\n  'fill form\u003einput.name Cory',\n  'click button.submit',\n  'await div.result',\n  'exists div With this text',\n]);\n```\n\n\n**Table of Contents**\n\n- [User-Routine](#user-routine)\n- [Access](#access)\n- [Usage](#usage)\n  - [Simple Examples](#simple-examples)\n  - [Input Parameter Details](#input-parameter-details)\n  - [Output Details](#output-details)\n  - [More Resources](#more-resources)\n- [Examples](#examples)\n  - [Live Demo](#live-demo)\n  - [Template](#template)\n  - [Use-cases](#use-cases)\n- [Development](#development)\n  - [Maintainers](#maintainers)\n    - [Getting Started](#getting-started)\n    - [Continuous Development](#continuous-development)\n\n# Access\n\nOptions:\n\n**1.** Install from NPM (`npm install user-routine`) and import\n\n```javascript\nimport { userRoutine } from 'user-routine';\n// OR\nconst { userRoutine } = require('user-routine');\n```\n\n**2.** Or include the User-Routine script file (`user-routine.blob.js`) in your HTML:\n\n```html\n\u003c!-- Declares function `userRoutine` (CDN) --\u003e\n\u003cscript src=\"https://cdn.jsdelivr.net/gh/CoryLR/user-routine/dist/user-routine.blob.js\"\u003e\u003c/script\u003e\n\u003c!-- OR --\u003e\n\u003c!-- Declares function `userRoutine` (local file) --\u003e\n\u003cscript src=\"./user-routine.blob.js\"\u003e\u003c/script\u003e\n\n```\n\n**3.** Or copy the portable template from here: [user-routine.template.js](./dist/user-routine.template.js)\n\n* ^ This works with zero setup if you copy-paste the contents into a browser console or into client-side JavaScript\n\n\n# Usage\n\nUser-Routine is served as a function named `userRoutine`.\n\n## Simple Examples\n\nRun a test:\n\n```javascript\nuserRoutine([\n  'click button.btn', // Target using CSS selectors\n  'await div.result Result Text', // Await result text\n], { message: 'Testing the button' });\n```\n\nDisplay a tutorial:\n\n```javascript\nuserRoutine([\n  'comment .some-form First, fill this out',\n  'comment .submit-button Then, hit Submit!',\n], { message: 'Tutorial', tutorialMode: true });\n```\n\nCustomize options to run quickly and quietly:\n\n```javascript\nuserRoutine([\n  'fill form\u003einput Mock input text',\n  'click button.submit',\n  'await div.some-expected-result',\n  // etc...\n], {\n  message: 'Testing the button',\n  displayProgress: false, // default is true\n  logProgress: false, // default is true\n  globalDelay: 50, // default is 500 (0.5 seconds)\n  awaitTimeout: 1500, // default is 15000 (15 seconds)\n});\n```\n\n## Input Parameter Details\n\nfunction userRoutine(actions: *string[] OR string*, options: *UserRoutineOptions?*)\n\n* 1: Actions List (*String* (separate actions by new lines) or *Array of strings/functions*, required)\n  * Action strings \u0026 examples:\n    * `append`\n      * Add text to the end of an element's textContent\n      * `'append section\u003ep Appended text'`\n    * `await`\n      * Await for something to appear\n      * `'await .modal.success-message'` or `'await h1 With This Text'`\n    * `!await`\n      * Await for something to disappear\n      * `'!await .spinner'` or `'!await h1 This title should disappear'`\n    * `click`\n      * Click on something\n      * `'click button.submit'` or `'click button With This Text'`\n    * `comment`\n      * Show a tooltip to point something out\n      * `'comment input.name Type your name here'`\n    * `exists`\n      * Check to see if something exists in any css selector matches\n      * `'exists .class-name'` or `'exists h1 With This Text'`\n    * `!exists`\n      * Check to see if something doesn't exist in any css selector matches\n      * `'!exists h1 Incorrect text'`\n    * `fill`\n      * Fill the value attribute of a specific element\n      * `'fill form\u003einput.name Cory Rahman'`\n    * `log`\n      * Record a message\n      * `'log Some message'`\n    * `nav`\n      * Use hash navigation\n      * `'nav #id'` or `'nav #/some/hash/routing/path'`\n    * `value`\n      * Check the value attribute of a specific element\n      * `'value input.required'` or `'value input.name Test User 1'`\n    * `wait`\n      * Wait for some time\n      * `'wait 3000'` (3 seconds)\n    * `write`\n      * Overwrite textContent of an element\n      * `'write p Overwritten text'`\n  * Selector:\n    * CSS selector like `button.class-name`\n    * The CSS selector should not contain spaces by default. Either use `\u003e\u003e` instead of spaces like `await .container\u003e\u003ediv Result Text`) or pass a custom action string `separator` in the Options\n  * Data:\n    * Required argument for `append`, `comment`, `fill`, `log`, `value`, `wait`, and `write`\n    * Optional argument for `await`, `click`, `exists`, and `value`\n* 2: Options (*Object*, optional)\n  * `awaitTimeout`: (*default: 15000*) How long in milliseconds to wait for an element using the await command\n  * `continueOnFailure`: (*default: false*) Continue to run actions even if one fails\n  * `displayMessage`: (*default: true*) Show message at the top of the page\n  * `displayProgress`: (*default: true*) Show animations of actions visually on the page using tooltips\n  * `displaySpeed`: (*default: 1*) Animation speed for displayProgress tooltips (0.5 = half speed, 2 = double speed, etc)\n  * `globalDelay`: (*default: 500*) Time between actions in milliseconds\n  * `keyboardControls`: (*default: true*) Enables play/pause/stop with space and escape keys\n  * `logCollapse`: (*default: false*) Initializes the console group collapsed\n  * `logProgress`: (*default: true*) Show real-time progress in the browser console\n  * `logResult`: (*default: true*) Show the final result in the browser console\n  * `message`: (*default: 'User-Routine'*) Label to show in the console and in the DOM\n  * `messageAttribution`: (*default: 'User-Routine'*) Subtitle text shown when custom message is provided\n  * `overrideCss`: (*default: ''*) Override default User-Routine CSS, target classes such as .user-routine-message, .user-routine-focus-box, or .user-routine-tooltip\n  * `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'`.\n  * `simultaneousAllowed`: (*default: false*) Allow the User-Routine to run even if one is already running\n  * `tutorialMode`: (*default: false*) Add a \"Next\" button to tooltips, and only show tooltips for \"log\" and \"comment\" actions\n\n## Output Details\n\n* The `userRoutine` function returns a Promise resolving to type `UserRoutineReturn`:\n  * `export type UserRoutineReturn = { success: boolean, log: string[], message: string, configuration: UserRoutineOptions };`\n* Updates are also logged to the browser console like so:\n\n```\n[User-Routine] Message\n  * Filled the value of form\u003einput.name to 'Cory'\n  * Clicked on button[type=\"submit\"]\n  * Awaiting 'div.success-message'...\n  * ...Found 'div.success-message'\n  * Done, success: true\n  Result: { success: true, log: Array(4), message: 'Message' }\n```\n\n## More Resources\n\n* Full documentation: https://github.com/CoryLR/user-routine#readme\n* Live demo: https://corylr.github.io/user-routine/\n\n\n# Examples\n\n## Live Demo\n\n✨ See the [Live Demo](https://corylr.github.io/user-routine/) ✨\n\n## Template\n\nSee 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\n\n## Use-cases\n\n**Fill inputs with `fill` and interact with `click` using Selectors:**\n\n```javascript\nuserRoutine([\n  'fill input[type=\"text\"] Hello, world!', // Fills in the input\n  'fill input[type=\"number\"] 20',\n  'click button.some-class', // Clicks a button with class 'some-class'\n  'click div With certain text', // Clicks on the given text within a div\n  'click * With certain text', // Clicks on the given text regardless of containing element\n  'click body\u003e\u003e.nested-div', // Use `\u003e\u003e` instead of spaces in CSS selectors\n]);\n```\n\n* Note: To use spaces in CSS selectors, either replace the spaces with `\u003e\u003e` (like `body\u003e\u003e.class` instead of `body .class`) or define a custom separator using the `separator` option (like `separator: '; '`).\n\n**Validate the DOM with `exists` and `value`:**\n\n```javascript\nuserRoutine([\n  'exists p.some-class', // Checks for the existence of this element\n  'exists p.some-class With certain text', // Also checks if it includes certain text\n  '!exists p.some-class', // Validates that the element does not exist\n  '!exists p.some-class With certain text', // Validates that the element does not exist with certain text\n  'value input.required', // Validates that the element has any value\n  'value input.name Jane Doe', // Validates that the element has a value of \"Jane Doe\"\n]);\n```\n\n**Deal with timing using `await` and `wait`:**\n\n```javascript\nuserRoutine([\n  'await div.some-popup', // Awaits the existence of this element\n  'await div.some-popup With certain text', // Awaits for it to include certain text\n  '!await div.some-spinner', // Awaits the non-existence of this element\n  '!await div.some-popup With certain text', // Awaits for it to not include certain text\n  'wait 3000', // waits 3 seconds\n]);\n```\n\n* Note: The default await timeout is 15000 ms (15 seconds), overwrite using the `awaitTimeout` option.\n\n**Navigate within a single-page application using `nav`:**\n\n```javascript\nuserRoutine([\n  'nav #some-id',\n  'nav #/some/hash/routing/path',\n  'nav #', // Back to the top\n]);\n```\n\n**Add notes with `append`, `log`, and `write`:**\n\n```javascript\nuserRoutine([\n  'write h1 Testing successful!', // overwrites the h1's textContent\n  'append h1  - Testing successful!', // appends to the h1's textContent\n  'log The testing is complete.',\n]);\n```\n\n**Pass options as a second argument:**\n\n```javascript\nuserRoutine([\n  'fill input.name Cory',\n  'click button[type=\"submit\"]',\n], { globalDelay: 1000 });\n// ^ Options object with 1 second between actions\n```\n\n* Note: See [Usage](#Usage) for a list of options\n\n# Development\n\n## Maintainers\n\n### Getting Started\n\n* Install dependencies for the Demo using `npm install`\n* Open the Demo with the `quick-regression-test` url parameter: [docs/index.html?action=quick-regression-test](./docs/index.html?action=quick-regression-test)\n\n### Continuous Development\n\n* Make changes to [lib/user-routine.ts](./lib/user-routine.ts)\n* Run `npm run build-local`\n  * If only editing the demo itself (`demo/`), you can just run `npm run build-demo`\n* To test changes, edit either [demo/regression-tests.js](./demo/regression-tests.js) or [demo/script.js](./demo/script.js)\n* Open the Demo with the `quick-regression-test` url parameter: [docs/index.html?action=quick-regression-test](./docs/index.html?action=quick-regression-test)\n* Before each commit, run the full `npm run build`\n\nTo publish:\n\n1. Bump the version number in the [package.json](./package.json)\n2. `npm i`\n3. `npm run build`\n4. Test one last time\n5. Fix any issues then commit changes\n6. `npm publish --access public`\n\nTO DO:\n\n* [ ] Add a tutorial walk-through to the demo page, using User-Routine to showcase User-Routine\n* [ ] Improve tutorialMode by automating progress via `await` and other actions instead of relying on the Next button\n* [ ] Separate actions into externally-callable functions\n* [ ] Add global case-sensitivity option\n* [ ] (Maybe) Add count action to count instances of a particular CSS selector\n* [ ] (Maybe) Add copy/paste actions\n* [ ] (Maybe) Add ability to keybind User-Routine(s) to keys\n* [ ] (Maybe) Add copy/paste actions\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcorylr%2Fuser-routine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcorylr%2Fuser-routine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcorylr%2Fuser-routine/lists"}