mirror of
https://github.com/cypress-io/cypress.git
synced 2026-05-18 22:28:38 -05:00
driver: add support for date inputs
This commit is contained in:
@@ -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."
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
Reference in New Issue
Block a user