Coder Social home page Coder Social logo

kerodon's People

Contributors

ayato-p avatar cgore avatar danielcompton avatar dotemacs avatar frozenlock avatar glenjamin avatar jayp avatar jbswetnam avatar johncowie avatar philandstuff avatar saivlis avatar seanhussey avatar sky-glenjamin avatar thegeez avatar tobiasbayer avatar tokenshift avatar wjlroe avatar xeqi avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kerodon's Issues

Support interacting with radio buttons

My current plan was to implement the following

(defn pick [state selector])

This would work similarly to the (choose) implementation, unchecking all radio boxes with the same name, and then checking the one requested.

Release new Kerodon to Clojars

Please, release Kerodon 0.3.0. Version 0.2.0 on Clojars is outdated and doesn't handle things I need to use.

(is there any other solution? lein checkouts?)

Kerodon incorrectly uses query-string when submitting form

When we (press "save") on this form:

<form action="/myform?email=hi>
  <input hidden="email" value="hello"/>
  <input type="submit" value="save"/>
</form>

Kerodon will wrongly reuse the query string resulting in a request path of /myform?email=hi&email=hello. This is inconsistent with the behaviour I see in my browser (latest chrome). Kerodon is also wrong according to specifications mentioned here [1].

This problem surfaces when the parameters are parsed with ring.middleware.params/wrap-params this results in {"email" ["hi" "hello"]} instead of {"email" "hello"}.

[1] https://stackoverflow.com/questions/1116019/when-submitting-a-get-form-the-query-string-is-removed-from-the-action-url/9882750#9882750

Sending origin and referer headers

My app makes use of the origin and referer headers for some functionality. It would be handy if kerodon automatically detected and provided origin and referer headers. Is this something that could be accepted in a PR?

More complete form element support

Here's a rough outline for the work I'm planning to support HTML forms more completely:

Select box support, picking values and being submitted with the form

(choose "Field" "value")

Checkbox and radio button support, picking values and submitting in the same way a browser would

(pick "Field")

Support for finding elements by placeholder.
I'm not as sure as this one, but the idea is to support fields like this:

<input name="query" type="search" placeholder="Search..." />

My rough implementation plan at the moment is to try and pull some of the common behaviour between form fields into a FormField protocol, I think this will look something like the following, but unsure whether this is actually a good idea.

(defprotocol FormField
   "Common behaviour for form fields"
   (field-name [this node] "name of the field for form submission")
   (field-value [this node] "value of the field for form submission")
   (set-field-value! [this node value] "update the value of the field in this enlive resource"))

(deftype InputField [selector]
  FormField
  (field-name [this node] (-> (enlive/select node [selector]) first :attrs :name))
  ; ...
  )

Typing this out here, I'm less sure it'll work well - but I'll try and implement something to see how it pans out, form-element would have to be changed to return types that implement FormField, maybe also becoming a multimethod so that both the factory and the available types are extensible by third parties?

I'd appreciate any input on this :)

Input file array coerced incorrectly

I noticed that a test case in my project was failing because an empty file-input element would result in an entry in the kerodon-generated request map like :

:some-key {:0 "" :1 ""}

Where as a browser (tested it with firefox) would generate a request map without such entry.
I am working around it by performing some filtering so that it works both for kerodon and an actual browser.

Just though It would be nice if kerodon can be consistent with an actual browser when possible.

Thanks for the awesome project!

Exception when any a tag contains other tags

If there are any <a> tags that contain other HTML tags like images or spans, then an error is thrown.

Okay:

<a href="/">Home</a>

Error:

<a href="/"><span>Home</span></a>

Note the error occurs when (follow "whatever") is used.

ERROR in (swirl-security) (string.clj:236)
Uncaught exception, not in assertion.
expected: nil
  actual: java.lang.ClassCastException: clojure.lang.PersistentStructMap cannot be cast to java.lang.CharSequence
 at clojure.string$trim.invoke (string.clj:236)
    clojure.core$map$fn__4245.invoke (core.clj:2559)
    clojure.lang.LazySeq.sval (LazySeq.java:40)
    clojure.lang.LazySeq.seq (LazySeq.java:49)
    clojure.lang.LazySeq.equals (LazySeq.java:115)
    clojure.lang.LazySeq.equiv (LazySeq.java:100)
    clojure.lang.Util.pcequiv (Util.java:124)
    clojure.lang.Util.equiv (Util.java:32)
    kerodon.impl$css_or_content$fn__16846.invoke (impl.clj:30)
    net.cgrand.enlive_html$pred$fn__16009.invoke (enlive_html.clj:241)
    net.cgrand.enlive_html$zip_pred$fn__16004.invoke (enlive_html.clj:236)
    net.cgrand.enlive_html$intersection$fn__16043.invoke (enlive_html.clj:282)
    net.cgrand.enlive_html$predset$fn__16137.invoke (enlive_html.clj:329)
    clojure.core$comp$fn__4192.invoke (core.clj:2403)
    net.cgrand.enlive_html$step.invoke (enlive_html.clj:390)
    net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__16290.invoke (enlive_html.clj:497)
    net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__16290$fn__16291.invoke (enlive_html.clj:498)
    clojure.core$map$fn__4245.invoke (core.clj:2559)
    clojure.lang.LazySeq.sval (LazySeq.java:40)
    clojure.lang.LazySeq.seq (LazySeq.java:49)
    clojure.lang.Cons.next (Cons.java:39)
    clojure.lang.RT.boundedLength (RT.java:1654)
    clojure.lang.RestFn.applyTo (RestFn.java:130)
    clojure.core$apply.invoke (core.clj:624)
    clojure.core$mapcat.doInvoke (core.clj:2586)
    clojure.lang.RestFn.invoke (RestFn.java:423)
    net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__16290.invoke (enlive_html.clj:498)
    net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__16290$fn__16291.invoke (enlive_html.clj:498)
    clojure.core$map$fn__4245.invoke (core.clj:2559)
    clojure.lang.LazySeq.sval (LazySeq.java:40)
    clojure.lang.LazySeq.seq (LazySeq.java:49)
    clojure.lang.Cons.next (Cons.java:39)
    clojure.lang.RT.boundedLength (RT.java:1654)
    clojure.lang.RestFn.applyTo (RestFn.java:130)
    clojure.core$apply.invoke (core.clj:624)
    clojure.core$mapcat.doInvoke (core.clj:2586)
    clojure.lang.RestFn.invoke (RestFn.java:423)
    net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__16290.invoke (enlive_html.clj:498)
    net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__16290$fn__16291.invoke (enlive_html.clj:498)
    clojure.core$map$fn__4245.invoke (core.clj:2559)
    clojure.lang.LazySeq.sval (LazySeq.java:40)
    clojure.lang.LazySeq.seq (LazySeq.java:49)
    clojure.lang.Cons.next (Cons.java:39)
    clojure.lang.RT.boundedLength (RT.java:1654)
    clojure.lang.RestFn.applyTo (RestFn.java:130)
    clojure.core$apply.invoke (core.clj:624)
    clojure.core$mapcat.doInvoke (core.clj:2586)
    clojure.lang.RestFn.invoke (RestFn.java:423)
    net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__16290.invoke (enlive_html.clj:498)
    net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__16290$fn__16291.invoke (enlive_html.clj:498)
    clojure.core$map$fn__4245.invoke (core.clj:2559)
    clojure.lang.LazySeq.sval (LazySeq.java:40)
    clojure.lang.LazySeq.seq (LazySeq.java:49)
    clojure.lang.Cons.next (Cons.java:39)
    clojure.lang.RT.boundedLength (RT.java:1654)
    clojure.lang.RestFn.applyTo (RestFn.java:130)
    clojure.core$apply.invoke (core.clj:624)
    clojure.core$mapcat.doInvoke (core.clj:2586)
    clojure.lang.RestFn.invoke (RestFn.java:423)
    net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__16290.invoke (enlive_html.clj:498)
    net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__16290$fn__16291.invoke (enlive_html.clj:498)
    clojure.core$map$fn__4245.invoke (core.clj:2559)
    clojure.lang.LazySeq.sval (LazySeq.java:40)
    clojure.lang.LazySeq.seq (LazySeq.java:49)
    clojure.lang.Cons.next (Cons.java:39)
    clojure.lang.RT.boundedLength (RT.java:1654)
    clojure.lang.RestFn.applyTo (RestFn.java:130)
    clojure.core$apply.invoke (core.clj:624)
    clojure.core$mapcat.doInvoke (core.clj:2586)
    clojure.lang.RestFn.invoke (RestFn.java:423)
    net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__16290.invoke (enlive_html.clj:498)
    net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__16290$fn__16291.invoke (enlive_html.clj:498)
    clojure.core$map$fn__4245.invoke (core.clj:2559)
    clojure.lang.LazySeq.sval (LazySeq.java:40)
    clojure.lang.LazySeq.seq (LazySeq.java:49)
    clojure.lang.Cons.next (Cons.java:39)
    clojure.lang.RT.boundedLength (RT.java:1654)
    clojure.lang.RestFn.applyTo (RestFn.java:130)
    clojure.core$apply.invoke (core.clj:624)
    clojure.core$mapcat.doInvoke (core.clj:2586)
    clojure.lang.RestFn.invoke (RestFn.java:423)
    net.cgrand.enlive_html$zip_select_nodes_STAR_$select1__16290.invoke (enlive_html.clj:498)
    net.cgrand.enlive_html$zip_select_nodes_STAR_$fn__16295.invoke (enlive_html.clj:500)
    clojure.core$map$fn__4245.invoke (core.clj:2559)
    clojure.lang.LazySeq.sval (LazySeq.java:40)
    clojure.lang.LazySeq.seq (LazySeq.java:49)
    clojure.lang.RT.seq (RT.java:484)
    clojure.core$seq.invoke (core.clj:133)
    clojure.core$apply.invoke (core.clj:624)
    clojure.core$mapcat.doInvoke (core.clj:2586)
    clojure.lang.RestFn.invoke (RestFn.java:423)
    net.cgrand.enlive_html$zip_select_nodes_STAR_.invoke (enlive_html.clj:500)
    net.cgrand.enlive_html$select_nodes_STAR_.invoke (enlive_html.clj:504)
    net.cgrand.enlive_html$select.invoke (enlive_html.clj:543)
    kerodon.impl$link.invoke (impl.clj:83)
    kerodon.impl$find_url.invoke (impl.clj:213)
    kerodon.core$follow.invoke (core.clj:19)
    yswrl.features.swirl_features/fn (swirl_features.clj:52)
    clojure.test$test_var$fn__7187.invoke (test.clj:704)
    clojure.test$test_var.invoke (test.clj:704)
    clojure.test$test_vars$fn__7209$fn__7214.invoke (test.clj:722)
    clojure.test$default_fixture.invoke (test.clj:674)
    clojure.test$test_vars$fn__7209.invoke (test.clj:722)
    clojure.test$default_fixture.invoke (test.clj:674)
    clojure.test$test_vars.invoke (test.clj:718)
    clojure.test$test_all_vars.invoke (test.clj:728)
    clojure.test$test_ns.invoke (test.clj:747)
    clojure.core$map$fn__4245.invoke (core.clj:2559)
    clojure.lang.LazySeq.sval (LazySeq.java:40)
    clojure.lang.LazySeq.seq (LazySeq.java:49)
    clojure.lang.Cons.next (Cons.java:39)
    clojure.lang.RT.next (RT.java:598)
    clojure.core$next.invoke (core.clj:64)
    clojure.core$reduce1.invoke (core.clj:903)
    clojure.core$reduce1.invoke (core.clj:894)
    clojure.core$merge_with.doInvoke (core.clj:2777)
    clojure.lang.RestFn.applyTo (RestFn.java:139)
    clojure.core$apply.invoke (core.clj:626)
    clojure.test$run_tests.doInvoke (test.clj:762)
    clojure.lang.RestFn.applyTo (RestFn.java:137)
    clojure.core$apply.invoke (core.clj:624)
    com.jakemccrary.test_refresh$run_selected_tests$fn__656.invoke (test_refresh.clj:129)
    com.jakemccrary.test_refresh$suppress_unselected_tests.invoke (test_refresh.clj:103)
    com.jakemccrary.test_refresh$run_selected_tests.invoke (test_refresh.clj:127)
    com.jakemccrary.test_refresh$run_tests.invoke (test_refresh.clj:135)
    com.jakemccrary.test_refresh$monitor_project$fn__672.invoke (test_refresh.clj:192)
    com.jakemccrary.test_refresh$monitor_project.invoke (test_refresh.clj:185)
    user$eval730.invoke (form-init5254813364040845940.clj:1)
    clojure.lang.Compiler.eval (Compiler.java:6703)
    clojure.lang.Compiler.eval (Compiler.java:6693)
    clojure.lang.Compiler.load (Compiler.java:7130)
    clojure.lang.Compiler.loadFile (Compiler.java:7086)
    clojure.main$load_script.invoke (main.clj:274)
    clojure.main$init_opt.invoke (main.clj:279)
    clojure.main$initialize.invoke (main.clj:307)
    clojure.main$null_opt.invoke (main.clj:342)
    clojure.main$main.doInvoke (main.clj:420)
    clojure.lang.RestFn.invoke (RestFn.java:421)
    clojure.lang.Var.invoke (Var.java:383)
    clojure.lang.AFn.applyToHelper (AFn.java:156)
    clojure.lang.Var.applyTo (Var.java:700)
    clojure.main.main (main.java:37)

