diff --git a/readme.md b/readme.md index a6093b8..4484110 100644 --- a/readme.md +++ b/readme.md @@ -18,6 +18,9 @@ Here is an [example project](https://github.com/dereke/web-testing) that demonst [@dereke](https://github.com/dereke) has made an excellent [video](https://www.youtube.com/watch?v=WQZ2eIfmfEs) of a TDD session using browser-monkey. +# Docs +[Docs Website](https://browsermonkey.org) + # example ```js codesandbox: basic-example @@ -47,569 +50,6 @@ describe("beer app", () => { ``` Run this example -# debug - -Browser monkey will explain what it is doing using [`debug`](https://github.com/visionmedia/debug). It can be extremely useful to see which buttons were clicked, or which text boxes were typed-in. To turn on, follow the [guide](https://github.com/visionmedia/debug#browser-support), or in short, type this into your browser console: - -```js -localStorage['debug'] = '*'; -``` - -Or to be more specific: - - -```js -localStorage['debug'] = 'browser-monkey'; -``` - -# mount - -Typically you will need to mount your application into the DOM before running your tests. - -Browser monkey comes with a handy way of doing this for popular web frameworks - -**hyperdom** -where YourHyperdomApp is a class that has a render method. [see here](test/app/hyperdom.jsx) for an example - -```js -const hyperdomMonkey = require('browser-monkey/hyperdom') -const monkey = hyperdomMonkey(new YourHyperdomApp()) -``` - -**angular** -where YourAngularApp is a class with fields 'directiveName' and 'moduleName' [see here](test/app/angular.js) for an example - -```js -const angularMonkey = require('browser-monkey/angular') -const monkey = angularMonkey({ - directiveName: 'best-frameworks', - moduleName: 'FrameworksApp' -}) -``` - -**react** -where YourReactApp is a react class [see here](test/app/react.jsx) for an example - -```js -const reactMonkey = require('browser-monkey/react') -const monkey = reactMonkey(new YourReactApp()) -``` - -**iframe** -You can also use browser-monkey to do full integration testing. -Just give it the url of your web server - -```js -const iframeMonkey = require('browser-monkey/iframe') -const monkey = iframeMonkey('http://your-app.example') -``` - -and then you can use the monkey - -```js -monkey.find('h1').shouldHave({text: 'Hello World'}); -``` - -The `monkey` is a normal browser monkey object which the has the following additional options: - - * mount - the mount object used to mount the app (useful for unmounting later) - * app - the application passed to withApp - -you can retrieve these options using the options api eg. `monkey.get('app')` - -# api - -The API is made up of three concepts: scopes, actions and assertions. - -* scopes are chains of queries, such as `find(css)` and `containing(css)`, that progressively narrow the scope of elements to be searched for. These queries return new scopes. -* actions such as `click()` and `typeIn(text)` wait for the scope to be found before simulating a UI event. These return promises that resolve when the event has been dispatched. -* assertions such as `shouldExist()` and `shouldHave(properties)` can be made on scopes to ensure that they exist or contain text, classes or other properties. - -All scope chains are immutable, so you can reuse portions of a scope chain to build new chains: - -```js -const details = browser.find('.details'); // finds .details -const name = details.find('.name'); // finds .details .name -const email = details.find('.email'); // finds .details .email -... -``` - -The API starts with the browser scope, which contains everything on the page. - -You can also create DSLs for components on the page using `scope.component(methods)`. By extending a scope, you can add methods that represent elements of the component at a higher level than mere CSS selectors. It's probably worth noting that these methods should normally just return scopes and not perform actions or assertions. - -## options - -There are some options you can set, which are inherited by inner scopes. - -```js -scope.set({visibleOnly: false}); -const innerScope = scope.find('input'); - -innerScope.get('visibleOnly'); // returns false -``` - -* `visibleOnly` if true, then only visible elements will be found, if false, then all elements are considered. Visible is determined by the element's computed CSS, see [jQuery's :visible selector](https://api.jquery.com/visible-selector/). Default is true. -* `timeout` an integer specifying the milliseconds to wait for an element to appear. This can be overriden by specifying the timeout when calling an action. - -## find - -```js -const innerScope = scope.find(css, [options]); -``` - -Returns a new scope that matches `css`. - -* `css` - css to find in the scope -* `options.text` - text to find in the scope. - -## is - -```js -const scope = scope.is(css); -``` - -Returns a new scope that ensures that the element found matches the CSS. For example, `scope.find('li').is('.enabled')` ensures that the `
  • ` has the class `enabled`. - -* `css` - css to match against the scope - -## containing - -```js -const scope = scope.containing(css, [options]); -``` - -Ensures that the scope contains the `css` and `options.text`, the scope returned still refers to the outer scope. This is useful, for example, in finding list items that contain certain elements, but still referring to the list items. - -* `css` - css to find in the scope -* `options.text` - text to find in the scope. - -For example, find the `li` that contains the `h2` with the text `Second`, and click the link in the `li`. - -```html - -``` - -```js -browser.find('ul li').containing('h2', {text: 'Second'}).find('a').click(); -``` - -## filter - -```js -const scope = scope.filter(filter); -``` - -* `filter(element)` a function that takes a DOM element, and returns either truthy or falsey. If truthy, then the element will be considered as part of the scope, if falsey then it won't. - -## component - -Represents a component on the page, with methods to access certain elements of the component. - -```js -const componentScope = scope.component(methods); -``` - -* `methods` - an object containing functions for scopes of elements inside the component. -* `componentScope` - a scope, but containing additional access methods - -You can create a component from another component too, simply extending the functionality in that component. - -For example, you may have an area on the page that deals with instant messages. You have a list of messages, a text box to enter a new message, and a button to send the message. - -```js -const messages = browser.component({ - messages: function () { - return this.find('.messages'); - }, - messageText: function () { - return this.find('input.message'); - }, - sendButton: function () { - return this.find('button', {text: 'Send'}); - } -}); -``` - -You can then use the messages component: - -```js -await messages.messages().shouldHave({text: ['hi!', 'wassup?']}); -await messages.messageBox().typeIn("just hangin'"); -await messages.sendButton().click(); -``` - -## scope - -You can reset the starting point for the scope, the element from which all elements are searched for. By default this is the `` element, but you can set it to a more specific element, or indeed another scope. - -```js -const scopeUnderElement = scope.scope(element | selector | anotherScope); -``` - -* `element` - an element. This can be an `