├── .gitignore ├── .travis.yml ├── Makefile ├── README.md ├── at-a-glance.rst ├── conf.py ├── contributing.rst ├── drivers ├── browserkit.rst ├── chrome.rst ├── goutte.rst ├── sahi.rst ├── selenium.rst ├── selenium2.rst └── zombie.rst ├── guides ├── drivers.rst ├── interacting-with-pages.rst ├── managing-sessions.rst ├── manipulating-pages.rst ├── session.rst └── traversing-pages.rst └── index.rst /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | sudo: false 4 | 5 | python: 6 | - "2.7" 7 | 8 | install: pip install Sphinx==1.2.2 sphinx_rtd_theme 9 | 10 | script: sphinx-build -nW -b html -d build/doctrees . build/html 11 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = build 9 | 10 | # Internal variables. 11 | PAPEROPT_a4 = -D latex_paper_size=a4 12 | PAPEROPT_letter = -D latex_paper_size=letter 13 | ALLSPHINXOPTS = -c . -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 14 | 15 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest 16 | 17 | help: 18 | @echo "Please use \`make ' where is one of" 19 | @echo " html to make standalone HTML files" 20 | @echo " dirhtml to make HTML files named index.html in directories" 21 | @echo " singlehtml to make a single large HTML file" 22 | @echo " pickle to make pickle files" 23 | @echo " json to make JSON files" 24 | @echo " htmlhelp to make HTML files and a HTML help project" 25 | @echo " qthelp to make HTML files and a qthelp project" 26 | @echo " devhelp to make HTML files and a Devhelp project" 27 | @echo " epub to make an epub" 28 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 29 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 30 | @echo " text to make text files" 31 | @echo " man to make manual pages" 32 | @echo " changes to make an overview of all changed/added/deprecated items" 33 | @echo " linkcheck to check all external links for integrity" 34 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 35 | 36 | clean: 37 | -rm -rf $(BUILDDIR)/* 38 | 39 | html: 40 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 41 | @echo $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 42 | @echo 43 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 44 | 45 | livehtml: 46 | sphinx-autobuild -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 47 | 48 | dirhtml: 49 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 50 | @echo 51 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 52 | 53 | singlehtml: 54 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 55 | @echo 56 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 57 | 58 | pickle: 59 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 60 | @echo 61 | @echo "Build finished; now you can process the pickle files." 62 | 63 | json: 64 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 65 | @echo 66 | @echo "Build finished; now you can process the JSON files." 67 | 68 | htmlhelp: 69 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 70 | @echo 71 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 72 | ".hhp project file in $(BUILDDIR)/htmlhelp." 73 | 74 | qthelp: 75 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 76 | @echo 77 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 78 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 79 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Behat.qhcp" 80 | @echo "To view the help file:" 81 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Behat.qhc" 82 | 83 | devhelp: 84 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 85 | @echo 86 | @echo "Build finished." 87 | @echo "To view the help file:" 88 | @echo "# mkdir -p $$HOME/.local/share/devhelp/Behat" 89 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Behat" 90 | @echo "# devhelp" 91 | 92 | epub: 93 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 94 | @echo 95 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 96 | 97 | latex: 98 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 99 | @echo 100 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 101 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 102 | "(use \`make latexpdf' here to do that automatically)." 103 | 104 | latexpdf: 105 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 106 | @echo "Running LaTeX files through pdflatex..." 107 | make -C $(BUILDDIR)/latex all-pdf 108 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 109 | 110 | text: 111 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 112 | @echo 113 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 114 | 115 | man: 116 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 117 | @echo 118 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 119 | 120 | changes: 121 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 122 | @echo 123 | @echo "The overview file is in $(BUILDDIR)/changes." 124 | 125 | linkcheck: 126 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 127 | @echo 128 | @echo "Link check complete; look for any errors in the above output " \ 129 | "or in $(BUILDDIR)/linkcheck/output.txt." 130 | 131 | doctest: 132 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 133 | @echo "Testing of doctests in the sources finished, look at the " \ 134 | "results in $(BUILDDIR)/doctest/output.txt." 135 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Mink Documentation 2 | ================== 3 | 4 | This repository contains the documentation for the [Mink](https://github.com/Behat/Mink) project. The [rendered documentation](http://mink.readthedocs.org/en/latest/index.html) is hosted at [Read the Docs](https://readthedocs.org). 5 | 6 | Contribute 7 | ---------- 8 | 9 | Contributions to the documentation are always welcome! 10 | 11 | * Report any bugs or issues you find on the [issue tracker](https://github.com/minkphp/docs/issues). 12 | * You can grab the source code in the [Git repository](https://github.com/minkphp/docs). 13 | 14 | License 15 | ------- 16 | 17 | The documentation is licensed under the [Creative Commons Attribution-ShareAlike 4.0 International License](http://creativecommons.org/licenses/by-sa/4.0/). 18 | -------------------------------------------------------------------------------- /at-a-glance.rst: -------------------------------------------------------------------------------- 1 | Mink at a Glance 2 | ================ 3 | 4 | There's a huge number of browser emulators out there, like `Goutte`_, `Selenium`_, 5 | `Sahi`_ and others. They all do the same job, but do it very differently. 6 | They behave differently and have very different API's. But, what's more important, 7 | there are actually 2 completely different types of browser emulators out there: 8 | 9 | * Headless browser emulators 10 | * Browser controllers 11 | 12 | The first type of browser emulators are simple pure HTTP specification implementations, like 13 | `Goutte`_. Those browser emulators send real HTTP requests against an application 14 | and parse the response content. They are very simple to run and configure, 15 | because this type of emulator can be written in any available programming 16 | language and can be run through the console on servers without a GUI. Headless 17 | emulators have both advantages and disadvantages. Advantages are simplicity, 18 | speed and ability to run without the need of a real browser. But this 19 | type of browser emulator has one big disadvantage, it has no JS/AJAX support. 20 | So, you can't test your rich GUI web applications with headless browsers. 21 | 22 | The second type of browser emulators are browser controllers. Those emulators aim 23 | to control the real browser. That's right, a program to control another program. 24 | Browser controllers simulate user interactions on the browser and are able to 25 | retrieve actual information from the current browser page. `Selenium`_ and `Sahi`_ 26 | are the two most famous browser controllers. The main advantage of using browser 27 | controllers is the support for JS/AJAX interactions on the page. The disadvantage 28 | is that such browser emulators require an installed browser, extra configuration 29 | and are usually much slower than headless counterparts. 30 | 31 | So, the easy answer is to choose the best emulator for your project and use 32 | its API for testing. But as we've already seen, both browser emulator types have 33 | advantages and disadvantages. If you choose a headless browser emulator, you 34 | will not be able to test your JS/AJAX pages. And if you choose a browser controller, 35 | your overall test suite will become very slow at some point. So, in the real 36 | world we should use both! And that's why you need **Mink**. 37 | 38 | **Mink** removes API differences between different browser emulators providing 39 | different drivers (read in :doc:`/guides/drivers` chapter) for every browser 40 | emulator and providing you with an easy way to control the browser (:doc:`/guides/session`), 41 | traverse pages (:doc:`/guides/traversing-pages`), manipulate page elements 42 | (:doc:`/guides/manipulating-pages`) or interact with them (:doc:`/guides/interacting-with-pages`). 43 | 44 | .. _Goutte: https://github.com/FriendsOfPHP/Goutte 45 | .. _Sahi: http://sahi.co.in/w/ 46 | .. _Selenium: http://seleniumhq.org/ 47 | -------------------------------------------------------------------------------- /conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Mink documentation build configuration file, created by 4 | # sphinx-quickstart on Tue Feb 15 02:29:36 2011. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # Note that not all possible configuration values are present in this 9 | # autogenerated file. 10 | # 11 | # All configuration values have a default; values that are commented out 12 | # serve to show the default. 13 | 14 | import sys, os 15 | from sphinx.highlighting import lexers 16 | from pygments.lexers.web import PhpLexer 17 | 18 | lexers['php'] = PhpLexer(startinline=True) 19 | 20 | # If extensions (or modules to document with autodoc) are in another directory, 21 | # add these directories to sys.path here. If the directory is relative to the 22 | # documentation root, use os.path.abspath to make it absolute, like shown here. 23 | #sys.path.insert(0, os.path.abspath('.')) 24 | 25 | # on_rtd is whether we are on readthedocs.org, this line of code grabbed from docs.readthedocs.org 26 | on_rtd = os.environ.get('READTHEDOCS', None) == 'True' 27 | 28 | if not on_rtd: # only import and set the theme if we're building docs locally 29 | import sphinx_rtd_theme 30 | html_theme = 'sphinx_rtd_theme' 31 | html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] 32 | 33 | # otherwise, readthedocs.org uses their theme by default, so no need to specify it 34 | 35 | # -- General configuration ----------------------------------------------------- 36 | 37 | # If your documentation needs a minimal Sphinx version, state it here. 38 | #needs_sphinx = '1.0' 39 | 40 | # Add any Sphinx extension module names here, as strings. They can be extensions 41 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 42 | extensions = [ 43 | 'sphinx.ext.todo', 44 | ] 45 | 46 | # Add any paths that contain templates here, relative to this directory. 47 | templates_path = ['theme/_templates'] 48 | 49 | # The suffix of source filenames. 50 | source_suffix = '.rst' 51 | 52 | # The encoding of source files. 53 | #source_encoding = 'utf-8-sig' 54 | 55 | # The master toctree document. 56 | master_doc = 'index' 57 | 58 | # General information about the project. 59 | project = u'Mink' 60 | copyright = u'2011-2015, Konstantin Kudryashov (everzet)' 61 | 62 | # The version info for the project you're documenting, acts as replacement for 63 | # |version| and |release|, also used in various other places throughout the 64 | # built documents. 65 | # 66 | # The short X.Y version. 67 | version = '1.6' 68 | # The full version, including alpha/beta/rc tags. 69 | release = '1.6' 70 | 71 | # The language for content autogenerated by Sphinx. Refer to documentation 72 | # for a list of supported languages. 73 | language = 'en' 74 | 75 | highlight_language = 'php' 76 | 77 | # There are two options for replacing |today|: either, you set today to some 78 | # non-false value, then it is used: 79 | #today = '' 80 | # Else, today_fmt is used as the format for a strftime call. 81 | #today_fmt = '%B %d, %Y' 82 | 83 | # List of patterns, relative to source directory, that match files and 84 | # directories to ignore when looking for source files. 85 | exclude_patterns = [] 86 | 87 | # The reST default role (used for this markup: `text`) to use for all documents. 88 | #default_role = None 89 | 90 | # If true, '()' will be appended to :func: etc. cross-reference text. 91 | #add_function_parentheses = True 92 | 93 | # If true, the current module name will be prepended to all description 94 | # unit titles (such as .. function::). 95 | #add_module_names = True 96 | 97 | # If true, sectionauthor and moduleauthor directives will be shown in the 98 | # output. They are ignored by default. 99 | #show_authors = False 100 | 101 | # The name of the Pygments (syntax highlighting) style to use. 102 | pygments_style = 'sphinx' 103 | 104 | # A list of ignored prefixes for module index sorting. 105 | #modindex_common_prefix = [] 106 | 107 | 108 | # -- Options for HTML output --------------------------------------------------- 109 | 110 | # Theme options are theme-specific and customize the look and feel of a theme 111 | # further. For a list of options available for each theme, see the 112 | # documentation. 113 | #html_theme_options = {} 114 | 115 | html_context = { 116 | 'logo_name': 'mink', 117 | 'menu_section': 'mink-docs' 118 | } 119 | 120 | # Add any paths that contain custom themes here, relative to this directory. 121 | #html_theme_path = [] 122 | 123 | # The name for this set of Sphinx documents. If None, it defaults to 124 | # " v documentation". 125 | #html_title = None 126 | 127 | # A shorter title for the navigation bar. Default is the same as html_title. 128 | #html_short_title = None 129 | 130 | # The name of an image file (relative to this directory) to place at the top 131 | # of the sidebar. 132 | #html_logo = None 133 | 134 | # The name of an image file (within the static path) to use as favicon of the 135 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 136 | # pixels large. 137 | #html_favicon = None 138 | 139 | # Add any paths that contain custom static files (such as style sheets) here, 140 | # relative to this directory. They are copied after the builtin static files, 141 | # so a file named "default.css" will overwrite the builtin "default.css". 142 | #html_static_path = ['theme/_static'] 143 | 144 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 145 | # using the given strftime format. 146 | #html_last_updated_fmt = '%b %d, %Y' 147 | 148 | # If true, SmartyPants will be used to convert quotes and dashes to 149 | # typographically correct entities. 150 | #html_use_smartypants = True 151 | 152 | # Custom sidebar templates, maps document names to template names. 153 | #html_sidebars = {} 154 | 155 | # Additional templates that should be rendered to pages, maps page names to 156 | # template names. 157 | #html_additional_pages = {} 158 | 159 | # If false, no module index is generated. 160 | #html_domain_indices = True 161 | 162 | # If false, no index is generated. 163 | #html_use_index = True 164 | 165 | # If true, the index is split into individual pages for each letter. 166 | #html_split_index = False 167 | 168 | # If true, links to the reST sources are added to the pages. 169 | #html_show_sourcelink = True 170 | 171 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 172 | #html_show_sphinx = True 173 | 174 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 175 | #html_show_copyright = True 176 | 177 | # If true, an OpenSearch description file will be output, and all pages will 178 | # contain a tag referring to it. The value of this option must be the 179 | # base URL from which the finished HTML is served. 180 | #html_use_opensearch = '' 181 | 182 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 183 | #html_file_suffix = None 184 | 185 | # Output file base name for HTML help builder. 186 | htmlhelp_basename = 'Minkdoc' 187 | 188 | 189 | # -- Options for LaTeX output -------------------------------------------------- 190 | 191 | # The paper size ('letter' or 'a4'). 192 | #latex_paper_size = 'letter' 193 | 194 | # The font size ('10pt', '11pt' or '12pt'). 195 | #latex_font_size = '10pt' 196 | 197 | # Grouping the document tree into LaTeX files. List of tuples 198 | # (source start file, target name, title, author, documentclass [howto/manual]). 199 | latex_documents = [ 200 | ('index', 'Mink.tex', u'Mink Documentation', 201 | u'Konstantin Kudryashov (everzet)', 'manual'), 202 | ] 203 | 204 | # The name of an image file (relative to this directory) to place at the top of 205 | # the title page. 206 | #latex_logo = None 207 | 208 | # For "manual" documents, if this is true, then toplevel headings are parts, 209 | # not chapters. 210 | #latex_use_parts = False 211 | 212 | # If true, show page references after internal links. 213 | #latex_show_pagerefs = False 214 | 215 | # If true, show URL addresses after external links. 216 | #latex_show_urls = False 217 | 218 | # Additional stuff for the LaTeX preamble. 219 | #latex_preamble = '' 220 | 221 | # Documents to append as an appendix to all manuals. 222 | #latex_appendices = [] 223 | 224 | # If false, no module index is generated. 225 | #latex_domain_indices = True 226 | 227 | 228 | # -- Options for manual page output -------------------------------------------- 229 | 230 | # One entry per manual page. List of tuples 231 | # (source start file, name, description, authors, manual section). 232 | man_pages = [ 233 | ('index', 'behat', u'Mink Documentation', 234 | [u'Konstantin Kudryashov (everzet)'], 1) 235 | ] 236 | 237 | 238 | # -- Options for Epub output --------------------------------------------------- 239 | 240 | # Bibliographic Dublin Core info. 241 | epub_title = u'Mink' 242 | epub_author = u'Konstantin Kudryashov (everzet)' 243 | epub_publisher = u'Konstantin Kudryashov (everzet)' 244 | epub_copyright = u'2011-2015, Konstantin Kudryashov (everzet)' 245 | 246 | # The language of the text. It defaults to the language option 247 | # or en if the language is not set. 248 | #epub_language = '' 249 | 250 | # The scheme of the identifier. Typical schemes are ISBN or URL. 251 | #epub_scheme = '' 252 | 253 | # The unique identifier of the text. This can be a ISBN number 254 | # or the project homepage. 255 | #epub_identifier = '' 256 | 257 | # A unique identification for the text. 258 | #epub_uid = '' 259 | 260 | # HTML files that should be inserted before the pages created by sphinx. 261 | # The format is a list of tuples containing the path and title. 262 | #epub_pre_files = [] 263 | 264 | # HTML files shat should be inserted after the pages created by sphinx. 265 | # The format is a list of tuples containing the path and title. 266 | #epub_post_files = [] 267 | 268 | # A list of files that should not be packed into the epub file. 269 | #epub_exclude_files = [] 270 | 271 | # The depth of the table of contents in toc.ncx. 272 | #epub_tocdepth = 3 273 | 274 | # Allow duplicate toc entries. 275 | #epub_tocdup = True 276 | -------------------------------------------------------------------------------- /contributing.rst: -------------------------------------------------------------------------------- 1 | Contributing 2 | ============ 3 | 4 | Reporting issues 5 | ---------------- 6 | 7 | If your issue affects only a single driver, it should be reported to the 8 | driver itself. 9 | Any other issues in the Mink abstraction layer and feature requests should 10 | be reported to the `main Mink repository`_. 11 | 12 | Contributing features 13 | --------------------- 14 | 15 | Contributions should be sent using GitHub pull requests. 16 | 17 | Any contribution should be covered by tests to be accepted. Changes impacting 18 | drivers should include tests in the common driver testsuite to ensure consistency 19 | between implementations. 20 | 21 | New features should always be contributed to the `main Mink repository`_ 22 | first. Features submitted only to a single driver without being part of the 23 | Mink abstraction won't be accepted. 24 | 25 | .. _main Mink repository: https://github.com/minkphp/Mink 26 | -------------------------------------------------------------------------------- /drivers/browserkit.rst: -------------------------------------------------------------------------------- 1 | BrowserKitDriver 2 | ================ 3 | 4 | BrowserKitDriver provides a bridge for the `Symfony BrowserKit`_ component. 5 | BrowserKit is a browser emulator provided by the `Symfony project`_. 6 | 7 | Installation 8 | ------------ 9 | 10 | BrowserKitDriver is a pure PHP library available through Composer: 11 | 12 | .. code-block:: bash 13 | 14 | $ composer require behat/mink-browserkit-driver 15 | 16 | .. note:: 17 | 18 | The BrowserKit component only provides an abstract implementation. The 19 | actual implementation is provided by other projects, like `Goutte`_ 20 | or the `Symfony HttpKernel`_ component. 21 | 22 | If you are using Goutte, you should use the special :doc:`/drivers/goutte` 23 | which ensures full compatibility for Goutte due to an edge case in Goutte. 24 | 25 | Usage 26 | ----- 27 | 28 | In order to talk with BrowserKit, you should instantiate a 29 | ``Behat\Mink\Driver\BrowserKitDriver``: 30 | 31 | .. code-block:: php 32 | 33 | $browserkitClient = // ... 34 | 35 | $driver = new \Behat\Mink\Driver\BrowserKitDriver($browserkitClient); 36 | 37 | .. _Goutte: https://github.com/FriendsOfPHP/Goutte 38 | .. _Symfony BrowserKit: http://symfony.com/components/BrowserKit 39 | .. _Symfony HttpKernel: http://symfony.com/components/HttpKernel 40 | .. _Symfony project: http://symfony.com 41 | -------------------------------------------------------------------------------- /drivers/chrome.rst: -------------------------------------------------------------------------------- 1 | ChromeDriver 2 | =============== 3 | 4 | ChromeDriver allows Mink to control Chrome without the overhead of Selenium. 5 | 6 | It communicates directly with chrome over HTTP and WebSockets, which allows it to work at least twice as fast as Chrome with Selenium. 7 | 8 | For Chrome 59+ it supports headless mode, eliminating the need to install a display server, and the overhead that comes with it. 9 | 10 | Installation 11 | ------------ 12 | 13 | ChromeDriver is available through Composer: 14 | 15 | .. code-block:: bash 16 | 17 | $ composer require dmore/chrome-mink-driver 18 | 19 | Usage 20 | ----- 21 | 22 | Run Chromium or Google Chrome with remote debugging enabled: 23 | 24 | .. code-block:: bash 25 | 26 | $ google-chrome-stable --remote-debugging-address=0.0.0.0 --remote-debugging-port=9222 27 | 28 | or headless (59+): 29 | 30 | .. code-block:: bash 31 | 32 | $ google-chrome-stable --disable-gpu --headless --remote-debugging-address=0.0.0.0 --remote-debugging-port=9222 33 | 34 | Configure Mink to use ChromeDriver: 35 | 36 | .. code-block:: php 37 | 38 | use Behat\Mink\Mink; 39 | use Behat\Mink\Session; 40 | use DMore\ChromeDriver\ChromeDriver; 41 | 42 | $mink = new Mink(array( 43 | 'browser' => new Session(new ChromeDriver('http://localhost:9222', null, 'http://www.google.com')) 44 | )); 45 | 46 | That's it! 47 | 48 | For more details, see `the official documentation`_ 49 | 50 | .. _the official documentation: https://gitlab.com/DMore/chrome-mink-driver/blob/master/README.md 51 | -------------------------------------------------------------------------------- /drivers/goutte.rst: -------------------------------------------------------------------------------- 1 | GoutteDriver 2 | ============ 3 | 4 | GoutteDriver provides a bridge for the `Goutte`_ headless browser. Goutte 5 | is a classical pure-php headless browser, written by the creator of the Symfony 6 | framework Fabien Potencier. 7 | 8 | .. note:: 9 | 10 | The GoutteDriver extends the :doc:`/drivers/browserkit` to fix a small 11 | edge case in the Goutte implementation of BrowserKit. It is also able 12 | to instantiate the Goutte client automatically. 13 | 14 | Installation 15 | ------------ 16 | 17 | GoutteDriver is a pure PHP library available through Composer: 18 | 19 | .. code-block:: bash 20 | 21 | $ composer require behat/mink-goutte-driver 22 | 23 | .. note:: 24 | 25 | GoutteDriver is compatible with both Goutte 1.x which relies on `Guzzle 3`_ 26 | and Goutte 2.x which relies on `Guzzle 4+`_ for the underlying HTTP implementation. 27 | 28 | Composer will probably select Goutte 2.x by default. 29 | 30 | Usage 31 | ----- 32 | 33 | In order to talk with Goutte, you should instantiate a 34 | ``Behat\Mink\Driver\GoutteDriver``: 35 | 36 | .. code-block:: php 37 | 38 | $driver = new \Behat\Mink\Driver\GoutteDriver(); 39 | 40 | Also, if you want to configure Goutte more precisely, you could do the full 41 | setup by hand: 42 | 43 | .. code-block:: php 44 | 45 | $client = new \Goutte\Client(); 46 | // Do more configuration for the Goutte client 47 | 48 | $driver = new \Behat\Mink\Driver\GoutteDriver($client); 49 | 50 | .. _Goutte: https://github.com/FriendsOfPHP/Goutte 51 | .. _Guzzle 3: http://guzzle3.readthedocs.org/en/latest/ 52 | .. _Guzzle 4+: http://docs.guzzlephp.org/en/latest/ 53 | -------------------------------------------------------------------------------- /drivers/sahi.rst: -------------------------------------------------------------------------------- 1 | SahiDriver 2 | ========== 3 | 4 | SahiDriver provides a bridge for the `Sahi`_ browser controller. Sahi is 5 | a new JS browser controller, that fast replaced the old Selenium testing suite. 6 | It's both easier to setup and to use than classical Selenium. It has a GUI 7 | installer for each popular operating system out there and is able to control 8 | every systems browser through a special bundled proxy server. 9 | 10 | Installation 11 | ------------ 12 | 13 | SahiDriver is available through Composer: 14 | 15 | .. code-block:: bash 16 | 17 | $ composer require behat/mink-sahi-driver 18 | 19 | In order to talk with a real browser through Sahi, you should install and 20 | configure Sahi first: 21 | 22 | 1. Download and run the Sahi jar from the `Sahi project website`_ and run 23 | it. It will run the installer, which will guide you through the installation 24 | process. 25 | 26 | 2. Run Sahi proxy before your test suites (you can start this proxy during 27 | system startup): 28 | 29 | .. code-block:: bash 30 | 31 | cd $YOUR_PATH_TO_SAHI/bin 32 | ./sahi.sh 33 | 34 | Usage 35 | ----- 36 | 37 | After installing Sahi and running the Sahi proxy server, you will be able 38 | to control it with ``Behat\Mink\Driver\SahiDriver``: 39 | 40 | .. code-block:: php 41 | 42 | $driver = new \Behat\Mink\Driver\SahiDriver('firefox'); 43 | 44 | .. note:: 45 | 46 | Notice, that the first argument of ``SahiDriver`` is always a browser name, 47 | `supported by Sahi`_. 48 | 49 | If you want more control during the driver initialization, like for example 50 | if you want to configure the driver to talk with a proxy on another machine, 51 | use the more verbose version with a second client argument: 52 | 53 | .. code-block:: php 54 | 55 | $driver = new \Behat\Mink\Driver\SahiDriver( 56 | 'firefox', 57 | new \Behat\SahiClient\Client( 58 | new \Behat\SahiClient\Connection($sid, $host, $port) 59 | ) 60 | ); 61 | 62 | .. note:: 63 | 64 | ``$sid`` is a Sahi session ID. It's a unique string, used by the driver 65 | and the Sahi proxy in order to be able to talk with each other. You should 66 | fill this with ``null`` if you want Sahi to start your browser automatically 67 | or with some unique string if you want to control an already started 68 | browser. 69 | 70 | ``$host`` simply defines the host on which Sahi is started. It is ``localhost`` 71 | by default. 72 | 73 | ``$port`` defines a Sahi proxy port. The default one is ``9999``. 74 | 75 | .. _Sahi: http://sahi.co.in/w/ 76 | .. _Sahi project website: http://sourceforge.net/projects/sahi/files/ 77 | .. _supported by Sahi: http://sahi.co.in/w/browser-types-xml 78 | -------------------------------------------------------------------------------- /drivers/selenium.rst: -------------------------------------------------------------------------------- 1 | SeleniumDriver 2 | ============== 3 | 4 | SeleniumDriver provides a bridge for the famous `Selenium`_ tool. If you 5 | need legacy Selenium, you can use it right out of the box in your Mink test 6 | suites. 7 | 8 | .. caution:: 9 | 10 | The SeleniumRC protocol used by this driver is deprecated and does not 11 | support all Mink features. For this reason, the SeleniumDriver is deprecated 12 | in favor of the :doc:`/drivers/selenium2`, which is based on the new 13 | protocol and is more powerful. 14 | 15 | Installation 16 | ------------ 17 | 18 | SeleniumDriver is available through Composer: 19 | 20 | .. code-block:: bash 21 | 22 | $ composer require behat/mink-selenium-driver 23 | 24 | In order to talk with the selenium server, you should install and configure 25 | it first: 26 | 27 | 1. Download the Selenium Server from the `project website`_. 28 | 29 | 2. Run the server with the following command (update the version number to 30 | the one you downloaded): 31 | 32 | .. code-block:: bash 33 | 34 | $ java -jar selenium-server-standalone-2.44.0.jar 35 | 36 | Usage 37 | ----- 38 | 39 | That's it, now you can use SeleniumDriver: 40 | 41 | .. code-block:: php 42 | 43 | $client = new \Selenium\Client($host, $port); 44 | $driver = new \Behat\Mink\Driver\SeleniumDriver( 45 | 'firefox', 'base_url', $client 46 | ); 47 | 48 | .. _project website: http://seleniumhq.org/download/ 49 | .. _Selenium: http://seleniumhq.org/ 50 | -------------------------------------------------------------------------------- /drivers/selenium2.rst: -------------------------------------------------------------------------------- 1 | Selenium2Driver 2 | =============== 3 | 4 | Selenium2Driver provides a bridge for the `Selenium2 (webdriver)`_ tool. 5 | If you just love Selenium2, you can now use it right out of the box too. 6 | 7 | Installation 8 | ------------ 9 | 10 | Selenium2Driver is available through Composer: 11 | 12 | .. code-block:: bash 13 | 14 | $ composer require behat/mink-selenium2-driver 15 | 16 | In order to talk with selenium server, you should install and configure it 17 | first: 18 | 19 | 1. Download the Selenium Server from the `project website`_. 20 | 21 | 2. Run the server with the following command (update the version number to 22 | the one you downloaded): 23 | 24 | .. code-block:: bash 25 | 26 | $ java -jar selenium-server-standalone-2.44.0.jar 27 | 28 | .. tip:: 29 | 30 | The Selenium2Driver actually relies on the WebDriver protocol defined 31 | by Selenium2. This means that it is possible to use it with other implementations 32 | of the protocol. Note however that other implementations may have some 33 | bugs. 34 | 35 | The testsuite of the driver is run against the `Phantom.js implementation`_ 36 | but it still triggers some failures because of bugs in their implementation. 37 | 38 | Usage 39 | ----- 40 | 41 | That's it, now you can use Selenium2Driver: 42 | 43 | .. code-block:: php 44 | 45 | $driver = new \Behat\Mink\Driver\Selenium2Driver('firefox'); 46 | 47 | .. _Phantom.js implementation: http://phantomjs.org/ 48 | .. _project website: http://seleniumhq.org/download/ 49 | .. _Selenium2 (webdriver): http://seleniumhq.org/ 50 | -------------------------------------------------------------------------------- /drivers/zombie.rst: -------------------------------------------------------------------------------- 1 | ZombieDriver 2 | ============ 3 | 4 | ZombieDriver provides a bridge for the `Zombie.js`_ browser emulator. Zombie.js 5 | is a headless browser emulator, written in node.js. It supports all JS interactions 6 | that :doc:`Selenium ` and :doc:`Sahi ` 7 | do and works almost as fast as Goutte does. It is the best of both worlds 8 | actually, but still limited to only one browser type (Webkit). Also it is 9 | still slower than Goutte and requires node.js and npm to be installed on 10 | the system. 11 | 12 | Installation 13 | ------------ 14 | 15 | ZombieDriver is available through Composer: 16 | 17 | .. code-block:: bash 18 | 19 | $ composer require behat/mink-zombie-driver 20 | 21 | In order to talk with a zombie.js server, you need to install and configure 22 | zombie.js first: 23 | 24 | 1. Install node.js by following instructions from the official site: 25 | ``_. 26 | 27 | 2. Install npm (node package manager) by following the instructions from 28 | ``_. 29 | 30 | 3. Install zombie.js with npm: 31 | 32 | .. code-block:: bash 33 | 34 | $ npm install -g zombie 35 | 36 | After installing npm and zombie.js, you'll need to add npm libs to your ``NODE_PATH``. 37 | The easiest way to do this is to add: 38 | 39 | .. code-block:: bash 40 | 41 | export NODE_PATH="/PATH/TO/NPM/node_modules" 42 | 43 | into your ``.bashrc``. 44 | 45 | Usage 46 | ----- 47 | 48 | After that, you'll be able to just use ZombieDriver without manual server 49 | setup. The driver will do all that for you automatically: 50 | 51 | .. code-block:: php 52 | 53 | $driver = new \Behat\Mink\Driver\ZombieDriver( 54 | new \Behat\Mink\Driver\NodeJS\Server\ZombieServer() 55 | ); 56 | 57 | If you want more control during driver initialization, like for example if 58 | you want to configure the driver to init the server on a specific port, use 59 | the more verbose version: 60 | 61 | .. code-block:: php 62 | 63 | $driver = new \Behat\Mink\Driver\ZombieDriver( 64 | new \Behat\Mink\Driver\Zombie\Server($host, $port, $nodeBin, $script) 65 | ); 66 | 67 | .. note:: 68 | 69 | ``$host`` simply defines the host on which zombie.js will be started. It's 70 | ``127.0.0.1`` by default. 71 | 72 | ``$port`` defines a zombie.js port. Default one is ``8124``. 73 | 74 | ``$nodeBin`` defines full path to node.js binary. Default one is just ``node``. 75 | 76 | ``$script`` defines a node.js script to start zombie.js server. If you pass 77 | a ``null`` the default script will be used. Use this option carefully! 78 | 79 | .. _Zombie.js: http://zombie.labnotes.org/ 80 | -------------------------------------------------------------------------------- /guides/drivers.rst: -------------------------------------------------------------------------------- 1 | Drivers 2 | ======= 3 | 4 | How does Mink provide a consistent API for very different browser library 5 | types, often written in different languages? Through drivers! A Mink driver 6 | is a simple class, that implements ``Behat\Mink\Driver\DriverInterface``. 7 | This interface describes bridge methods between Mink and real browser emulators. 8 | Mink always talks with browser emulators through its driver. It doesn't know 9 | anything about how to start/stop or traverse pages in that particular browser 10 | emulator. It only knows what driver method it should call in order to do this. 11 | 12 | Mink comes with six drivers out of the box: 13 | 14 | .. toctree:: 15 | :maxdepth: 1 16 | 17 | /drivers/goutte 18 | /drivers/browserkit 19 | /drivers/selenium2 20 | /drivers/chrome 21 | /drivers/zombie 22 | /drivers/sahi 23 | /drivers/selenium 24 | 25 | .. _driver-feature-support: 26 | 27 | Driver Feature Support 28 | ---------------------- 29 | 30 | Although Mink does its best to remove browser differences between different 31 | browser emulators, it can't do much in some cases. For example, BrowserKitDriver 32 | cannot evaluate JavaScript and Selenium2Driver cannot get the response status 33 | code. In such cases, the driver will always throw a meaningful 34 | ``Behat\Mink\Exception\UnsupportedDriverActionException``. 35 | 36 | ====================== ================= ========= ====== ====== ======== ==== 37 | Feature BrowserKit/Goutte Selenium2 Chrome Zombie Selenium Sahi 38 | ====================== ================= ========= ====== ====== ======== ==== 39 | Page traversing Yes Yes Yes Yes Yes Yes 40 | Form manipulation Yes Yes Yes Yes Yes Yes 41 | HTTP Basic auth Yes No Yes Yes No No 42 | Windows management No Yes Yes No Yes Yes 43 | iFrames management No Yes Yes No Yes No 44 | Request headers access Yes No Yes Yes No No 45 | Response headers Yes No Yes Yes No No 46 | Cookie manipulation Yes Yes Yes Yes Yes Yes 47 | Status code access Yes No Yes Yes No No 48 | Mouse manipulation No Yes Yes Yes Yes Yes 49 | Drag'n Drop No Yes Yes No Yes Yes 50 | Keyboard actions No Yes Yes Yes Yes Yes 51 | Element visibility No Yes Yes No Yes Yes 52 | JS evaluation No Yes Yes Yes Yes Yes 53 | Window resizing No Yes Yes No No No 54 | Window maximizing No Yes Yes No Yes No 55 | ====================== ================= ========= ====== ====== ======== ==== 56 | -------------------------------------------------------------------------------- /guides/interacting-with-pages.rst: -------------------------------------------------------------------------------- 1 | Interacting with Pages 2 | ====================== 3 | 4 | Most usages of Mink will involve working with the page opened in your browser. 5 | The Mink Element API lets you interact with elements of the page. 6 | 7 | Interacting with Links and Buttons 8 | ---------------------------------- 9 | 10 | The ``NodeElement::click`` and ``NodeElement::press`` methods let you click 11 | the links and press the buttons on the page. 12 | 13 | .. note:: 14 | 15 | These methods are actually equivalent internally (pressing a button involves 16 | clicking on it). Having both methods allows the code to be more readable. 17 | 18 | .. _interacting-with-forms: 19 | 20 | Interacting with Forms 21 | ---------------------- 22 | 23 | The ``NodeElement`` class has a set of methods allowing interaction with 24 | forms: 25 | 26 | ``NodeElement::getValue`` 27 | gets the value of a form field. The value depends on the type of field: 28 | 29 | - the value of the selected option for single select boxes (or ``null`` 30 | when none are selected); 31 | - an array of selected option values for multiple select boxes; 32 | - the value of the checkbox field when checked, or ``null`` when not 33 | checked; 34 | - the value of the selected radio button in the radio group for radio 35 | buttons; 36 | - the value of the field for textual fields and textareas; 37 | - an undefined value for file fields (because of browser limitations). 38 | 39 | ``NodeElement::setValue`` 40 | sets the value of a form field 41 | 42 | - for a file field, it should be the absolute path to the file; 43 | - for a checkbox, it should be a boolean indicating whether it is checked; 44 | - for other fields, it should match the behavior of ``getValue``. 45 | 46 | ``NodeElement::isChecked`` 47 | reports whether a radio button or a checkbox is checked. 48 | 49 | ``NodeElement::isSelected`` 50 | reports whether an ``