├── .gitignore ├── .travis.yml ├── README.md ├── index.js ├── package.json └── test └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "6" 4 | - "6.1" 5 | addons: 6 | apt: 7 | packages: 8 | - xvfb 9 | 10 | install: 11 | - export DISPLAY=':99.0' 12 | - Xvfb :99 -screen 0 1024x768x24 > /dev/null 2>&1 & 13 | - npm install 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/pietgeursen/pull-dom-driver.svg?branch=master)](https://travis-ci.org/pietgeursen/pull-dom-driver) 2 | 3 | # pull-dom-driver 4 | 5 | > A pullstream "webdriver" for interacting with changes to the dom. 6 | 7 | When you're testing client side apps like [react](https://facebook.github.io/react/) or [inu](https://github.com/ahdinosaur/inu), finding and interacting with elements that appear dynamically is painful. pull-dom-driver uses a [pull-stream](https://github.com/ahdinosaur/inu) source of dom mutations from [pull-dom-mutants](http://pull-stream.github.io/#pull-dom-mutants) to `find(".list")` and `click("#go-button")` on elements once they're actually in the dom. 8 | 9 | ## Usage 10 | 11 | Let's find an element that isn't in the dom yet but will be: 12 | 13 | ```js 14 | //in the browser 15 | var createDomStream = require('pull-dom-driver') 16 | var pull = require('pull-stream') 17 | 18 | var domStream = createDomStream(document, window) 19 | pull( 20 | domStream.find('#mutant') 21 | pull.drain((elem) => console.log(`I found this: ${elem}`)) 22 | ) 23 | 24 | var myDiv = document.createElement('div') 25 | myDiv.id = "mutant" 26 | document.body.appendChild(myDiv) 27 | ``` 28 | 29 | This will output 30 | 31 | ``` 32 | "I found this: [object HTMLDivElement]" 33 | ``` 34 | 35 | ## API 36 | 37 | ### var createDomStream = require('pull-dom-driver') 38 | ### createDomStream(rootElement) 39 | Takes the `rootElement` on which you'd like to obseve changes. 40 | 41 | ### var domStream = createDomStream(el) 42 | Returns an object with the following keys: 43 | - `subscribe` 44 | - `find` 45 | - `click` 46 | 47 | ### domStream.find(cssSelectorString) 48 | Takes a `cssSelectorString` for the element(s) you'd like to find. 49 | Returns a pull-stream source of elements that have been found in the dom. 50 | Note that if there is an element that matches the selector when the stream is created it will be emitted by the stream first. 51 | 52 | ### domStream.click(cssSelectorString) 53 | Takes a `cssSelectorString` for the element(s) you'd like to click on. 54 | Returns a pull-stream source of elements that have been clicked in the dom. 55 | Note that if there is an element(s) that matches the selector when the stream is created it will be emitted by the stream first. 56 | 57 | ### domStream.subscribe() 58 | Returns a pull-stream source of dom mutations from [pull-dom-mutants](http://pull-stream.github.io/#pull-dom-mutants) 59 | 60 | ## Install 61 | 62 | With [npm](https://npmjs.org/) installed, run 63 | ``` 64 | $ npm install pull-dom-driver 65 | ``` 66 | 67 | ## Acknowledgments 68 | 69 | pull-dom-driver was inspired by.. 70 | 71 | ## See Also 72 | 73 | - [`noffle/common-readme`](https://github.com/noffle/common-readme) 74 | 75 | ## License 76 | 77 | MIT 78 | 79 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var pull = require('pull-stream') 2 | var many = require('pull-many') 3 | var domMutant = require('pull-dom-mutants') 4 | 5 | module.exports = createDomStream 6 | 7 | function createDomStream (el) { 8 | return { 9 | find, 10 | click, 11 | subscribe 12 | } 13 | function subscribe () { 14 | return domMutant(el, {subtree: true}) 15 | } 16 | function find (selector, opts) { 17 | const newElements = pull( 18 | subscribe(), 19 | selectTargetEl(selector) 20 | ) 21 | const currentElements = pull.once(el.querySelector(selector)) 22 | return many([ 23 | newElements, 24 | currentElements 25 | ]) 26 | } 27 | function click (selector, opts) { 28 | return pull( 29 | find(selector, opts), 30 | pull.map(el => { 31 | el.click() 32 | return el 33 | }) 34 | ) 35 | } 36 | function selectTargetEl (selector) { 37 | return pull( 38 | pull.filter(function (mutation) { 39 | return mutation.target.querySelector(selector) 40 | }), 41 | pull.map(function (mutation) { 42 | return mutation.target.querySelector(selector) 43 | }) 44 | ) 45 | } 46 | } 47 | 48 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "pull-dom-driver", 3 | "version": "2.1.0", 4 | "description": "A pullstream \"webdriver\" for interacting with changes to the dom.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "browserify test/*.js | tape-run | tap-spec" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+ssh://git@github.com/pietgeursen/pull-dom-driver.git" 12 | }, 13 | "keywords": [ 14 | "pull-stream", 15 | "dom", 16 | "css-selector", 17 | "dom-mutation", 18 | "pull-dom-mutants" 19 | ], 20 | "author": "pietgeursen", 21 | "license": "MIT", 22 | "bugs": { 23 | "url": "https://github.com/pietgeursen/pull-dom-driver/issues" 24 | }, 25 | "homepage": "https://github.com/pietgeursen/pull-dom-driver#readme", 26 | "dependencies": { 27 | "pull-dom-mutants": "^1.0.1", 28 | "pull-many": "^1.0.6", 29 | "pull-stream": "^3.4.5" 30 | }, 31 | "devDependencies": { 32 | "browserify": "^13.1.0", 33 | "global": "^4.3.1", 34 | "tap-spec": "^4.1.1", 35 | "tape": "^4.6.2", 36 | "tape-run": "^2.1.4" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | var test = require('tape') 2 | var pull = require('pull-stream') 3 | var document = require('global/document') 4 | 5 | var createDomStream = require('../') 6 | 7 | test('find emits elements that are already in the dom when the stream is created', function (t) { 8 | var root = document.createElement('div') 9 | var el = document.createElement('div') 10 | el.id = 'test' 11 | root.appendChild(el) 12 | var dom = createDomStream(root) 13 | pull( 14 | dom.find('#test'), 15 | pull.drain((el) => { 16 | t.equal(el.id, 'test') 17 | t.end() 18 | return false 19 | }) 20 | ) 21 | }) 22 | 23 | test('find emits elements that are added to the dom after the stream is created', function (t) { 24 | var root = document.createElement('div') 25 | var dom = createDomStream(root) 26 | pull( 27 | dom.find('#test'), 28 | pull.drain((el) => { 29 | t.equal(el.id, 'test') 30 | t.end() 31 | return false 32 | }) 33 | ) 34 | var el = document.createElement('div') 35 | el.id = 'test' 36 | root.appendChild(el) 37 | }) 38 | 39 | test('click emits elements that are already in the dom when the stream is created', function (t) { 40 | var root = document.createElement('div') 41 | var el = document.createElement('div') 42 | el.id = 'test' 43 | root.appendChild(el) 44 | var dom = createDomStream(root) 45 | pull( 46 | dom.click('#test'), 47 | pull.drain((el) => { 48 | t.equal(el.id, 'test') 49 | t.end() 50 | return false 51 | }) 52 | ) 53 | }) 54 | 55 | test('click emits elements that are added to the dom after the stream is created', function (t) { 56 | var root = document.createElement('div') 57 | var dom = createDomStream(root) 58 | pull( 59 | dom.click('#test'), 60 | pull.drain((el) => { 61 | t.equal(el.id, 'test') 62 | t.end() 63 | return false 64 | }) 65 | ) 66 | var el = document.createElement('div') 67 | el.id = 'test' 68 | root.appendChild(el) 69 | }) 70 | 71 | test('click calls the click method on the element', function (t) { 72 | var root = document.createElement('div') 73 | var dom = createDomStream(root) 74 | pull( 75 | dom.click('#test'), 76 | pull.drain((el) => { 77 | }) 78 | ) 79 | var el = document.createElement('div') 80 | el.id = 'test' 81 | el.click = () => { 82 | t.ok(true, 'was clicked') 83 | t.end() 84 | } 85 | root.appendChild(el) 86 | }) 87 | 88 | test('find emits nested elements that are added to the dom after the stream is created', function (t) { 89 | var root = document.createElement('div') 90 | var el = document.createElement('div') 91 | root.appendChild(el) 92 | var dom = createDomStream(root) 93 | pull( 94 | dom.find('#test'), 95 | pull.drain((el) => { 96 | t.equal(el.id, 'test') 97 | t.end() 98 | return false 99 | }) 100 | ) 101 | var el1 = document.createElement('div') 102 | el.appendChild(el1) 103 | el1.id = 'test' 104 | }) 105 | 106 | test('click emits nested elements that are added to the dom after the stream is created', function (t) { 107 | var root = document.createElement('div') 108 | var el = document.createElement('div') 109 | root.appendChild(el) 110 | var dom = createDomStream(root) 111 | pull( 112 | dom.click('#test'), 113 | pull.drain((el) => { 114 | t.equal(el.id, 'test') 115 | t.end() 116 | return false 117 | }) 118 | ) 119 | var el1 = document.createElement('div') 120 | el.appendChild(el1) 121 | el1.id = 'test' 122 | }) 123 | --------------------------------------------------------------------------------