Kerodon redirects me to not existing URL

I have a test:

(ns sprint-is.test.routes.auth
    (:use [kerodon.core]
        [kerodon.test]
        [clojure.test]
        [korma.core])
    (:require
        [sprint-is.modules.users]
        [sprint-is.handler]))

(defn setup-db [] 
    (do 
        (delete sprint-is.modules.users/users) 
        (insert sprint-is.modules.users/users (values 
            {:id 1 :email "[email protected]" :salt "salt" :password (sprint-is.modules.users/hash-password "pass" "salt")}))))


(deftest user-can-have-bad-password
    (setup-db)
    (-> 
        (session sprint-is.handler/app)
        (visit "/sign/in")
        (fill-in "E-mail" "[email protected]")
        (fill-in "Password" "bad password")
        (press "Prihlasit")
        (has (text? "Bad Password"))))

And Route:

(ns sprint-is.routes.auth
  (:use compojure.core)
  (:use sprint-is.libs.form)
  (:use flatland.ordered.map)
  (:use sprint-is.libs.errors)
  (:require [sprint-is.views.layout :as layout]
            [noir.response :as response]
            [sprint-is.modules.users :as users]
            [noir.session :as session]
            ))

(defform login-form (ordered-map
    :email {:type :text :value "" :label "E-mail" :errors []}
    :password {:type :password :value "" :label "Password" :errors []}
    :submit {:type :submit :value "Prihlasit" :label "" :errors []}))

(defn login-page
  ([] (login-page (session/flash-get :message)))
  ([message] (layout/render "login.html" {:message message :form (render-form login-form)})))

(defn process-login [email password] 
  (let-or-error (users/login email password) 
    (fn [user] (session/put! :user user) (response/redirect "/"))
    (fn [error] (login-page (error :message)))))


(defn logout-page []
  (session/clear!)
  (response/redirect "/sign/in"))

(defroutes auth-routes
  (GET "/sign/in" [] (login-page))
  (POST "/sign/in" [email password] (process-login email password))
  (GET "/sign/out" [] (logout-page)))

When I run test, Kerodon runs the code, fill in form and click login, but it goes to URL /sign/ instead of /sign/in (after submitting form) so I get "Not found" page. When I (prn) page after (visit "/sign/in"), {:request {:uri}} is "sign/in", after (press "Prihlasit"), the {:request {:uri}} is "/sign/". Form action is empty string

Cannot find a select element

I have a page that has multiple input tags, all of which are found without issue, and a single select, which kerodon cannot find. I have added a println into the test flow just above where the error occurs:

(deftest user-record-created-on-signup
  (let [response (read-string (slurp "test/data/nest_access_token.clj"))]
    (fake-http/with-fake-http [nest/token-url response]
      (-> (session handler/app)
        (visit "/users/new")
        (fill-in "email" "[email protected]")
        (fill-in "password" "password")
        (fill-in "confirm password" "password")
        (fill-in "phone number" "123-456-7890")
        (println)
        (choose "timezone" "America/New_York")
        (fill-in "nest pin" "1234")
        (press "submit")
        (follow-redirect)
        (has (some-text? "Welcome [email protected]"))))))

All the output is pasted below, which includes the rendered html. The issue is in finding the "timezone" dropdown.

Thanks for any help!

