Skip to content
Newer
Older
100644 172 lines (121 sloc) 9.55 KB
1290a3e @semperos Update readme to use by-attr= for one of its examples
authored Mar 11, 2011
1 # Selenium-WebDriver Support for Clojure
03ae48a @semperos Initial commit
authored Mar 11, 2011
2
d44681e @semperos Update README, more tag options
authored May 13, 2011
3 This is a Clojure library for driving a web browser using Selenium-WebDriver as the backend. Credits to [mikitebeka/webdriver-clj][webdriver-orig] for the initial code for this project and many of the low-level wrappers around the WebDriver API.
03ae48a @semperos Initial commit
authored Mar 11, 2011
4
c38290a @semperos Add primary links for this project's resources to the README
authored Aug 11, 2011
5 * [Project Wiki](https://github.com/semperos/clj-webdriver/wiki)
6 * [Marginalia Documentation](http://techylinguist.com/project-static/clj-webdriver/uberdoc.html)
7 * [Google Group](https://groups.google.com/forum/#!forum/clj-webdriver)
8 * [Issue Queue](https://github.com/semperos/clj-webdriver/issues)
9
03ae48a @semperos Initial commit
authored Mar 11, 2011
10 ## Usage
11
1507bb5 @semperos Make important points more prominent in README
authored Aug 10, 2011
12 ### Important ###
13
14 * This library uses *Clojure 1.3.0-beta1*.
15 * You *must* add the java.net Maven repository to your own `project.clj` when using this library (for example: `:repositories {"java-dot-net" "http://download.java.net/maven/2"}`). The JNA jars required by the latest Selenium-WebDriver release are only available there.
16
17 ### Quickstart ###
01d7b2d @semperos Fix phirsch's issue with WindowHandle not being found due to namespac…
authored May 13, 2011
18
03ae48a @semperos Initial commit
authored Mar 11, 2011
19 Use/require the library in your code:
20
88cc5b5 @semperos Update README to use Github-style md for code blocks
authored Jul 14, 2011
21 ```clj
22 (use 'clj-webdriver.core)
23 ```
03ae48a @semperos Initial commit
authored Mar 11, 2011
24
25 Start up a browser:
26
88cc5b5 @semperos Update README to use Github-style md for code blocks
authored Jul 14, 2011
27 ```clj
28 (def b (start :firefox "https://github.com"))
29 ```
03ae48a @semperos Initial commit
authored Mar 11, 2011
30
735c3cb @semperos Update README and source documentation, clean-up remnants of old READ…
authored Mar 12, 2011
31 At the moment, the best documentation is the source code itself. While there are many functions in the core namespace, they're mostly short and straightforward wrappers around WebDriver API's. For the task of finding elements on the page, I've added some utility functions at the end of the core namespace.
32
33 Here's an example of logging into Github:
03ae48a @semperos Initial commit
authored Mar 11, 2011
34
88cc5b5 @semperos Update README to use Github-style md for code blocks
authored Jul 14, 2011
35 ```clj
36 ;; Start the browser and bind it to `b`
37 (def b (start :firefox "https://github.com"))
38
39 ;; Click "Login" link
40 (-> b
41 (find-it {:text "Login"})
42 click)
43
44 ;; Input username/email into the "Login or Email" field
45 (-> b
46 (find-it {:class "text", :name "login"}) ; use multiple attributes
47 (input-text "username"))
48
49 ;; Input password into the "Password" field
50 (-> b
51 (find-it {:xpath "//input[@id='password']"}) ; :xpath and :css options
52 (input-text "password"))
53
54 ;; Click the "Log in" button"
55 (-> b
56 (find-it :input {:value #"(?i)log"}) ; use of regular expressions
57 click)
58 ```
03ae48a @semperos Initial commit
authored Mar 11, 2011
59
250370c @semperos Update README language to reflect use of generic seq's instead of for…
authored Mar 14, 2011
60 The key functions for finding an element on the page are `find-it` and `find-them`. The `find-it` function returns the first result that matches the criteria, while `find-them` returns a seq of all matches for the given criteria. Both support the same syntax and set of attributes.
b8fea8d @semperos Update readme with more details, remove 'low level' example
authored Mar 11, 2011
61
46de941 @semperos Update readme with more examples and better break-down of how to use …
authored Mar 14, 2011
62 Here is an overview of the arguments you can pass these functions:
63
d44681e @semperos Update README, more tag options
authored May 13, 2011
64 * **HTML Tag as keyword:** Pass in the name of an HTML tag as a keyword (`:div`, `:a`, `:span`, `:img`, etc.) `(find-it :a)` will find the first `<a>` tag on the page. There are also special keywords such as `:*` (match any tag), `:text` (match textfields and textareas), `:window` (to match an open browser window by title or url)
c69c0d2 @semperos Update readme with more details on usage and reformat some things
authored Mar 15, 2011
65 * **HTML Tag plus attributes:** Pass in the name of an HTML tag as a keyword plus some attributes to describe it. `(find-it :a {:class "external"})` will return the first `<a>` tag with a class of "external"
66 * **HTML attributes alone:** You don't have to pass in a tag. `(find-it {:class "external"})` will find the first element of any tag with class "external"
67 * **Multiple HTML attributes:** You can pass in as many attribute-value pairs as you like. `(find-it {:class "external", :text "Moustache"})` will find the first HTML element on the page with both a class of "external" and visible text of "Moustache"
68 * **Regular Expressions:** Instead of looking for an exact match, you can use Java-style regular expressions to find elements. `(find-it :a {:class #"exter"})` will find the first `<a>` tag with a class which matches the regular expression `#"exter"`. You can also use regexes in the final position of an ancestry-based query (see below).
d44681e @semperos Update README, more tag options
authored May 13, 2011
69 * **Ancestry-based queries:** This library provides a pure-Clojure mechanism for finding an element based on parent elements. `(find-it [:div {:id "content"}, :a {:class "external"}])` will find the first `<a>` tag with a class of "external" that is located within the `<div>` with id "content". This is equivalent to the XPath `//div[@id='content']//a[@class='external']`. You can also include regular expressions in the final attribute-value map which you supply. (*Note: Due to issues of ambiguity and in order not to reinvent the wheel any further, applying regexes higher up the query is not supported and will cause an exception. In addition, none of the "semantic" tags such as `:button*`, `:radio`, `:checkbox`, `:textfield`, etc. that do not map directly to HTML tags are not supported. If you need more advanced querying, use XPath or CSS selectors directly.)*
0565378 @semperos Update readme to accurately reflect how :xpath and :css are handled
authored Apr 9, 2011
70 * **XPath and CSS Selectors:** You can use the `:xpath` and `:css` attributes to use such queries in place of simple HTML attributes. If you use one of these attributes, you shouldn't use any others, as they will be ignored (e.g. `{:xpath "//a", :class "external"}` will only utilize the xpath `//a`). `(find-it {:xpath "//a[@class='external']"})` will return the first `<a>` tag with a class of "external"
46de941 @semperos Update readme with more examples and better break-down of how to use …
authored Mar 14, 2011
71
250370c @semperos Update README language to reflect use of generic seq's instead of for…
authored Mar 14, 2011
72 As mentioned above, the `find-it` and `find-them` functions share the same features and syntax; `find-it` returns a single element, `find-them` returns a seq of all matched elements.
46de941 @semperos Update readme with more examples and better break-down of how to use …
authored Mar 14, 2011
73
c36bba7 @semperos Update alternative find-it functions to take a map of attr-val just l…
authored Mar 12, 2011
74 To demonstrate how to use arguments in different ways, consider the following example. If I wanted to find `<a href="/contact" id="contact-link" class="menu-item" name="contact">Contact Us</a>` in a page and click on it I could perform any of the following:
75
88cc5b5 @semperos Update README to use Github-style md for code blocks
authored Jul 14, 2011
76 ```clj
77 (-> b
78 (find-it :a) ; assuming its the first <a> on the page
79 click)
80
81 (-> b
82 (find-it {:id "contact-link"}) ; :id is unique, so only one is needed
83 click)
84
85 (-> b
86 (find-it {:class "menu-item", :name "contact"}) ; use multiple attributes
87 click)
88
89 (-> b
90 (find-it :a {:class "menu-item", :name "contact"}) ; specify tag
91 click)
92
93 (-> b
94 (find-it :a {:text "Contact Us"}) ; special :text attribute, uses XPath's
95 click) ; text() function to find the element
96
97 (-> b
98 (find-it :a {:class #"(?i)menu-"}) ; use Java-style regular
99 click) ; expressions
100
101 (-> b
102 (find-it [:div {:id "content"}, :a {:id "contact-link"}]) ; hierarchical/ancestry-based query
103 click) ; equivalent to
104 ; //div[@id='content']//a[@id='contact-link']
105
106 (-> b
107 (find-it [:div {:id "content"}, :a {}]) ; ancestry-based query, tag with
108 click) ; no attributes (empty map required)
109
110 (-> b
111 (find-it {:xpath "//a[@id='contact-link']"}) ; XPath query
112 click)
c36bba7 @semperos Update alternative find-it functions to take a map of attr-val just l…
authored Mar 12, 2011
113
88cc5b5 @semperos Update README to use Github-style md for code blocks
authored Jul 14, 2011
114 (-> b
115 (find-it {:css "a#contact-link"}) ; CSS selector
116 click)
117 ```
b8fea8d @semperos Update readme with more details, remove 'low level' example
authored Mar 11, 2011
118
735c3cb @semperos Update README and source documentation, clean-up remnants of old READ…
authored Mar 12, 2011
119 So, to describe the general pattern of interacting with the page:
120
88cc5b5 @semperos Update README to use Github-style md for code blocks
authored Jul 14, 2011
121 ```clj
122 (-> browser-instance
123 (find-it options)
124 (do-something-with-the-element))
125 ```
03ae48a @semperos Initial commit
authored Mar 11, 2011
126
5e8d682 @semperos Add info on Firefox-specific functionality and provide code examples
authored Mar 15, 2011
127 ### Firefox Functionality
128
129 Support for Firefox currently exceeds that for all other browsers, most notably via support for customizable Firefox profiles. I've included support for several of these advanced featues in the `clj-webdriver.firefox` namespace. Here are a few examples (borrowed from [here][wd-ruby-bindings]:
130
88cc5b5 @semperos Update README to use Github-style md for code blocks
authored Jul 14, 2011
131 ```clj
132 (use 'clj-webdriver.core)
133 (require '[clj-webdriver.firefox :as ff])
134
135 (def b (new-driver :firefox
136 (doto (ff/new-profile)
137 ;; Enable Firebug
138 (ff/enable-extension "/path/to/extensions/firebug.xpi")))
139
140 ;; Auto-download certain file types to a specific folder
141 (ff/set-preferences {:browser.download.dir "C:/Users/semperos/Desktop",
142 :browser.download.folderList 2
143 :browser.helperApps.neverAsk.saveToDisk "application/pdf"})))
144 ```
5e8d682 @semperos Add info on Firefox-specific functionality and provide code examples
authored Mar 15, 2011
145
146
ed9aefb @semperos Update README with information about running test suite
authored Mar 11, 2011
147 ## Running Tests
148
149 The namespace `clj-webdriver.test.example-app.core` contains a [Ring][ring-github] app (routing by [Moustache][moustache-github]) that acts as my "control application" for this project's test suite. Instead of running my tests against a remote server on the Internet (prone to change, not always available), I've packaged this small web application to be run locally for the purposes of testing.
150
151 Due to some Java server/socket issues, you cannot start both this Ring app and the WebDriver browser instance in the test itself (in this situation, the Ring app starts and WebDriver opens the browser, but then a host of errors follow).
152
153 Here's how I run these tests:
154
155 * Open a terminal and run `lein repl` or `lein swank` at the root of this project
735c3cb @semperos Update README and source documentation, clean-up remnants of old READ…
authored Mar 12, 2011
156 * Evaluate `(use 'clj-webdriver.test.example-app.core 'ring.adapter.jetty)`
d4239b9 @semperos Change default testing port to ASCII code for WD
authored Aug 10, 2011
157 * Evaluate `(defonce my-server (run-jetty #'routes {:port 5744, :join? false}))`, making sure to adjust the `test-port` in `test/clj_webdriver/test/core.clj` to whatever you use here.
ed9aefb @semperos Update README with information about running test suite
authored Mar 11, 2011
158 * Open a new terminal tab/window and run `lein test` at the root of this project
159
160 The last test in the suite closes the WebDriver browser instance; you can stop the Jetty server by evaluating `(.stop my-server)` or just killing the REPL with `Ctrl+C` or `C-c C-c`.
161
162 If anyone can figure out how to solve this issue (i.e. be able to run just `lein test` and start both the Ring app and WebDriver browser instance in one go), I'd be most appreciative. Until then, testing multiple server-based apps in separate "sandboxes" is acceptable to me.
163
03ae48a @semperos Initial commit
authored Mar 11, 2011
164 ## License
165
166 Distributed under the Eclipse Public License, the same as Clojure.
167
168 [webdriver-orig]: https://github.com/mikitebeka/webdriver-clj
ed9aefb @semperos Update README with information about running test suite
authored Mar 11, 2011
169 [ring-github]: https://github.com/mmcgrana/ring
170 [moustache-github]: https://github.com/cgrand/moustache
5e8d682 @semperos Add info on Firefox-specific functionality and provide code examples
authored Mar 15, 2011
171 [wd-ruby-bindings]: http://code.google.com/p/selenium/wiki/RubyBindings
Something went wrong with that request. Please try again.