Skip to content
Newer
Older
100644 162 lines (114 sloc) 8.97 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
5 ## Usage
6
e09997f @semperos Put Clojure 1.2.1 requirement at very beginning of usage section
authored May 13, 2011
7 **Clojure version 1.2.1 is required to use this library** due to a breaking change between Clojure versions 1.2.0 and 1.2.1 with regards to namespaces with dashes.
01d7b2d @semperos Fix phirsch's issue with WindowHandle not being found due to namespac…
authored May 13, 2011
8
03ae48a @semperos Initial commit
authored Mar 11, 2011
9 Use/require the library in your code:
10
88cc5b5 @semperos Update README to use Github-style md for code blocks
authored Jul 14, 2011
11 ```clj
12 (use 'clj-webdriver.core)
13 ```
03ae48a @semperos Initial commit
authored Mar 11, 2011
14
15 Start up a browser:
16
88cc5b5 @semperos Update README to use Github-style md for code blocks
authored Jul 14, 2011
17 ```clj
18 (def b (start :firefox "https://github.com"))
19 ```
03ae48a @semperos Initial commit
authored Mar 11, 2011
20
735c3cb @semperos Update README and source documentation, clean-up remnants of old READ…
authored Mar 12, 2011
21 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.
22
23 Here's an example of logging into Github:
03ae48a @semperos Initial commit
authored Mar 11, 2011
24
88cc5b5 @semperos Update README to use Github-style md for code blocks
authored Jul 14, 2011
25 ```clj
26 ;; Start the browser and bind it to `b`
27 (def b (start :firefox "https://github.com"))
28
29 ;; Click "Login" link
30 (-> b
31 (find-it {:text "Login"})
32 click)
33
34 ;; Input username/email into the "Login or Email" field
35 (-> b
36 (find-it {:class "text", :name "login"}) ; use multiple attributes
37 (input-text "username"))
38
39 ;; Input password into the "Password" field
40 (-> b
41 (find-it {:xpath "//input[@id='password']"}) ; :xpath and :css options
42 (input-text "password"))
43
44 ;; Click the "Log in" button"
45 (-> b
46 (find-it :input {:value #"(?i)log"}) ; use of regular expressions
47 click)
48 ```
03ae48a @semperos Initial commit
authored Mar 11, 2011
49
250370c @semperos Update README language to reflect use of generic seq's instead of for…
authored Mar 14, 2011
50 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
51
46de941 @semperos Update readme with more examples and better break-down of how to use …
authored Mar 14, 2011
52 Here is an overview of the arguments you can pass these functions:
53
d44681e @semperos Update README, more tag options
authored May 13, 2011
54 * **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
55 * **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"
56 * **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"
57 * **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"
58 * **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
59 * **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
60 * **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
61
250370c @semperos Update README language to reflect use of generic seq's instead of for…
authored Mar 14, 2011
62 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
63
c36bba7 @semperos Update alternative find-it functions to take a map of attr-val just l…
authored Mar 12, 2011
64 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:
65
88cc5b5 @semperos Update README to use Github-style md for code blocks
authored Jul 14, 2011
66 ```clj
67 (-> b
68 (find-it :a) ; assuming its the first <a> on the page
69 click)
70
71 (-> b
72 (find-it {:id "contact-link"}) ; :id is unique, so only one is needed
73 click)
74
75 (-> b
76 (find-it {:class "menu-item", :name "contact"}) ; use multiple attributes
77 click)
78
79 (-> b
80 (find-it :a {:class "menu-item", :name "contact"}) ; specify tag
81 click)
82
83 (-> b
84 (find-it :a {:text "Contact Us"}) ; special :text attribute, uses XPath's
85 click) ; text() function to find the element
86
87 (-> b
88 (find-it :a {:class #"(?i)menu-"}) ; use Java-style regular
89 click) ; expressions
90
91 (-> b
92 (find-it [:div {:id "content"}, :a {:id "contact-link"}]) ; hierarchical/ancestry-based query
93 click) ; equivalent to
94 ; //div[@id='content']//a[@id='contact-link']
95
96 (-> b
97 (find-it [:div {:id "content"}, :a {}]) ; ancestry-based query, tag with
98 click) ; no attributes (empty map required)
99
100 (-> b
101 (find-it {:xpath "//a[@id='contact-link']"}) ; XPath query
102 click)
c36bba7 @semperos Update alternative find-it functions to take a map of attr-val just l…
authored Mar 12, 2011
103
88cc5b5 @semperos Update README to use Github-style md for code blocks
authored Jul 14, 2011
104 (-> b
105 (find-it {:css "a#contact-link"}) ; CSS selector
106 click)
107 ```
b8fea8d @semperos Update readme with more details, remove 'low level' example
authored Mar 11, 2011
108
735c3cb @semperos Update README and source documentation, clean-up remnants of old READ…
authored Mar 12, 2011
109 So, to describe the general pattern of interacting with the page:
110
88cc5b5 @semperos Update README to use Github-style md for code blocks
authored Jul 14, 2011
111 ```clj
112 (-> browser-instance
113 (find-it options)
114 (do-something-with-the-element))
115 ```
03ae48a @semperos Initial commit
authored Mar 11, 2011
116
5e8d682 @semperos Add info on Firefox-specific functionality and provide code examples
authored Mar 15, 2011
117 ### Firefox Functionality
118
119 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]:
120
88cc5b5 @semperos Update README to use Github-style md for code blocks
authored Jul 14, 2011
121 ```clj
122 (use 'clj-webdriver.core)
123 (require '[clj-webdriver.firefox :as ff])
124
125 (def b (new-driver :firefox
126 (doto (ff/new-profile)
127 ;; Enable Firebug
128 (ff/enable-extension "/path/to/extensions/firebug.xpi")))
129
130 ;; Auto-download certain file types to a specific folder
131 (ff/set-preferences {:browser.download.dir "C:/Users/semperos/Desktop",
132 :browser.download.folderList 2
133 :browser.helperApps.neverAsk.saveToDisk "application/pdf"})))
134 ```
5e8d682 @semperos Add info on Firefox-specific functionality and provide code examples
authored Mar 15, 2011
135
136
ed9aefb @semperos Update README with information about running test suite
authored Mar 11, 2011
137 ## Running Tests
138
139 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.
140
141 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).
142
143 Here's how I run these tests:
144
145 * 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
146 * Evaluate `(use 'clj-webdriver.test.example-app.core 'ring.adapter.jetty)`
ed9aefb @semperos Update README with information about running test suite
authored Mar 11, 2011
147 * Evaluate `(defonce my-server (run-jetty #'routes {:port 8080, :join? false}))`
148 * Open a new terminal tab/window and run `lein test` at the root of this project
149
150 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`.
151
152 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.
153
03ae48a @semperos Initial commit
authored Mar 11, 2011
154 ## License
155
156 Distributed under the Eclipse Public License, the same as Clojure.
157
158 [webdriver-orig]: https://github.com/mikitebeka/webdriver-clj
ed9aefb @semperos Update README with information about running test suite
authored Mar 11, 2011
159 [ring-github]: https://github.com/mmcgrana/ring
160 [moustache-github]: https://github.com/cgrand/moustache
5e8d682 @semperos Add info on Firefox-specific functionality and provide code examples
authored Mar 15, 2011
161 [wd-ruby-bindings]: http://code.google.com/p/selenium/wiki/RubyBindings
Something went wrong with that request. Please try again.