ask-nest.core=> (clojure.test/run-tests 'ask-nest.integration.new-user-test)

Testing ask-nest.integration.new-user-test
{:response {:status 200, :headers {X-Content-Type-Options nosniff, X-Frame-Options SAMEORIGIN, X-XSS-Protection 1; mode=block, Set-Cookie (ring-session=eee00742-3b90-45c0-86ef-071287b29443;Path=/;HttpOnly), Content-Type text/html; charset=utf-8}, :body <!DOCTYPE html>
<html>
<head>
  <title>Whendows </title>
</head>

<body>
  <div id="users-new">

<header>
  <h1>Sign Up</h1>
</header>
<form action="/users" method="post">
  <input id="__anti-forgery-token" name="__anti-forgery-token" type="hidden" value="oLjni6mRPBWb1VPUnRhsc8bILkqOV4ombnZ2XdiVnuwPEL6n2IJ/J16/5FXCDv9meWhpG+YrcwC4MBsl" />
  <label for="email">
    email
    <input type="email" name="email" id="email" />
  </label>
  <label for="password">
    password
    <input type="password" name="password" id="password" />
  </label>
  <label for="confirm-password">
    confirm password
    <input type="password" name="confirm-password" id="confirm-password" />
  </label>
  <label for="phone-number">
    phone number
    <input type="tel" name="phone-number" id="phone-number" />
  </label>
  <label for="timezone">
    timezone
    <select id="timezone" name="timezone">

        <option>Etc/GMT+12</option>

        <option>Etc/GMT+11</option>

        <option>Pacific/Apia</option>

        <option>Pacific/Midway</option>

        <option>Pacific/Niue</option>

        <option>Pacific/Pago_Pago</option>

        <option>America/Adak</option>

        <option>Etc/GMT+10</option>

        <option>HST</option>

        <option>Pacific/Fakaofo</option>

        <option>Pacific/Honolulu</option>

        <option>Pacific/Johnston</option>

        <option>Pacific/Rarotonga</option>

        <option>Pacific/Tahiti</option>

        <option>Pacific/Marquesas</option>

        <option>America/Anchorage</option>

        <option>America/Juneau</option>

        <option>America/Nome</option>

        <option>America/Yakutat</option>

        <option>Etc/GMT+9</option>

        <option>Pacific/Gambier</option>

        <option>America/Dawson</option>

        <option>America/Los_Angeles</option>

        <option>America/Santa_Isabel</option>

        <option>America/Tijuana</option>

        <option>America/Vancouver</option>

        <option>America/Whitehorse</option>

        <option>Etc/GMT+8</option>

        <option>PST8PDT</option>

        <option>Pacific/Pitcairn</option>

        <option>America/Boise</option>

        <option>America/Cambridge_Bay</option>

        <option>America/Chihuahua</option>

        <option>America/Dawson_Creek</option>

        <option>America/Denver</option>

        <option>America/Edmonton</option>

        <option>America/Hermosillo</option>

        <option>America/Inuvik</option>

        <option>America/Mazatlan</option>

        <option>America/Ojinaga</option>

        <option>America/Phoenix</option>

        <option>America/Yellowknife</option>

        <option>Etc/GMT+7</option>

        <option>MST</option>

        <option>MST7MDT</option>

        <option>America/Bahia_Banderas</option>

        <option>America/Belize</option>

        <option>America/Cancun</option>

        <option>America/Chicago</option>

        <option>America/Costa_Rica</option>

        <option>America/El_Salvador</option>

        <option>America/Guatemala</option>

        <option>America/Indiana/Knox</option>

        <option>America/Indiana/Tell_City</option>

        <option>America/Managua</option>

        <option>America/Matamoros</option>

        <option>America/Menominee</option>

        <option>America/Merida</option>

        <option>America/Mexico_City</option>

        <option>America/Monterrey</option>

        <option>America/North_Dakota/Center</option>

        <option>America/North_Dakota/New_Salem</option>

        <option>America/Rainy_River</option>

        <option>America/Rankin_Inlet</option>

        <option>America/Regina</option>

        <option>America/Swift_Current</option>

        <option>America/Tegucigalpa</option>

        <option>America/Winnipeg</option>

        <option>CST6CDT</option>

        <option>Etc/GMT+6</option>

        <option>Pacific/Easter</option>

        <option>Pacific/Galapagos</option>

        <option>America/Atikokan</option>

        <option>America/Bogota</option>

        <option>America/Cayman</option>

        <option>America/Detroit</option>

        <option>America/Grand_Turk</option>

        <option>America/Guayaquil</option>

        <option>America/Havana</option>

        <option>America/Indiana/Indianapolis</option>

        <option>America/Indiana/Marengo</option>

        <option>America/Indiana/Petersburg</option>

        <option>America/Indiana/Vevay</option>

        <option>America/Indiana/Vincennes</option>

        <option>America/Indiana/Winamac</option>

        <option>America/Iqaluit</option>

        <option>America/Jamaica</option>

        <option>America/Kentucky/Louisville</option>

        <option>America/Kentucky/Monticello</option>

        <option>America/Lima</option>

        <option>America/Montreal</option>

        <option>America/Nassau</option>

        <option>America/New_York</option>

        <option>America/Nipigon</option>

        <option>America/Panama</option>

        <option>America/Pangnirtung</option>

        <option>America/Port-au-Prince</option>

        <option>America/Resolute</option>

        <option>America/Thunder_Bay</option>

        <option>America/Toronto</option>

        <option>EST</option>

        <option>EST5EDT</option>

        <option>Etc/GMT+5</option>

        <option>America/Caracas</option>

        <option>America/Anguilla</option>

        <option>America/Antigua</option>

        <option>America/Argentina/San_Luis</option>

        <option>America/Aruba</option>

        <option>America/Asuncion</option>

        <option>America/Barbados</option>

        <option>America/Blanc-Sablon</option>

        <option>America/Boa_Vista</option>

        <option>America/Campo_Grande</option>

        <option>America/Cuiaba</option>

        <option>America/Curacao</option>

        <option>America/Dominica</option>

        <option>America/Eirunepe</option>

        <option>America/Glace_Bay</option>

        <option>America/Goose_Bay</option>

        <option>America/Grenada</option>

        <option>America/Guadeloupe</option>

        <option>America/Guyana</option>

        <option>America/Halifax</option>

        <option>America/La_Paz</option>

        <option>America/Manaus</option>

        <option>America/Martinique</option>

        <option>America/Moncton</option>

        <option>America/Montserrat</option>

        <option>America/Port_of_Spain</option>

        <option>America/Porto_Velho</option>

        <option>America/Puerto_Rico</option>

        <option>America/Rio_Branco</option>

        <option>America/Santiago</option>

        <option>America/Santo_Domingo</option>

        <option>America/St_Kitts</option>

        <option>America/St_Lucia</option>

        <option>America/St_Thomas</option>

        <option>America/St_Vincent</option>

        <option>America/Thule</option>

        <option>America/Tortola</option>

        <option>Antarctica/Palmer</option>

        <option>Atlantic/Bermuda</option>

        <option>Atlantic/Stanley</option>

        <option>Etc/GMT+4</option>

        <option>America/St_Johns</option>

        <option>America/Araguaina</option>

        <option>America/Argentina/Buenos_Aires</option>

        <option>America/Argentina/Catamarca</option>

        <option>America/Argentina/Cordoba</option>

        <option>America/Argentina/Jujuy</option>

        <option>America/Argentina/La_Rioja</option>

        <option>America/Argentina/Mendoza</option>

        <option>America/Argentina/Rio_Gallegos</option>

        <option>America/Argentina/Salta</option>

        <option>America/Argentina/San_Juan</option>

        <option>America/Argentina/Tucuman</option>

        <option>America/Argentina/Ushuaia</option>

        <option>America/Bahia</option>

        <option>America/Belem</option>

        <option>America/Cayenne</option>

        <option>America/Fortaleza</option>

        <option>America/Godthab</option>

        <option>America/Maceio</option>

        <option>America/Miquelon</option>

        <option>America/Montevideo</option>

        <option>America/Paramaribo</option>

        <option>America/Recife</option>

        <option>America/Santarem</option>

        <option>America/Sao_Paulo</option>

        <option>Antarctica/Rothera</option>

        <option>Etc/GMT+3</option>

        <option>America/Noronha</option>

        <option>Atlantic/South_Georgia</option>

        <option>Etc/GMT+2</option>

        <option>America/Scoresbysund</option>

        <option>Atlantic/Azores</option>

        <option>Atlantic/Cape_Verde</option>

        <option>Etc/GMT+1</option>

        <option>Africa/Abidjan</option>

        <option>Africa/Accra</option>

        <option>Africa/Bamako</option>

        <option>Africa/Banjul</option>

        <option>Africa/Bissau</option>

        <option>Africa/Casablanca</option>

        <option>Africa/Conakry</option>

        <option>Africa/Dakar</option>

        <option>Africa/El_Aaiun</option>

        <option>Africa/Freetown</option>

        <option>Africa/Lome</option>

        <option>Africa/Monrovia</option>

        <option>Africa/Nouakchott</option>

        <option>Africa/Ouagadougou</option>

        <option>Africa/Sao_Tome</option>

        <option>America/Danmarkshavn</option>

        <option>Atlantic/Canary</option>

        <option>Atlantic/Faroe</option>

        <option>Atlantic/Madeira</option>

        <option>Atlantic/Reykjavik</option>

        <option>Atlantic/St_Helena</option>

        <option>Etc/GMT</option>

        <option>Etc/UCT</option>

        <option>Etc/UTC</option>

        <option>Europe/Dublin</option>

        <option>Europe/Lisbon</option>

        <option>Europe/London</option>

        <option>UTC</option>

        <option>WET</option>

        <option>Africa/Algiers</option>

        <option>Africa/Bangui</option>

        <option>Africa/Brazzaville</option>

        <option>Africa/Ceuta</option>

        <option>Africa/Douala</option>

        <option>Africa/Kinshasa</option>

        <option>Africa/Lagos</option>

        <option>Africa/Libreville</option>

        <option>Africa/Luanda</option>

        <option>Africa/Malabo</option>

        <option>Africa/Ndjamena</option>

        <option>Africa/Niamey</option>

        <option>Africa/Porto-Novo</option>

        <option>Africa/Tunis</option>

        <option>Africa/Windhoek</option>

        <option>CET</option>

        <option>Etc/GMT-1</option>

        <option>Europe/Amsterdam</option>

        <option>Europe/Andorra</option>

        <option>Europe/Belgrade</option>

        <option>Europe/Berlin</option>

        <option>Europe/Brussels</option>

        <option>Europe/Budapest</option>

        <option>Europe/Copenhagen</option>

        <option>Europe/Gibraltar</option>

        <option>Europe/Luxembourg</option>

        <option>Europe/Madrid</option>

        <option>Europe/Malta</option>

        <option>Europe/Monaco</option>

        <option>Europe/Oslo</option>

        <option>Europe/Paris</option>

        <option>Europe/Prague</option>

        <option>Europe/Rome</option>

        <option>Europe/Stockholm</option>

        <option>Europe/Tirane</option>

        <option>Europe/Vaduz</option>

        <option>Europe/Vienna</option>

        <option>Europe/Warsaw</option>

        <option>Europe/Zurich</option>

        <option>MET</option>

        <option>Africa/Blantyre</option>

        <option>Africa/Bujumbura</option>

        <option>Africa/Cairo</option>

        <option>Africa/Gaborone</option>

        <option>Africa/Harare</option>

        <option>Africa/Johannesburg</option>

        <option>Africa/Kigali</option>

        <option>Africa/Lubumbashi</option>

        <option>Africa/Lusaka</option>

        <option>Africa/Maputo</option>

        <option>Africa/Maseru</option>

        <option>Africa/Mbabane</option>

        <option>Africa/Tripoli</option>

        <option>Asia/Amman</option>

        <option>Asia/Beirut</option>

        <option>Asia/Damascus</option>

        <option>Asia/Gaza</option>

        <option>Asia/Jerusalem</option>

        <option>Asia/Nicosia</option>

        <option>EET</option>

        <option>Etc/GMT-2</option>

        <option>Europe/Athens</option>

        <option>Europe/Bucharest</option>

        <option>Europe/Chisinau</option>

        <option>Europe/Helsinki</option>

        <option>Europe/Istanbul</option>

        <option>Europe/Kaliningrad</option>

        <option>Europe/Kiev</option>

        <option>Europe/Minsk</option>

        <option>Europe/Riga</option>

        <option>Europe/Simferopol</option>

        <option>Europe/Sofia</option>

        <option>Europe/Tallinn</option>

        <option>Europe/Uzhgorod</option>

        <option>Europe/Vilnius</option>

        <option>Europe/Zaporozhye</option>

        <option>Africa/Addis_Ababa</option>

        <option>Africa/Asmara</option>

        <option>Africa/Dar_es_Salaam</option>

        <option>Africa/Djibouti</option>

        <option>Africa/Kampala</option>

        <option>Africa/Khartoum</option>

        <option>Africa/Mogadishu</option>

        <option>Africa/Nairobi</option>

        <option>Antarctica/Syowa</option>

        <option>Asia/Aden</option>

        <option>Asia/Baghdad</option>

        <option>Asia/Bahrain</option>

        <option>Asia/Kuwait</option>

        <option>Asia/Qatar</option>

        <option>Asia/Riyadh</option>

        <option>Etc/GMT-3</option>

        <option>Europe/Moscow</option>

        <option>Europe/Samara</option>

        <option>Europe/Volgograd</option>

        <option>Indian/Antananarivo</option>

        <option>Indian/Comoro</option>

        <option>Indian/Mayotte</option>

        <option>Asia/Tehran</option>

        <option>Asia/Baku</option>

        <option>Asia/Dubai</option>

        <option>Asia/Muscat</option>

        <option>Asia/Tbilisi</option>

        <option>Asia/Yerevan</option>

        <option>Etc/GMT-4</option>

        <option>Indian/Mahe</option>

        <option>Indian/Mauritius</option>

        <option>Indian/Reunion</option>

        <option>Asia/Kabul</option>

        <option>Antarctica/Mawson</option>

        <option>Asia/Aqtau</option>

        <option>Asia/Aqtobe</option>

        <option>Asia/Ashgabat</option>

        <option>Asia/Dushanbe</option>

        <option>Asia/Karachi</option>

        <option>Asia/Oral</option>

        <option>Asia/Samarkand</option>

        <option>Asia/Tashkent</option>

        <option>Asia/Yekaterinburg</option>

        <option>Etc/GMT-5</option>

        <option>Indian/Kerguelen</option>

        <option>Indian/Maldives</option>

        <option>Asia/Colombo</option>

        <option>Asia/Kolkata</option>

        <option>Asia/Kathmandu</option>

        <option>Antarctica/Vostok</option>

        <option>Asia/Almaty</option>

        <option>Asia/Bishkek</option>

        <option>Asia/Dhaka</option>

        <option>Asia/Novokuznetsk</option>

        <option>Asia/Novosibirsk</option>

        <option>Asia/Omsk</option>

        <option>Asia/Qyzylorda</option>

        <option>Asia/Thimphu</option>

        <option>Etc/GMT-6</option>

        <option>Indian/Chagos</option>

        <option>Asia/Rangoon</option>

        <option>Indian/Cocos</option>

        <option>Antarctica/Davis</option>

        <option>Asia/Bangkok</option>

        <option>Asia/Ho_Chi_Minh</option>

        <option>Asia/Hovd</option>

        <option>Asia/Jakarta</option>

        <option>Asia/Krasnoyarsk</option>

        <option>Asia/Phnom_Penh</option>

        <option>Asia/Pontianak</option>

        <option>Asia/Vientiane</option>

        <option>Etc/GMT-7</option>

        <option>Indian/Christmas</option>

        <option>Antarctica/Casey</option>

        <option>Asia/Brunei</option>

        <option>Asia/Choibalsan</option>

        <option>Asia/Chongqing</option>

        <option>Asia/Harbin</option>

        <option>Asia/Hong_Kong</option>

        <option>Asia/Irkutsk</option>

        <option>Asia/Kashgar</option>

        <option>Asia/Kuala_Lumpur</option>

        <option>Asia/Kuching</option>

        <option>Asia/Macau</option>

        <option>Asia/Makassar</option>

        <option>Asia/Manila</option>

        <option>Asia/Shanghai</option>

        <option>Asia/Singapore</option>

        <option>Asia/Taipei</option>

        <option>Asia/Ulaanbaatar</option>

        <option>Asia/Urumqi</option>

        <option>Australia/Perth</option>

        <option>Etc/GMT-8</option>

        <option>Australia/Eucla</option>

        <option>Asia/Dili</option>

        <option>Asia/Jayapura</option>

        <option>Asia/Pyongyang</option>

        <option>Asia/Seoul</option>

        <option>Asia/Tokyo</option>

        <option>Asia/Yakutsk</option>

        <option>Etc/GMT-9</option>

        <option>Pacific/Palau</option>

        <option>Australia/Adelaide</option>

        <option>Australia/Broken_Hill</option>

        <option>Australia/Darwin</option>

        <option>Antarctica/DumontDUrville</option>

        <option>Asia/Sakhalin</option>

        <option>Asia/Vladivostok</option>

        <option>Australia/Brisbane</option>

        <option>Australia/Currie</option>

        <option>Australia/Hobart</option>

        <option>Australia/Lindeman</option>

        <option>Australia/Melbourne</option>

        <option>Australia/Sydney</option>

        <option>Etc/GMT-10</option>

        <option>Pacific/Chuuk</option>

        <option>Pacific/Guam</option>

        <option>Pacific/Port_Moresby</option>

        <option>Pacific/Saipan</option>

        <option>Australia/Lord_Howe</option>

        <option>Antarctica/Macquarie</option>

        <option>Asia/Anadyr</option>

        <option>Asia/Kamchatka</option>

        <option>Asia/Magadan</option>

        <option>Etc/GMT-11</option>

        <option>Pacific/Efate</option>

        <option>Pacific/Guadalcanal</option>

        <option>Pacific/Kosrae</option>

        <option>Pacific/Noumea</option>

        <option>Pacific/Pohnpei</option>

        <option>Pacific/Norfolk</option>

        <option>Antarctica/McMurdo</option>

        <option>Etc/GMT-12</option>

        <option>Pacific/Auckland</option>

        <option>Pacific/Fiji</option>

        <option>Pacific/Funafuti</option>

        <option>Pacific/Kwajalein</option>

        <option>Pacific/Majuro</option>

        <option>Pacific/Nauru</option>

        <option>Pacific/Tarawa</option>

        <option>Pacific/Wake</option>

        <option>Pacific/Wallis</option>

        <option>Pacific/Chatham</option>

        <option>Etc/GMT-13</option>

        <option>Pacific/Enderbury</option>

        <option>Pacific/Tongatapu</option>

        <option>Etc/GMT-14</option>

        <option>Pacific/Kiritimati</option>

    </select>
  </label>
  <label for="nest-pin">
    nest pin
    <input name="nest-pin" id="nest-pin" />
  </label>
  <div id="nest-pin-retrieval">
    <p>
      Follow the link below and log in to Nest. Paste the PIN number that is
      shown on the screen into the field above
    </p>
    <a href="https://home.nest.com/login/oauth2?client_id=nest-client-id&state=fnCLwYer"
       target="_blank"
    >
      nest authorization
    </a>
  </div>

  <input type="submit" id="submit" value="submit" />
</form>

  </div>
</body>
</html>

}, :request {:body nil, :server-port 80, :server-name localhost, :remote-addr localhost, :uri /users/new, :query-string nil, :scheme :http, :request-method :get, :headers {host localhost}}, :headers nil, :enlive [{:type :dtd, :data [html nil nil]} {:tag :html, :attrs nil, :content [
 {:tag :head, :attrs nil, :content [
   {:tag :title, :attrs nil, :content [Whendows ]}
]}

 {:tag :body, :attrs nil, :content [
   {:tag :div, :attrs {:id users-new}, :content [

 {:tag :header, :attrs nil, :content [
   {:tag :h1, :attrs nil, :content [Sign Up]}
]}
 {:tag :form, :attrs {:method post, :action /users}, :content [
   {:tag :input, :attrs {:value oLjni6mRPBWb1VPUnRhsc8bILkqOV4ombnZ2XdiVnuwPEL6n2IJ/J16/5FXCDv9meWhpG+YrcwC4MBsl, :type hidden, :name __anti-forgery-token, :id __anti-forgery-token}, :content []}
   {:tag :label, :attrs {:for email}, :content [
    email
     {:tag :input, :attrs {:value [email protected], :id email, :name email, :type email}, :content []}
  ]}
   {:tag :label, :attrs {:for password}, :content [
    password
     {:tag :input, :attrs {:value password, :id password, :name password, :type password}, :content []}
  ]}
   {:tag :label, :attrs {:for confirm-password}, :content [
    confirm password
     {:tag :input, :attrs {:value password, :id confirm-password, :name confirm-password, :type password}, :content []}
  ]}
   {:tag :label, :attrs {:for phone-number}, :content [
    phone number
     {:tag :input, :attrs {:value 123-456-7890, :id phone-number, :name phone-number, :type tel}, :content []}
  ]}
   {:tag :label, :attrs {:for timezone}, :content [
    timezone
     {:tag :select, :attrs {:tabindex 0, :name timezone, :id timezone}, :content [

         {:tag :option, :attrs nil, :content [Etc/GMT+12]}

         {:tag :option, :attrs nil, :content [Etc/GMT+11]}

         {:tag :option, :attrs nil, :content [Pacific/Apia]}

         {:tag :option, :attrs nil, :content [Pacific/Midway]}

         {:tag :option, :attrs nil, :content [Pacific/Niue]}

         {:tag :option, :attrs nil, :content [Pacific/Pago_Pago]}

         {:tag :option, :attrs nil, :content [America/Adak]}

         {:tag :option, :attrs nil, :content [Etc/GMT+10]}

         {:tag :option, :attrs nil, :content [HST]}

         {:tag :option, :attrs nil, :content [Pacific/Fakaofo]}

         {:tag :option, :attrs nil, :content [Pacific/Honolulu]}

         {:tag :option, :attrs nil, :content [Pacific/Johnston]}

         {:tag :option, :attrs nil, :content [Pacific/Rarotonga]}

         {:tag :option, :attrs nil, :content [Pacific/Tahiti]}

         {:tag :option, :attrs nil, :content [Pacific/Marquesas]}

         {:tag :option, :attrs nil, :content [America/Anchorage]}

         {:tag :option, :attrs nil, :content [America/Juneau]}

         {:tag :option, :attrs nil, :content [America/Nome]}

         {:tag :option, :attrs nil, :content [America/Yakutat]}

         {:tag :option, :attrs nil, :content [Etc/GMT+9]}

         {:tag :option, :attrs nil, :content [Pacific/Gambier]}

         {:tag :option, :attrs nil, :content [America/Dawson]}

         {:tag :option, :attrs nil, :content [America/Los_Angeles]}

         {:tag :option, :attrs nil, :content [America/Santa_Isabel]}

         {:tag :option, :attrs nil, :content [America/Tijuana]}

         {:tag :option, :attrs nil, :content [America/Vancouver]}

         {:tag :option, :attrs nil, :content [America/Whitehorse]}

         {:tag :option, :attrs nil, :content [Etc/GMT+8]}

         {:tag :option, :attrs nil, :content [PST8PDT]}

         {:tag :option, :attrs nil, :content [Pacific/Pitcairn]}

         {:tag :option, :attrs nil, :content [America/Boise]}

         {:tag :option, :attrs nil, :content [America/Cambridge_Bay]}

         {:tag :option, :attrs nil, :content [America/Chihuahua]}

         {:tag :option, :attrs nil, :content [America/Dawson_Creek]}

         {:tag :option, :attrs nil, :content [America/Denver]}

         {:tag :option, :attrs nil, :content [America/Edmonton]}

         {:tag :option, :attrs nil, :content [America/Hermosillo]}

         {:tag :option, :attrs nil, :content [America/Inuvik]}

         {:tag :option, :attrs nil, :content [America/Mazatlan]}

         {:tag :option, :attrs nil, :content [America/Ojinaga]}

         {:tag :option, :attrs nil, :content [America/Phoenix]}

         {:tag :option, :attrs nil, :content [America/Yellowknife]}

         {:tag :option, :attrs nil, :content [Etc/GMT+7]}

         {:tag :option, :attrs nil, :content [MST]}

         {:tag :option, :attrs nil, :content [MST7MDT]}

         {:tag :option, :attrs nil, :content [America/Bahia_Banderas]}

         {:tag :option, :attrs nil, :content [America/Belize]}

         {:tag :option, :attrs nil, :content [America/Cancun]}

         {:tag :option, :attrs nil, :content [America/Chicago]}

         {:tag :option, :attrs nil, :content [America/Costa_Rica]}

         {:tag :option, :attrs nil, :content [America/El_Salvador]}

         {:tag :option, :attrs nil, :content [America/Guatemala]}

         {:tag :option, :attrs nil, :content [America/Indiana/Knox]}

         {:tag :option, :attrs nil, :content [America/Indiana/Tell_City]}

         {:tag :option, :attrs nil, :content [America/Managua]}

         {:tag :option, :attrs nil, :content [America/Matamoros]}

         {:tag :option, :attrs nil, :content [America/Menominee]}

         {:tag :option, :attrs nil, :content [America/Merida]}

         {:tag :option, :attrs nil, :content [America/Mexico_City]}

         {:tag :option, :attrs nil, :content [America/Monterrey]}

         {:tag :option, :attrs nil, :content [America/North_Dakota/Center]}

         {:tag :option, :attrs nil, :content [America/North_Dakota/New_Salem]}

         {:tag :option, :attrs nil, :content [America/Rainy_River]}

         {:tag :option, :attrs nil, :content [America/Rankin_Inlet]}

         {:tag :option, :attrs nil, :content [America/Regina]}

         {:tag :option, :attrs nil, :content [America/Swift_Current]}

         {:tag :option, :attrs nil, :content [America/Tegucigalpa]}

         {:tag :option, :attrs nil, :content [America/Winnipeg]}

         {:tag :option, :attrs nil, :content [CST6CDT]}

         {:tag :option, :attrs nil, :content [Etc/GMT+6]}

         {:tag :option, :attrs nil, :content [Pacific/Easter]}

         {:tag :option, :attrs nil, :content [Pacific/Galapagos]}

         {:tag :option, :attrs nil, :content [America/Atikokan]}

         {:tag :option, :attrs nil, :content [America/Bogota]}

         {:tag :option, :attrs nil, :content [America/Cayman]}

         {:tag :option, :attrs nil, :content [America/Detroit]}

         {:tag :option, :attrs nil, :content [America/Grand_Turk]}

         {:tag :option, :attrs nil, :content [America/Guayaquil]}

         {:tag :option, :attrs nil, :content [America/Havana]}

         {:tag :option, :attrs nil, :content [America/Indiana/Indianapolis]}

         {:tag :option, :attrs nil, :content [America/Indiana/Marengo]}

         {:tag :option, :attrs nil, :content [America/Indiana/Petersburg]}

         {:tag :option, :attrs nil, :content [America/Indiana/Vevay]}

         {:tag :option, :attrs nil, :content [America/Indiana/Vincennes]}

         {:tag :option, :attrs nil, :content [America/Indiana/Winamac]}

         {:tag :option, :attrs nil, :content [America/Iqaluit]}

         {:tag :option, :attrs nil, :content [America/Jamaica]}

         {:tag :option, :attrs nil, :content [America/Kentucky/Louisville]}

         {:tag :option, :attrs nil, :content [America/Kentucky/Monticello]}

         {:tag :option, :attrs nil, :content [America/Lima]}

         {:tag :option, :attrs nil, :content [America/Montreal]}

         {:tag :option, :attrs nil, :content [America/Nassau]}

         {:tag :option, :attrs nil, :content [America/New_York]}

         {:tag :option, :attrs nil, :content [America/Nipigon]}

         {:tag :option, :attrs nil, :content [America/Panama]}

         {:tag :option, :attrs nil, :content [America/Pangnirtung]}

         {:tag :option, :attrs nil, :content [America/Port-au-Prince]}

         {:tag :option, :attrs nil, :content [America/Resolute]}

         {:tag :option, :attrs nil, :content [America/Thunder_Bay]}

         {:tag :option, :attrs nil, :content [America/Toronto]}

         {:tag :option, :attrs nil, :content [EST]}

         {:tag :option, :attrs nil, :content [EST5EDT]}

         {:tag :option, :attrs nil, :content [Etc/GMT+5]}

         {:tag :option, :attrs nil, :content [America/Caracas]}

         {:tag :option, :attrs nil, :content [America/Anguilla]}

         {:tag :option, :attrs nil, :content [America/Antigua]}

         {:tag :option, :attrs nil, :content [America/Argentina/San_Luis]}

         {:tag :option, :attrs nil, :content [America/Aruba]}

         {:tag :option, :attrs nil, :content [America/Asuncion]}

         {:tag :option, :attrs nil, :content [America/Barbados]}

         {:tag :option, :attrs nil, :content [America/Blanc-Sablon]}

         {:tag :option, :attrs nil, :content [America/Boa_Vista]}

         {:tag :option, :attrs nil, :content [America/Campo_Grande]}

         {:tag :option, :attrs nil, :content [America/Cuiaba]}

         {:tag :option, :attrs nil, :content [America/Curacao]}

         {:tag :option, :attrs nil, :content [America/Dominica]}

         {:tag :option, :attrs nil, :content [America/Eirunepe]}

         {:tag :option, :attrs nil, :content [America/Glace_Bay]}

         {:tag :option, :attrs nil, :content [America/Goose_Bay]}

         {:tag :option, :attrs nil, :content [America/Grenada]}

         {:tag :option, :attrs nil, :content [America/Guadeloupe]}

         {:tag :option, :attrs nil, :content [America/Guyana]}

         {:tag :option, :attrs nil, :content [America/Halifax]}

         {:tag :option, :attrs nil, :content [America/La_Paz]}

         {:tag :option, :attrs nil, :content [America/Manaus]}

         {:tag :option, :attrs nil, :content [America/Martinique]}

         {:tag :option, :attrs nil, :content [America/Moncton]}

         {:tag :option, :attrs nil, :content [America/Montserrat]}

         {:tag :option, :attrs nil, :content [America/Port_of_Spain]}

         {:tag :option, :attrs nil, :content [America/Porto_Velho]}

         {:tag :option, :attrs nil, :content [America/Puerto_Rico]}

         {:tag :option, :attrs nil, :content [America/Rio_Branco]}

         {:tag :option, :attrs nil, :content [America/Santiago]}

         {:tag :option, :attrs nil, :content [America/Santo_Domingo]}

         {:tag :option, :attrs nil, :content [America/St_Kitts]}

         {:tag :option, :attrs nil, :content [America/St_Lucia]}

         {:tag :option, :attrs nil, :content [America/St_Thomas]}

         {:tag :option, :attrs nil, :content [America/St_Vincent]}

         {:tag :option, :attrs nil, :content [America/Thule]}

         {:tag :option, :attrs nil, :content [America/Tortola]}

         {:tag :option, :attrs nil, :content [Antarctica/Palmer]}

         {:tag :option, :attrs nil, :content [Atlantic/Bermuda]}

         {:tag :option, :attrs nil, :content [Atlantic/Stanley]}

         {:tag :option, :attrs nil, :content [Etc/GMT+4]}

         {:tag :option, :attrs nil, :content [America/St_Johns]}

         {:tag :option, :attrs nil, :content [America/Araguaina]}

         {:tag :option, :attrs nil, :content [America/Argentina/Buenos_Aires]}

         {:tag :option, :attrs nil, :content [America/Argentina/Catamarca]}

         {:tag :option, :attrs nil, :content [America/Argentina/Cordoba]}

         {:tag :option, :attrs nil, :content [America/Argentina/Jujuy]}

         {:tag :option, :attrs nil, :content [America/Argentina/La_Rioja]}

         {:tag :option, :attrs nil, :content [America/Argentina/Mendoza]}

         {:tag :option, :attrs nil, :content [America/Argentina/Rio_Gallegos]}

         {:tag :option, :attrs nil, :content [America/Argentina/Salta]}

         {:tag :option, :attrs nil, :content [America/Argentina/San_Juan]}

         {:tag :option, :attrs nil, :content [America/Argentina/Tucuman]}

         {:tag :option, :attrs nil, :content [America/Argentina/Ushuaia]}

         {:tag :option, :attrs nil, :content [America/Bahia]}

         {:tag :option, :attrs nil, :content [America/Belem]}

         {:tag :option, :attrs nil, :content [America/Cayenne]}

         {:tag :option, :attrs nil, :content [America/Fortaleza]}

         {:tag :option, :attrs nil, :content [America/Godthab]}

         {:tag :option, :attrs nil, :content [America/Maceio]}

         {:tag :option, :attrs nil, :content [America/Miquelon]}

         {:tag :option, :attrs nil, :content [America/Montevideo]}

         {:tag :option, :attrs nil, :content [America/Paramaribo]}

         {:tag :option, :attrs nil, :content [America/Recife]}

         {:tag :option, :attrs nil, :content [America/Santarem]}

         {:tag :option, :attrs nil, :content [America/Sao_Paulo]}

         {:tag :option, :attrs nil, :content [Antarctica/Rothera]}

         {:tag :option, :attrs nil, :content [Etc/GMT+3]}

         {:tag :option, :attrs nil, :content [America/Noronha]}

         {:tag :option, :attrs nil, :content [Atlantic/South_Georgia]}

         {:tag :option, :attrs nil, :content [Etc/GMT+2]}

         {:tag :option, :attrs nil, :content [America/Scoresbysund]}

         {:tag :option, :attrs nil, :content [Atlantic/Azores]}

         {:tag :option, :attrs nil, :content [Atlantic/Cape_Verde]}

         {:tag :option, :attrs nil, :content [Etc/GMT+1]}

         {:tag :option, :attrs nil, :content [Africa/Abidjan]}

         {:tag :option, :attrs nil, :content [Africa/Accra]}

         {:tag :option, :attrs nil, :content [Africa/Bamako]}

         {:tag :option, :attrs nil, :content [Africa/Banjul]}

         {:tag :option, :attrs nil, :content [Africa/Bissau]}

         {:tag :option, :attrs nil, :content [Africa/Casablanca]}

         {:tag :option, :attrs nil, :content [Africa/Conakry]}

         {:tag :option, :attrs nil, :content [Africa/Dakar]}

         {:tag :option, :attrs nil, :content [Africa/El_Aaiun]}

         {:tag :option, :attrs nil, :content [Africa/Freetown]}

         {:tag :option, :attrs nil, :content [Africa/Lome]}

         {:tag :option, :attrs nil, :content [Africa/Monrovia]}

         {:tag :option, :attrs nil, :content [Africa/Nouakchott]}

         {:tag :option, :attrs nil, :content [Africa/Ouagadougou]}

         {:tag :option, :attrs nil, :content [Africa/Sao_Tome]}

         {:tag :option, :attrs nil, :content [America/Danmarkshavn]}

         {:tag :option, :attrs nil, :content [Atlantic/Canary]}

         {:tag :option, :attrs nil, :content [Atlantic/Faroe]}

         {:tag :option, :attrs nil, :content [Atlantic/Madeira]}

         {:tag :option, :attrs nil, :content [Atlantic/Reykjavik]}

         {:tag :option, :attrs nil, :content [Atlantic/St_Helena]}

         {:tag :option, :attrs nil, :content [Etc/GMT]}

         {:tag :option, :attrs nil, :content [Etc/UCT]}

         {:tag :option, :attrs nil, :content [Etc/UTC]}

         {:tag :option, :attrs nil, :content [Europe/Dublin]}

         {:tag :option, :attrs nil, :content [Europe/Lisbon]}

         {:tag :option, :attrs nil, :content [Europe/London]}

         {:tag :option, :attrs nil, :content [UTC]}

         {:tag :option, :attrs nil, :content [WET]}

         {:tag :option, :attrs nil, :content [Africa/Algiers]}

         {:tag :option, :attrs nil, :content [Africa/Bangui]}

         {:tag :option, :attrs nil, :content [Africa/Brazzaville]}

         {:tag :option, :attrs nil, :content [Africa/Ceuta]}

         {:tag :option, :attrs nil, :content [Africa/Douala]}

         {:tag :option, :attrs nil, :content [Africa/Kinshasa]}

         {:tag :option, :attrs nil, :content [Africa/Lagos]}

         {:tag :option, :attrs nil, :content [Africa/Libreville]}

         {:tag :option, :attrs nil, :content [Africa/Luanda]}

         {:tag :option, :attrs nil, :content [Africa/Malabo]}

         {:tag :option, :attrs nil, :content [Africa/Ndjamena]}

         {:tag :option, :attrs nil, :content [Africa/Niamey]}

         {:tag :option, :attrs nil, :content [Africa/Porto-Novo]}

         {:tag :option, :attrs nil, :content [Africa/Tunis]}

         {:tag :option, :attrs nil, :content [Africa/Windhoek]}

         {:tag :option, :attrs nil, :content [CET]}

         {:tag :option, :attrs nil, :content [Etc/GMT-1]}

         {:tag :option, :attrs nil, :content [Europe/Amsterdam]}

         {:tag :option, :attrs nil, :content [Europe/Andorra]}

         {:tag :option, :attrs nil, :content [Europe/Belgrade]}

         {:tag :option, :attrs nil, :content [Europe/Berlin]}

         {:tag :option, :attrs nil, :content [Europe/Brussels]}

         {:tag :option, :attrs nil, :content [Europe/Budapest]}

         {:tag :option, :attrs nil, :content [Europe/Copenhagen]}

         {:tag :option, :attrs nil, :content [Europe/Gibraltar]}

         {:tag :option, :attrs nil, :content [Europe/Luxembourg]}

         {:tag :option, :attrs nil, :content [Europe/Madrid]}

         {:tag :option, :attrs nil, :content [Europe/Malta]}

         {:tag :option, :attrs nil, :content [Europe/Monaco]}

         {:tag :option, :attrs nil, :content [Europe/Oslo]}

         {:tag :option, :attrs nil, :content [Europe/Paris]}

         {:tag :option, :attrs nil, :content [Europe/Prague]}

         {:tag :option, :attrs nil, :content [Europe/Rome]}

         {:tag :option, :attrs nil, :content [Europe/Stockholm]}

         {:tag :option, :attrs nil, :content [Europe/Tirane]}

         {:tag :option, :attrs nil, :content [Europe/Vaduz]}

         {:tag :option, :attrs nil, :content [Europe/Vienna]}

         {:tag :option, :attrs nil, :content [Europe/Warsaw]}

         {:tag :option, :attrs nil, :content [Europe/Zurich]}

         {:tag :option, :attrs nil, :content [MET]}

         {:tag :option, :attrs nil, :content [Africa/Blantyre]}

         {:tag :option, :attrs nil, :content [Africa/Bujumbura]}

         {:tag :option, :attrs nil, :content [Africa/Cairo]}

         {:tag :option, :attrs nil, :content [Africa/Gaborone]}

         {:tag :option, :attrs nil, :content [Africa/Harare]}

         {:tag :option, :attrs nil, :content [Africa/Johannesburg]}

         {:tag :option, :attrs nil, :content [Africa/Kigali]}

         {:tag :option, :attrs nil, :content [Africa/Lubumbashi]}

         {:tag :option, :attrs nil, :content [Africa/Lusaka]}

         {:tag :option, :attrs nil, :content [Africa/Maputo]}

         {:tag :option, :attrs nil, :content [Africa/Maseru]}

         {:tag :option, :attrs nil, :content [Africa/Mbabane]}

         {:tag :option, :attrs nil, :content [Africa/Tripoli]}

         {:tag :option, :attrs nil, :content [Asia/Amman]}

         {:tag :option, :attrs nil, :content [Asia/Beirut]}

         {:tag :option, :attrs nil, :content [Asia/Damascus]}

         {:tag :option, :attrs nil, :content [Asia/Gaza]}

         {:tag :option, :attrs nil, :content [Asia/Jerusalem]}

         {:tag :option, :attrs nil, :content [Asia/Nicosia]}

         {:tag :option, :attrs nil, :content [EET]}

         {:tag :option, :attrs nil, :content [Etc/GMT-2]}

         {:tag :option, :attrs nil, :content [Europe/Athens]}

         {:tag :option, :attrs nil, :content [Europe/Bucharest]}

         {:tag :option, :attrs nil, :content [Europe/Chisinau]}

         {:tag :option, :attrs nil, :content [Europe/Helsinki]}

         {:tag :option, :attrs nil, :content [Europe/Istanbul]}

         {:tag :option, :attrs nil, :content [Europe/Kaliningrad]}

         {:tag :option, :attrs nil, :content [Europe/Kiev]}

         {:tag :option, :attrs nil, :content [Europe/Minsk]}

         {:tag :option, :attrs nil, :content [Europe/Riga]}

         {:tag :option, :attrs nil, :content [Europe/Simferopol]}

         {:tag :option, :attrs nil, :content [Europe/Sofia]}

         {:tag :option, :attrs nil, :content [Europe/Tallinn]}

         {:tag :option, :attrs nil, :content [Europe/Uzhgorod]}

         {:tag :option, :attrs nil, :content [Europe/Vilnius]}

         {:tag :option, :attrs nil, :content [Europe/Zaporozhye]}

         {:tag :option, :attrs nil, :content [Africa/Addis_Ababa]}

         {:tag :option, :attrs nil, :content [Africa/Asmara]}

         {:tag :option, :attrs nil, :content [Africa/Dar_es_Salaam]}

         {:tag :option, :attrs nil, :content [Africa/Djibouti]}

         {:tag :option, :attrs nil, :content [Africa/Kampala]}

         {:tag :option, :attrs nil, :content [Africa/Khartoum]}

         {:tag :option, :attrs nil, :content [Africa/Mogadishu]}

         {:tag :option, :attrs nil, :content [Africa/Nairobi]}

         {:tag :option, :attrs nil, :content [Antarctica/Syowa]}

         {:tag :option, :attrs nil, :content [Asia/Aden]}

         {:tag :option, :attrs nil, :content [Asia/Baghdad]}

         {:tag :option, :attrs nil, :content [Asia/Bahrain]}

         {:tag :option, :attrs nil, :content [Asia/Kuwait]}

         {:tag :option, :attrs nil, :content [Asia/Qatar]}

         {:tag :option, :attrs nil, :content [Asia/Riyadh]}

         {:tag :option, :attrs nil, :content [Etc/GMT-3]}

         {:tag :option, :attrs nil, :content [Europe/Moscow]}

         {:tag :option, :attrs nil, :content [Europe/Samara]}

         {:tag :option, :attrs nil, :content [Europe/Volgograd]}

         {:tag :option, :attrs nil, :content [Indian/Antananarivo]}

         {:tag :option, :attrs nil, :content [Indian/Comoro]}

         {:tag :option, :attrs nil, :content [Indian/Mayotte]}

         {:tag :option, :attrs nil, :content [Asia/Tehran]}

         {:tag :option, :attrs nil, :content [Asia/Baku]}

         {:tag :option, :attrs nil, :content [Asia/Dubai]}

         {:tag :option, :attrs nil, :content [Asia/Muscat]}

         {:tag :option, :attrs nil, :content [Asia/Tbilisi]}

         {:tag :option, :attrs nil, :content [Asia/Yerevan]}

         {:tag :option, :attrs nil, :content [Etc/GMT-4]}

         {:tag :option, :attrs nil, :content [Indian/Mahe]}

         {:tag :option, :attrs nil, :content [Indian/Mauritius]}

         {:tag :option, :attrs nil, :content [Indian/Reunion]}

         {:tag :option, :attrs nil, :content [Asia/Kabul]}

         {:tag :option, :attrs nil, :content [Antarctica/Mawson]}

         {:tag :option, :attrs nil, :content [Asia/Aqtau]}

         {:tag :option, :attrs nil, :content [Asia/Aqtobe]}

         {:tag :option, :attrs nil, :content [Asia/Ashgabat]}

         {:tag :option, :attrs nil, :content [Asia/Dushanbe]}

         {:tag :option, :attrs nil, :content [Asia/Karachi]}

         {:tag :option, :attrs nil, :content [Asia/Oral]}

         {:tag :option, :attrs nil, :content [Asia/Samarkand]}

         {:tag :option, :attrs nil, :content [Asia/Tashkent]}

         {:tag :option, :attrs nil, :content [Asia/Yekaterinburg]}

         {:tag :option, :attrs nil, :content [Etc/GMT-5]}

         {:tag :option, :attrs nil, :content [Indian/Kerguelen]}

         {:tag :option, :attrs nil, :content [Indian/Maldives]}

         {:tag :option, :attrs nil, :content [Asia/Colombo]}

         {:tag :option, :attrs nil, :content [Asia/Kolkata]}

         {:tag :option, :attrs nil, :content [Asia/Kathmandu]}

         {:tag :option, :attrs nil, :content [Antarctica/Vostok]}

         {:tag :option, :attrs nil, :content [Asia/Almaty]}

         {:tag :option, :attrs nil, :content [Asia/Bishkek]}

         {:tag :option, :attrs nil, :content [Asia/Dhaka]}

         {:tag :option, :attrs nil, :content [Asia/Novokuznetsk]}

         {:tag :option, :attrs nil, :content [Asia/Novosibirsk]}

         {:tag :option, :attrs nil, :content [Asia/Omsk]}

         {:tag :option, :attrs nil, :content [Asia/Qyzylorda]}

         {:tag :option, :attrs nil, :content [Asia/Thimphu]}

         {:tag :option, :attrs nil, :content [Etc/GMT-6]}

         {:tag :option, :attrs nil, :content [Indian/Chagos]}

         {:tag :option, :attrs nil, :content [Asia/Rangoon]}

         {:tag :option, :attrs nil, :content [Indian/Cocos]}

         {:tag :option, :attrs nil, :content [Antarctica/Davis]}

         {:tag :option, :attrs nil, :content [Asia/Bangkok]}

         {:tag :option, :attrs nil, :content [Asia/Ho_Chi_Minh]}

         {:tag :option, :attrs nil, :content [Asia/Hovd]}

         {:tag :option, :attrs nil, :content [Asia/Jakarta]}

         {:tag :option, :attrs nil, :content [Asia/Krasnoyarsk]}

         {:tag :option, :attrs nil, :content [Asia/Phnom_Penh]}

         {:tag :option, :attrs nil, :content [Asia/Pontianak]}

         {:tag :option, :attrs nil, :content [Asia/Vientiane]}

         {:tag :option, :attrs nil, :content [Etc/GMT-7]}

         {:tag :option, :attrs nil, :content [Indian/Christmas]}

         {:tag :option, :attrs nil, :content [Antarctica/Casey]}

         {:tag :option, :attrs nil, :content [Asia/Brunei]}

         {:tag :option, :attrs nil, :content [Asia/Choibalsan]}

         {:tag :option, :attrs nil, :content [Asia/Chongqing]}

         {:tag :option, :attrs nil, :content [Asia/Harbin]}

         {:tag :option, :attrs nil, :content [Asia/Hong_Kong]}

         {:tag :option, :attrs nil, :content [Asia/Irkutsk]}

         {:tag :option, :attrs nil, :content [Asia/Kashgar]}

         {:tag :option, :attrs nil, :content [Asia/Kuala_Lumpur]}

         {:tag :option, :attrs nil, :content [Asia/Kuching]}

         {:tag :option, :attrs nil, :content [Asia/Macau]}

         {:tag :option, :attrs nil, :content [Asia/Makassar]}

         {:tag :option, :attrs nil, :content [Asia/Manila]}

         {:tag :option, :attrs nil, :content [Asia/Shanghai]}

         {:tag :option, :attrs nil, :content [Asia/Singapore]}

         {:tag :option, :attrs nil, :content [Asia/Taipei]}

         {:tag :option, :attrs nil, :content [Asia/Ulaanbaatar]}

         {:tag :option, :attrs nil, :content [Asia/Urumqi]}

         {:tag :option, :attrs nil, :content [Australia/Perth]}

         {:tag :option, :attrs nil, :content [Etc/GMT-8]}

         {:tag :option, :attrs nil, :content [Australia/Eucla]}

         {:tag :option, :attrs nil, :content [Asia/Dili]}

         {:tag :option, :attrs nil, :content [Asia/Jayapura]}

         {:tag :option, :attrs nil, :content [Asia/Pyongyang]}

         {:tag :option, :attrs nil, :content [Asia/Seoul]}

         {:tag :option, :attrs nil, :content [Asia/Tokyo]}

         {:tag :option, :attrs nil, :content [Asia/Yakutsk]}

         {:tag :option, :attrs nil, :content [Etc/GMT-9]}

         {:tag :option, :attrs nil, :content [Pacific/Palau]}

         {:tag :option, :attrs nil, :content [Australia/Adelaide]}

         {:tag :option, :attrs nil, :content [Australia/Broken_Hill]}

         {:tag :option, :attrs nil, :content [Australia/Darwin]}

         {:tag :option, :attrs nil, :content [Antarctica/DumontDUrville]}

         {:tag :option, :attrs nil, :content [Asia/Sakhalin]}

         {:tag :option, :attrs nil, :content [Asia/Vladivostok]}

         {:tag :option, :attrs nil, :content [Australia/Brisbane]}

         {:tag :option, :attrs nil, :content [Australia/Currie]}

         {:tag :option, :attrs nil, :content [Australia/Hobart]}

         {:tag :option, :attrs nil, :content [Australia/Lindeman]}

         {:tag :option, :attrs nil, :content [Australia/Melbourne]}

         {:tag :option, :attrs nil, :content [Australia/Sydney]}

         {:tag :option, :attrs nil, :content [Etc/GMT-10]}

         {:tag :option, :attrs nil, :content [Pacific/Chuuk]}

         {:tag :option, :attrs nil, :content [Pacific/Guam]}

         {:tag :option, :attrs nil, :content [Pacific/Port_Moresby]}

         {:tag :option, :attrs nil, :content [Pacific/Saipan]}

         {:tag :option, :attrs nil, :content [Australia/Lord_Howe]}

         {:tag :option, :attrs nil, :content [Antarctica/Macquarie]}

         {:tag :option, :attrs nil, :content [Asia/Anadyr]}

         {:tag :option, :attrs nil, :content [Asia/Kamchatka]}

         {:tag :option, :attrs nil, :content [Asia/Magadan]}

         {:tag :option, :attrs nil, :content [Etc/GMT-11]}

         {:tag :option, :attrs nil, :content [Pacific/Efate]}

         {:tag :option, :attrs nil, :content [Pacific/Guadalcanal]}

         {:tag :option, :attrs nil, :content [Pacific/Kosrae]}

         {:tag :option, :attrs nil, :content [Pacific/Noumea]}

         {:tag :option, :attrs nil, :content [Pacific/Pohnpei]}

         {:tag :option, :attrs nil, :content [Pacific/Norfolk]}

         {:tag :option, :attrs nil, :content [Antarctica/McMurdo]}

         {:tag :option, :attrs nil, :content [Etc/GMT-12]}

         {:tag :option, :attrs nil, :content [Pacific/Auckland]}

         {:tag :option, :attrs nil, :content [Pacific/Fiji]}

         {:tag :option, :attrs nil, :content [Pacific/Funafuti]}

         {:tag :option, :attrs nil, :content [Pacific/Kwajalein]}

         {:tag :option, :attrs nil, :content [Pacific/Majuro]}

         {:tag :option, :attrs nil, :content [Pacific/Nauru]}

         {:tag :option, :attrs nil, :content [Pacific/Tarawa]}

         {:tag :option, :attrs nil, :content [Pacific/Wake]}

         {:tag :option, :attrs nil, :content [Pacific/Wallis]}

         {:tag :option, :attrs nil, :content [Pacific/Chatham]}

         {:tag :option, :attrs nil, :content [Etc/GMT-13]}

         {:tag :option, :attrs nil, :content [Pacific/Enderbury]}

         {:tag :option, :attrs nil, :content [Pacific/Tongatapu]}

         {:tag :option, :attrs nil, :content [Etc/GMT-14]}

         {:tag :option, :attrs nil, :content [Pacific/Kiritimati]}

    ]}
  ]}
   {:tag :label, :attrs {:for nest-pin}, :content [
    nest pin
     {:tag :input, :attrs {:id nest-pin, :name nest-pin}, :content []}
  ]}
   {:tag :div, :attrs {:id nest-pin-retrieval}, :content [
     {:tag :p, :attrs nil, :content [
      Follow the link below and log in to Nest. Paste the PIN number that is
      shown on the screen into the field above
    ]}
     {:tag :a, :attrs {:target _blank, :href https://home.nest.com/login/oauth2?client_id=nest-client-id&state=fnCLwYer}, :content [
      nest authorization
    ]}
  ]}

   {:tag :input, :attrs {:value submit, :id submit, :type submit}, :content []}
]}

  ]}
]}


]}], :app #<middleware$wrap_internal_error$fn__10094 ask_nest.middleware$wrap_internal_error$fn__10094@602ec0dc>, :content-type nil, :cookie-jar {localhost {ring-session {:http-only true, :raw ring-session=eee00742-3b90-45c0-86ef-071287b29443, :domain localhost, :path /, :value eee00742-3b90-45c0-86ef-071287b29443}}}}

ERROR in (user-record-created-on-signup) (impl.clj:50)
Uncaught exception, not in assertion.
expected: nil
  actual: java.lang.IllegalArgumentException: field could not be found with selector "timezone"
 at kerodon.impl$not_found.invoke (impl.clj:50)
    kerodon.impl$form_element.invoke (impl.clj:80)
    kerodon.impl$form_element_query.invoke (impl.clj:112)
    kerodon.impl$choose_value.invoke (impl.clj:199)
    kerodon.core$choose.invoke (core.clj:25)
    ask_nest.integration.new_user_test/fn (new_user_test.clj:18)
    clojure.test$test_var$fn__7187.invoke (test.clj:704)
    clojure.test$test_var.invoke (test.clj:704)
    clojure.test$test_vars$fn__7209$fn__7214.invoke (test.clj:722)
    ask_nest.integration.new_user_test$eval22126$fn__22127.invoke (new_user_test.clj:13)
    clojure.test$compose_fixtures$fn__7181$fn__7182.invoke (test.clj:681)
    clojure.test$default_fixture.invoke (test.clj:674)
    clojure.test$compose_fixtures$fn__7181.invoke (test.clj:681)
    clojure.test$test_vars$fn__7209.invoke (test.clj:722)
    ask_nest.integration.new_user_test$eval22122$fn__22123.invoke (new_user_test.clj:12)
    clojure.test$compose_fixtures$fn__7181$fn__7182.invoke (test.clj:681)
    clojure.test$default_fixture.invoke (test.clj:674)
    clojure.test$compose_fixtures$fn__7181.invoke (test.clj:681)
    clojure.test$test_vars.invoke (test.clj:718)
    clojure.test$test_all_vars.invoke (test.clj:728)
    clojure.test$test_ns.invoke (test.clj:747)
    clojure.core$map$fn__4245.invoke (core.clj:2559)
    clojure.lang.LazySeq.sval (LazySeq.java:40)
    clojure.lang.LazySeq.seq (LazySeq.java:49)
    clojure.lang.Cons.next (Cons.java:39)
    clojure.lang.RT.boundedLength (RT.java:1654)
    clojure.lang.RestFn.applyTo (RestFn.java:130)
    clojure.core$apply.invoke (core.clj:626)
    clojure.test$run_tests.doInvoke (test.clj:762)
    clojure.lang.RestFn.invoke (RestFn.java:408)
    ask_nest.core$eval22140.invoke (form-init4673959029001529348.clj:1)
    clojure.lang.Compiler.eval (Compiler.java:6703)
    clojure.lang.Compiler.eval (Compiler.java:6666)
    clojure.core$eval.invoke (core.clj:2927)
    clojure.main$repl$read_eval_print__6625$fn__6628.invoke (main.clj:239)
    clojure.main$repl$read_eval_print__6625.invoke (main.clj:239)
    clojure.main$repl$fn__6634.invoke (main.clj:257)
    clojure.main$repl.doInvoke (main.clj:257)
    clojure.lang.RestFn.invoke (RestFn.java:1523)
    clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__10799.invoke (interruptible_eval.clj:72)
    clojure.lang.AFn.applyToHelper (AFn.java:152)
    clojure.lang.AFn.applyTo (AFn.java:144)
    clojure.core$apply.invoke (core.clj:624)
    clojure.core$with_bindings_STAR_.doInvoke (core.clj:1862)
    clojure.lang.RestFn.invoke (RestFn.java:425)
    clojure.tools.nrepl.middleware.interruptible_eval$evaluate.invoke (interruptible_eval.clj:56)
    clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__10841$fn__10844.invoke (interruptible_eval.clj:191)
    clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__10836.invoke (interruptible_eval.clj:159)
    clojure.lang.AFn.run (AFn.java:22)
    java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1142)
    java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:617)
    java.lang.Thread.run (Thread.java:745)

