xeqi / kerodon

interaction and testing library for html based ring apps.
305 stars 22 forks source link

More complete form element support #9

Closed glenjamin closed 11 years ago

glenjamin commented 11 years ago

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 :)

xeqi commented 11 years ago

We need to make sure that for each of the field elements supported:

  1. There is a method simulating user input. (pick ..), (choose ..), etc
  2. Form submission sends them, along with handling defaults.
  3. (?) Test helpers

Given the different actions for different form elements, I'm not sure a general set of polymorphic functions would be that useful. pick might be able to use one since it would be for both checkboxes and radio buttons. Using a multimethod might work better, as the dispatch function could figure out the "type", rather then having to wrap the data in a record or such.


I'm uncertain about the find by placeholder. I usually just use an id or class to find unlabeled elements. Perhaps the actions should take a finder in place of the current string selector. There could be a list of finder functions based on the current overloaded usage of the selector concept. Something like:

(-> ...
   (fill-in (label "Username") "user")
   (fill-in (selector "#password") "password")
   (submit (value "Sign In") "password"))

This part might be worth a separate issue/discussion. Makes the end user api a bit more verbose, but also "simple".

glenjamin commented 11 years ago

I had a little bit of a play around with this, using a Protocol doesn't quite work as it's not clear what "this" should be.

I ran into a bit of an issue using a multimethod too, my goal was to keep it completely open to extension, but I couldn't figure out a good dispatch function, I wanted to do something like:

(defmethod something :select)
(defmethod something :textarea)
(defmethod something [:input :date])
(defmethod something [:input :radio])
(defmethod something [:input :checkbox])
(defmethod something :input) 

I was hoping to be able to have a function that given a form element could produce a list of all elements of the supported field types, using an extensible multimethod as the enlive/select predicate.

In order to add a new field type, you'd have to: Be able to find all occurrences within a form Be able to find a single occurrence given a selector Be able to determine the value of a given occurrence Be able to enlive/transform a node to change the value

If I abandon the goal of keeping it open to extension this seems pretty doable - radio buttons are probably the trickiest because toggling a value works very differently to extracting the current value

glenjamin commented 11 years ago

I've got a basic proof of concept of more generic reading of the form at https://github.com/glenjamin/kerodon/tree/more-form-stuff

I think this works fairly well - it should be easy to add read support for checkboxes and and radio buttons.

Hopefully then it'll be pretty easy to make a similar restructuring for writing form values back in, with some code re-use around the helper functions.

Also, i like the finder function idea!

glenjamin commented 11 years ago

I've completed the work to parse all of the different types of form fields at https://github.com/glenjamin/kerodon/tree/more-form-stuff I'm going to take a crack at pick/choose at some point soon and then look at getting this merged back in properly.

Feedback welcomed!

xeqi commented 11 years ago

I'm fairly busy today, but I'll can plan to take a look at in tomorrow evening

xeqi commented 11 years ago

I like the way it looks. After thinking about it for awhile, I'm good with the double multimethod setup. Its not quite as extensible as it seems you were originally hoping, but I think it allows extension where needed.

Feel free to merge it and I'll make a release with it, #10, and a peridot update. I'm a little bit leery of doing a release with just 302f3b4f7 when this looks like it get the right values.

I can't wait to see what you come up with for the other pieces.

glenjamin commented 11 years ago

I've just pushed support for a choose function, which allows picking a value from a <select> - same branch as before.

xeqi commented 11 years ago

Ack, apparently I lost my rss feed which told me when commits happened awhile back. Is this work on master and ready for a release?

Also, I ran into a need for finding by placeholder so I expect to work on finder functions soon.

glenjamin commented 11 years ago

Reading the form is on master, picking the select box value is only on my branch.

There's a bug I introduced in ring-mock 0.1.4 that I've got a PR open for ( https://github.com/weavejester/ring-mock/pull/8) once @weavejester bumps that to 0.1.5 then peridot can get a release and kerodon can bump and release with this stuff.

Glen

On 23 May 2013, at 04:10, Nelson Morris notifications@github.com wrote:

Ack, apparently I lost my rss feed which told me when commits happened awhile back. Is this work on master and ready for a release?

Also, I ran into a need for finding by placeholder so I expect to work on finder functions soon.

— Reply to this email directly or view it on GitHubhttps://github.com/xeqi/kerodon/issues/9#issuecomment-18321141 .

xeqi commented 11 years ago

Looks like ring-mock 0.1.5 is released. I'll plan to do a set of releases for peridot and kerodon in the next couple days.

xeqi commented 11 years ago

I've released 0.2.0 with the form reading updates. Thanks for your work on this. How is the choosing going?

glenjamin commented 11 years ago

Brilliant, thanks.

I've been a bit stacked lately, but I don't think there's a huge amount left to do to get radio buttons and checkboxes in. Hopefully I'll get a bit of time this weekend.

glenjamin commented 11 years ago

I haven't had as much time to work on this as I wanted, but i've got a bit of stuff done.

I'm heading off on holiday at the weekend so I'm going to close this issue and raise a few more with a better breakdown of work that I reckon needs doing