driver: add support for date inputs

This commit is contained in:
Chris Breiding
2017-05-23 10:48:05 -04:00
parent 1aa716f329
commit c62d329bc1
6 changed files with 103 additions and 22 deletions
+4
View File
@@ -190,6 +190,10 @@ cy.get("body").type("{uparrow}{uparrow}{downarrow}{downarrow}{leftarrow}{rightar
cy.get("body").type("{shift}", {release: false}).get("li:first").click()
```
# Date inputs
Using `cy.type()` on a date input (`<input type="date">`) requires specifying a valid date in the format `yyyy-MM-dd`, e.g. `"1999-12-31"`. This isn't exactly how a user would type into a date input, but is a workaround since date input support varies between browsers and the format varies based on locale. `yyyy-MM-dd` is the format required by [the W3 spec](https://www.w3.org/TR/html5/forms.html#date-state-(type=date)) and is what the input's `value` will be set to regardless of browser or locale.
# Known Issues
## Native `input[type=date,datetime,datetime-local,month,year,color]`
@@ -1,6 +1,7 @@
_ = require("lodash")
$ = require("jquery")
Promise = require("bluebird")
moment = require("moment")
{ delay, waitForAnimations } = require("./utils")
$Log = require("../../../cypress/log")
@@ -9,6 +10,7 @@ utils = require("../../../cypress/utils")
inputEvents = "textInput input".split(" ")
textLike = "textarea,:text,[contenteditable],[type=password],[type=email],[type=number],[type=date],[type=week],[type=month],[type=time],[type=datetime],[type=datetime-local],[type=search],[type=url],[type=tel]"
dateRegex = /\d{4}-\d{2}-\d{2}/
module.exports = (Cypress, Commands) ->
Cypress.on "test:before:run", ->
@@ -73,6 +75,7 @@ module.exports = (Cypress, Commands) ->
isBody = options.$el.is("body")
isTextLike = options.$el.is(textLike)
isDate = options.$el.is("[type=date]")
hasTabIndex = options.$el.is("[tabindex]")
## TODO: tabindex can't be -1
@@ -102,6 +105,16 @@ module.exports = (Cypress, Commands) ->
if _.isBlank(chars)
utils.throwErrByPath("type.empty_string", { onFail: options._log })
if isDate and (
not _.isString(chars) or
not dateRegex.test(chars) or
not moment(chars).isValid()
)
utils.throwErrByPath("type.invalid_date", {
onFail: options._log
args: { chars }
})
options.chars = "" + chars
type = =>
@@ -166,13 +179,27 @@ module.exports = (Cypress, Commands) ->
return dispatched
typed = ""
charsToType = if isDate
options.chars.replace("-", "")
else
options.chars
$Keyboard.type({
$el: options.$el
chars: options.chars
chars: charsToType
delay: options.delay
release: options.release
window: @privateState("window")
updateValue: (rng, key) ->
if isDate
typed += key
if typed is charsToType
options.$el.val(options.chars)
else
rng.text(key, "end")
onBeforeType: (totalKeys) =>
## for the total number of keys we're about to
## type, ensure we raise the timeout to account
@@ -588,6 +588,7 @@ module.exports = {
type:
empty_string: "#{cmd('type')} cannot accept an empty String. You need to actually type something."
invalid: "Special character sequence: '{{chars}}' is not recognized. Available sequences are: {{allChars}}"
invalid_date: "Typing into a date input with #{cmd('type')} requires a valid date with the format 'yyyy-MM-dd'. You passed: {{chars}}"
multiple_elements: "#{cmd('type')} can only be called on a single textarea or :text. Your subject contained {{num}} elements."
not_on_text_field: "#{cmd('type')} can only be called on textarea or :text. Your subject is a: {{node}}"
tab: "{tab} isn't a supported character sequence. You'll want to use the command #{cmd('tab')}, which is not ready yet, but when it is done that's what you'll use."
+1 -4
View File
@@ -475,9 +475,6 @@ $Keyboard = {
return dispatched
updateValue: (rng, key) ->
rng.text(key, "end")
typeKey: (el, key, options) ->
## if we have an afterKey value it means
## we've typed in prior to this
@@ -489,7 +486,7 @@ $Keyboard = {
@moveCaretToEnd(options.rng)
@ensureKey el, key, options, ->
@updateValue(options.rng, key)
options.updateValue(options.rng, key)
ensureKey: (el, key, options, fn) ->
options.id = _.uniqueId("char")
@@ -125,10 +125,6 @@
el with tabindex
</div>
<input id="input" />
<input id="input-with-value" value="foo" />
<input id="number-with-value" value="12" />
<input id="email-with-value" value="brian@foo.c" />
<button id="button">button</button>
<form id="by-id">
@@ -257,11 +253,23 @@
</div>
<div id="input-types">
<input type="number" />
<input type="email" />
<input type="password" />
<input type="date" />
<input type="time" />
<input id="input-with-value" value="foo" />
<input id="input-without-value" />
<input id="number-with-value" type="number" value="12" />
<input id="number-without-value" type="number" />
<input id="email-with-value" type="email" value="brian@foo.c" />
<input id="email-without-value" type="email" />
<input id="password-with-value" type="password" value="pass" />
<input id="password-without-value" type="password" />
<input id="date-with-value" type="date" value="2016-01-01" />
<input id="date-without-value" type="date" />
<input id="time" type="time" />
<div contenteditable="true"></div>
<textarea></textarea>
</div>
@@ -568,6 +568,19 @@ describe "$Cypress.Cy Text Commands", ->
@cy.get("#password-without-value").type("agent").then ($input) ->
expect($input).to.have.value("agent")
describe "input[type=date]", ->
it "can change values", ->
@cy.get("#date-without-value").type("1959-09-13").then ($text) ->
expect($text).to.have.value("1959-09-13")
it "overwrites existing value", ->
@cy.get("#date-with-value").type("1959-09-13").then ($text) ->
expect($text).to.have.value("1959-09-13")
it "overwrites existing value input by invoking val", ->
@cy.get("#date-without-value").invoke("val", "2016-01-01").type("1959-09-13").then ($text) ->
expect($text).to.have.value("1959-09-13")
describe "[contenteditable]", ->
it "can change values", ->
@cy.get("#input-types [contenteditable]").type("foo").then ($div) ->
@@ -577,14 +590,6 @@ describe "$Cypress.Cy Text Commands", ->
@cy.get("#input-types [contenteditable]").invoke("text", "foo").type(" bar").then ($text) ->
expect($text).to.have.text("foo bar")
# it "can change input[type=date] values", ->
# @cy.get("#input-types [type=date").type("1986-03-14").then ($text) ->
# expect($text).to.have.value("1986-03-14")
# it "inserts text after existing text on input[type=date]", ->
# @cy.get("#input-types [type=date").invoke("val", "pass").type("word").then ($text) ->
# expect($text).to.have.value("date")
describe "specialChars", ->
context "{{}", ->
it "sets which and keyCode to 219", (done) ->
@@ -2019,6 +2024,45 @@ describe "$Cypress.Cy Text Commands", ->
@cy.get(":text:first").type("")
it "throws when type=date and chars is not a string", (done) ->
logs = []
@Cypress.on "log", (attrs, log) ->
logs.push(log)
@cy.on "fail", (err) =>
expect(logs.length).to.eq 2
expect(err.message).to.eq "Typing into a date input with cy.type() requires a valid date with the format 'yyyy-MM-dd'. You passed: 1989"
done()
@cy.get("#date-without-value").type(1989)
it "throws when type=date and chars is invalid format", (done) ->
logs = []
@Cypress.on "log", (attrs, log) ->
logs.push(log)
@cy.on "fail", (err) =>
expect(logs.length).to.eq 2
expect(err.message).to.eq "Typing into a date input with cy.type() requires a valid date with the format 'yyyy-MM-dd'. You passed: 01-01-1989"
done()
@cy.get("#date-without-value").type("01-01-1989")
it "throws when type=date and chars is invalid date", (done) ->
logs = []
@Cypress.on "log", (attrs, log) ->
logs.push(log)
@cy.on "fail", (err) =>
expect(logs.length).to.eq 2
expect(err.message).to.eq "Typing into a date input with cy.type() requires a valid date with the format 'yyyy-MM-dd'. You passed: 1989-04-31"
done()
@cy.get("#date-without-value").type("1989-04-31")
_.each [NaN, Infinity, [], {}, null, undefined], (val) =>
it "throws when trying to type: #{val}", (done) ->
logs = []