Ran 1 tests containing 1 assertions.
0 failures, 1 errors.
{:type :summary, :fail 0, :error 1, :pass 0, :test 1}

fill-in doesn't work for array input names

I have a form with multiple inputs sharing the name "members[]" so that their values will be collected into a vector when the form data is received by ring. I found that when I use fill-in to fill in one of those inputs (using a selector specific to that one), Kerodon was filling in all of the inputs, not just the one. This turned out to be because impl/field-to-selector matches by :name instead of using the more specific selector I had provided.

I can work around this by providing a unique id for each of the inputs (impl/field-to-selector checks for :id before going to :name). However, is there some reason why we can't match inputs with any arbitrary selector?

Consider dropping support for Clojure older than 1.7

Looks like the dependency org.flatland/ordered is required for tests to succeed with Clojure older than 1.7.

If this support is dropped, Kerodon would no longer need its single use of ordered-map and the dependency could be dropped.

Browser-like treatment of whitespace in text

Hi,
Thanks for all of your great work - I'm finding Kerodon really useful!

I just wondered if you have any plans to push a version to Clojars in the near future? The "Browser-like treatment of whitespace in text" in particular is something I'm really to get my hands on.

thanks
Gary

Add support for labels that don't have for attributes

Although it appears that this commit added support for for-less labels, it's not working for me on version 0.5.0.

Does not work:

<label>Username
    <input id="username" type="text" autocomplete="nickname" name="username" autofocus required maxlength="50" value="{{username}}">
</label>

Does work:

<label for="username">Username</label>
<input id="username" type="text" autocomplete="nickname" name="username" autofocus required maxlength="50" value="{{username}}">

Support interaction with <select multiple>

Based on the current API, to maintain symmetry, this would probably need a function called (unchoose)

Alternatively, (choose) could be a toggle action on <select multiple>

Pressing buttons

Let me know if I'm missing something, but it looks like that press is working only with <input type="submit"> and not with <button>. Is there a way to interact with buttons?

Thanks.

Using follow with a String creates a ClassCastException

I am using the current 0.6.0-SNAPSHOT release.

When I use (kerodon.core/follow "Logout") I get the following exception:

I also created a pastebin http://pastebin.com/dzQQu5ts with the testing code, the stacktrace and the current state.

   1. Unhandled java.lang.ClassCastException
    clojure.lang.PersistentStructMap cannot be cast to java.lang.CharSequence

    string.clj:  236  clojure.string/trim
    core.clj: 2557  clojure.core/map/fn
                  LazySeq.java:   40  clojure.lang.LazySeq/sval
   LazySeq.java:   49  clojure.lang.LazySeq/seq
    LazySeq.java:  115  clojure.lang.LazySeq/equals
    LazySeq.java:  100  clojure.lang.LazySeq/equiv
    Util.java:  124  clojure.lang.Util/pcequiv
    Util.java:   32  clojure.lang.Util/equiv
    impl.clj:   30  kerodon.impl/css-or-content/fn
    enlive_html.clj:  241  net.cgrand.enlive-html/pred/fn
    enlive_html.clj:  236  net.cgrand.enlive-html/zip-pred/fn
    enlive_html.clj:  282  net.cgrand.enlive-html/intersection/fn
    enlive_html.clj:  329  net.cgrand.enlive-html/predset/fn
    core.clj: 2403  clojure.core/comp/fn
    enlive_html.clj:  390  net.cgrand.enlive-html/step
    enlive_html.clj:  497  net.cgrand.enlive-html/zip-select-nodes*/select1
               enlive_html.clj:  498  net.cgrand.enlive-html/zip-select-nodes*/select1/fn
   core.clj: 2559  clojure.core/map/fn
                  LazySeq.java:   40  clojure.lang.LazySeq/sval
   LazySeq.java:   49  clojure.lang.LazySeq/seq
    RT.java:  484  clojure.lang.RT/seq
    core.clj:  133  clojure.core/seq
    core.clj:  624  clojure.core/apply
    core.clj: 2586  clojure.core/mapcat
    RestFn.java:  423  clojure.lang.RestFn/invoke
    enlive_html.clj:  498  net.cgrand.enlive-html/zip-select-nodes*/select1
               enlive_html.clj:  498  net.cgrand.enlive-html/zip-select-nodes*/select1/fn
   core.clj: 2559  clojure.core/map/fn
                  LazySeq.java:   40  clojure.lang.LazySeq/sval
   LazySeq.java:   49  clojure.lang.LazySeq/seq
    RT.java:  484  clojure.lang.RT/seq
    core.clj:  133  clojure.core/seq
    core.clj:  624  clojure.core/apply
    core.clj: 2586  clojure.core/mapcat
    RestFn.java:  423  clojure.lang.RestFn/invoke
    enlive_html.clj:  498  net.cgrand.enlive-html/zip-select-nodes*/select1
               enlive_html.clj:  498  net.cgrand.enlive-html/zip-select-nodes*/select1/fn
   core.clj: 2559  clojure.core/map/fn
                  LazySeq.java:   40  clojure.lang.LazySeq/sval
   LazySeq.java:   49  clojure.lang.LazySeq/seq
    RT.java:  484  clojure.lang.RT/seq
    core.clj:  133  clojure.core/seq
    core.clj:  624  clojure.core/apply
    core.clj: 2586  clojure.core/mapcat
    RestFn.java:  423  clojure.lang.RestFn/invoke
    enlive_html.clj:  498  net.cgrand.enlive-html/zip-select-nodes*/select1
               enlive_html.clj:  498  net.cgrand.enlive-html/zip-select-nodes*/select1/fn
   core.clj: 2559  clojure.core/map/fn
                  LazySeq.java:   40  clojure.lang.LazySeq/sval
   LazySeq.java:   49  clojure.lang.LazySeq/seq
    Cons.java:   39  clojure.lang.Cons/next
    RT.java: 1654  clojure.lang.RT/boundedLength
    RestFn.java:  130  clojure.lang.RestFn/applyTo
    core.clj:  624  clojure.core/apply
    core.clj: 2586  clojure.core/mapcat
    RestFn.java:  423  clojure.lang.RestFn/invoke
    enlive_html.clj:  498  net.cgrand.enlive-html/zip-select-nodes*/select1
               enlive_html.clj:  498  net.cgrand.enlive-html/zip-select-nodes*/select1/fn
   core.clj: 2559  clojure.core/map/fn
                  LazySeq.java:   40  clojure.lang.LazySeq/sval
   LazySeq.java:   49  clojure.lang.LazySeq/seq
    RT.java:  484  clojure.lang.RT/seq
    core.clj:  133  clojure.core/seq
    core.clj:  624  clojure.core/apply
    core.clj: 2586  clojure.core/mapcat
    RestFn.java:  423  clojure.lang.RestFn/invoke
    enlive_html.clj:  498  net.cgrand.enlive-html/zip-select-nodes*/select1
               enlive_html.clj:  498  net.cgrand.enlive-html/zip-select-nodes*/select1/fn
   core.clj: 2559  clojure.core/map/fn
                  LazySeq.java:   40  clojure.lang.LazySeq/sval
   LazySeq.java:   49  clojure.lang.LazySeq/seq
    Cons.java:   39  clojure.lang.Cons/next
    RT.java: 1654  clojure.lang.RT/boundedLength
    RestFn.java:  130  clojure.lang.RestFn/applyTo
    core.clj:  624  clojure.core/apply
    core.clj: 2586  clojure.core/mapcat
    RestFn.java:  423  clojure.lang.RestFn/invoke
    enlive_html.clj:  498  net.cgrand.enlive-html/zip-select-nodes*/select1
               enlive_html.clj:  498  net.cgrand.enlive-html/zip-select-nodes*/select1/fn
   core.clj: 2559  clojure.core/map/fn
                  LazySeq.java:   40  clojure.lang.LazySeq/sval
   LazySeq.java:   49  clojure.lang.LazySeq/seq
    Cons.java:   39  clojure.lang.Cons/next
    RT.java: 1654  clojure.lang.RT/boundedLength
    RestFn.java:  130  clojure.lang.RestFn/applyTo
    core.clj:  624  clojure.core/apply
    core.clj: 2586  clojure.core/mapcat
    RestFn.java:  423  clojure.lang.RestFn/invoke
    enlive_html.clj:  498  net.cgrand.enlive-html/zip-select-nodes*/select1
               enlive_html.clj:  498  net.cgrand.enlive-html/zip-select-nodes*/select1/fn
   core.clj: 2559  clojure.core/map/fn
                  LazySeq.java:   40  clojure.lang.LazySeq/sval
   LazySeq.java:   49  clojure.lang.LazySeq/seq
    Cons.java:   39  clojure.lang.Cons/next
    RT.java: 1654  clojure.lang.RT/boundedLength
    RestFn.java:  130  clojure.lang.RestFn/applyTo
    core.clj:  624  clojure.core/apply
    core.clj: 2586  clojure.core/mapcat
    RestFn.java:  423  clojure.lang.RestFn/invoke
    enlive_html.clj:  498  net.cgrand.enlive-html/zip-select-nodes*/select1
               enlive_html.clj:  500  net.cgrand.enlive-html/zip-select-nodes*/fn
                      core.clj: 2559  clojure.core/map/fn
                  LazySeq.java:   40  clojure.lang.LazySeq/sval
   LazySeq.java:   49  clojure.lang.LazySeq/seq
    RT.java:  484  clojure.lang.RT/seq
    core.clj:  133  clojure.core/seq
    core.clj:  624  clojure.core/apply
    core.clj: 2586  clojure.core/mapcat
    RestFn.java:  423  clojure.lang.RestFn/invoke
    enlive_html.clj:  500  net.cgrand.enlive-html/zip-select-nodes*
    enlive_html.clj:  504  net.cgrand.enlive-html/select-nodes*
    enlive_html.clj:  543  net.cgrand.enlive-html/select
    impl.clj:   83  kerodon.impl/link
    impl.clj:  213  kerodon.impl/find-url
    core.clj:   19  kerodon.core/follow
    acceptance_test.clj:   66  web.acceptance-test/fn
    test.clj:  704  clojure.test/test-var/fn
    test.clj:  704  clojure.test/test-var
    test.clj:  124  cider.nrepl.middleware.test/test-vars/fn/fn
    test_data.clj:  215  clj-demgen.test-data/with-test-data
    test.clj:  681  clojure.test/compose-fixtures/fn/fn
    acceptance_test.clj:   23  web.acceptance-test/with-test-system
    test.clj:  681  clojure.test/compose-fixtures/fn/fn
    test.clj:  674  clojure.test/default-fixture
    test.clj:  681  clojure.test/compose-fixtures/fn
    test.clj:  681  clojure.test/compose-fixtures/fn
    test.clj:  124  cider.nrepl.middleware.test/test-vars/fn
    test_data.clj:   29  clj-demgen.test-data/with-test-home-folder
    test.clj:  681  clojure.test/compose-fixtures/fn/fn
    test.clj:  674  clojure.test/default-fixture
    test.clj:  681  clojure.test/compose-fixtures/fn
    test.clj:  120  cider.nrepl.middleware.test/test-vars
    test.clj:  139  cider.nrepl.middleware.test/test-ns
    test.clj:  161  cider.nrepl.middleware.test/handle-test/fn
    AFn.java:  152  clojure.lang.AFn/applyToHelper
    AFn.java:  144  clojure.lang.AFn/applyTo
    core.clj:  624  clojure.core/apply
    core.clj: 1862  clojure.core/with-bindings*
    RestFn.java:  425  clojure.lang.RestFn/invoke
    test.clj:  159  cider.nrepl.middleware.test/handle-test
    test.clj:  200  cider.nrepl.middleware.test/wrap-test/fn

Using (kerodon.core/follow :#id-of-logout-link) works fine btw. The link is present on the page.

Send the value of the pressed button on form submission

One thing I noticed we're not doing that browsers do.

At the moment, inputs "reset", "button" and "submit" will all be treated as "text", which could cause some unexpected results.

I believe the spec says "reset" and "button" are never considered successful, and that if there are multiple submit buttons, only the one pressed should be considered successful.

Press button not working

Can't work out what I'm doing wrong here:

Code: (press :.next-swirls)

Error: java.lang.IllegalArgumentException: button could not be found with selector ":.next-swirls"

Print from the session:

{:tag :div, :attrs {:class paging}, :content (
     {:tag :button, :attrs {:class previous-swirls}, :content (< Previous 20 Swirls)} 
     {:tag :button, :attrs {:class next-swirls}, :content (Next 20 Swirls >)} 
)}

Html:

<div class="paging">
    <button class="previous-swirls">&lt; Previous 20 Swirls</button>
    <button class="next-swirls">Next 20 Swirls &gt;</button>
</div>

Note I have tried:
Using ID:
(press [:#next-swirls])

With and without [](press :#next-swirls)
(press [:#next-swirls])
(press .next-swirls)
(press [.next-swirls])

`status?` fails because response doesn't contain a :status

This isn't technically due to kerodon, but kerodon provides the status? function, so I'm starting here. Looking into this, I realized that the response created by Peridot doesn't have a :status when I try to use just Peridot. Peridot uses ring-mock, and that is what is giving us the response from the app handler. Again, trying to just use ring-mock directly, I see that its response doesn't contain :status or :headers keys.

Has anyone else run into this?

Problem with ring-anti-forgery tests and 2 forms

I have a problem with Kerodon tests when they go through 2 forms that use ring-anti-forgery. This is what happens:

  1. tests opens a page and there is a form with token
  2. tests clicks a link and opens another page with a form and token
  3. test submits the form
  4. test receives "Invalid token" response

If I however skip step 1. and go to the second page with a form directly, I don't get the error.

I didn't notice this happening in production environment.

Thanks.

Enabling more flexible selectors

(First of all, thanks for writing this useful little library. 😄 I'm attempting to evangelize Clojure among some colleagues who are more accustomed to Rails and browser tests, and I think this library will serve as a nice bridge so that things aren't quite as alien to them.)

I've been learning kerodon and attempting to use it on a simple app. Once I figured out that selectors were mostly enlive selectors (and after I learned those), a lot of things clicked into place. But then I tried using a selector of this sort: [:.parent :.child], and it didn't work. It took me a while to understand why: the selector I supply is placed in a context of a larger enlive selector that begins with :form, like so: [:form [:.parent :.child]]. As an enlive selector, this means "find a node with both the parent and child classes under a <form> tag". That's not what I wanted, and sadly, there's no way to support such a selector given the implicit context it's put in. I've provided code for a simple test case below.

I have 2 ideas for how to address this. I'll start with the more ambitious.

Proposal 1: define explicit type-based interpretations of selector values

We could define the interpretation of a selector value to be dependent on its type. If it's:

  1. a string, it's interpreted as a text-based lookup, the same way kerodon currently deals with strings.
  2. a vector, it's interpreted as an enlive selector, and is not placed within any additional context.
  3. anything else (keyword, function, etc), it's considered an enlive selector fragment, which is wrapped in a vector and used as-is without any additional context.

(1) involves no change to the semantics. (2) and (3) drop the implicit "parent form" context. (2) goes further: users who are using vector to mean "find a node that matches all the criteria specified in this vector" will have to wrap their vectors in another vector to achieve the same semantics. This is annoying and a bit noisy, but it provides a good deal of flexibility for more complex use cases. Plus, the clarity of the definition will (I believe) make it easier for people to learn and use kerodon.

But, this would definitely be a significant breaking change. Given that this is Clojure and our primary thought leader exhorts a rather strict no-breakage approach to change, I suspect that this proposal will not be palatable, even if it went along with a major version bump to 1.0. So:

Proposal 2: allow explicit enlive selectors to be specified via metadata

If a selector is tagged with :kerodon.core/literal-selector metadata equal to true, it is interpreted as a literal selector, which means it's neither wrapped in additional vectors nor assumed to be within a "parent form" context. Rather, it's used literally, with no transformations between it and the enlive/select call. Then, if kerodon.core is aliased to k, I could say ^:k/literal-selector [:.parent :.child] to solve my use case above.

This would be a growth-only change, keeping all existing kerodon uses the same. However, it would require more complexity to accomplish.

Question

(Thanks for bearing with me so far…I know it's long.)

So my question is: are you amenable to either of these proposals? If so, I think I will have some cycles to work on implementation. If not, that's totally cool, and I still thank you for the library. 😄 Maybe I could do this in a fork instead.

Example

Here's an example use case and test case (to be added to the kerodon.unit.impl namespace):

(defn checked-form-produces [fields-html check-selector expected]
  (let [html (str "<form action=/>"
                  fields-html
                  "<input type=submit value=Submit>"
                  "</form>")
        enlive (to-html-resource html)
        state (check-box {:enlive enlive} check-selector)
        parsed (build-request-details state "Submit")
        details (apply hash-map :url parsed)]
    (is (= expected (:params details)))))

(deftest test-form-element-query
  (let [html (str "<div id=broccoli>"
                  "  <label>"
                  "    <input class=yes type=radio name=broccoli value=yes /> Yes"
                  "  </label>"
                  "  <label>"
                  "    <input class=no type=radio name=broccoli value=no /> No"
                  "  </label>"
                  "</div>"
                  "<div id=cauliflower>"
                  "  <label>"
                  "    <input class=yes type=radio name=cauliflower value=yes /> Yes"
                  "  </label>"
                  "  <label>"
                  "    <input class=no type=radio name=cauliflower value=no /> No"
                  "  </label>"
                  "</div>")]
    (checked-form-produces html [:div#broccoli :input.yes] {"broccoli" "yes"})
    (checked-form-produces html [:div#broccoli :input.no] {"broccoli" "no"})
    (checked-form-produces html [:div#cauliflower :input.yes] {"cauliflower" "yes"})
    (checked-form-produces html [:div#cauliflower :input.no] {"cauliflower" "no"})))

Note that not even within can address this use case in the current implementation. I could say something like (within :div#broccoli (check :input.yes)), but that won't be found because it's implicitly looking for a [:form :input.yes] inside the div.

(Yes, I realize that with the existing approach I can say [:input.yes (enlive/attr= "name" "broccoli")] to select the input. The problems with that are (1) this is an undocumented (and maybe not-officially-supported?) way to leverage enlive for a selector, (2) you have to require the enlive library in your project, (3) it's a lot to explain to people like my colleagues who will be learning the library.)

Trouble with GET params and `follow-redirect`

Hi there.

I'm having problem with GET params in the URI. When testing the app with visit, the app doesn't receive the GET params:

(-> (session app)
      (visit "/guy" :params {"key" "guyskey"}))
;; or the equivalent
(-> (session app)
      (visit "/guy?key=guyskey"))

In both cases the :query-string is "key=guyskey", but the app doesn't receive those values.

I also get this error when using follow redirect:

(deftest site-navegation-test
  (-> (session app)
      (visit "/")
      (fill-in :#key "André")
      (press "Buscar atleta")
      (follow-redirect)))
Uncaught exception, not in assertion.
expected: nil
  actual: java.lang.IllegalArgumentException: Previous response was not a redirect
 at peridot.core$follow_redirect.invoke (core.clj:59)
    kerodon.core$follow_redirect.invoke (core.clj:16)
...

Is there anything I'm doing wrong?

facilitate using kerodon with test frameworks other than clojure.test

I'd like to use kerodon from a test framework other than clojure.test. It'd be nice to have functions similar to text?, status?, value? etc which simply returned the text, status, or value of the node. That way, I could make my assertions using whatever assertion/test library I want.

For example, using speclj, I would want to be able to write

(should= (attr session [:form] :id) "my-form")

or using midje,

((attr session [:form] :id) => "my-form")

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.