diff --git a/docs/source/api/commands/type.md b/docs/source/api/commands/type.md index f5d4bdf73d..7e36a7a718 100644 --- a/docs/source/api/commands/type.md +++ b/docs/source/api/commands/type.md @@ -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 (``) 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]` diff --git a/packages/driver/src/cy/commands/actions/text.coffee b/packages/driver/src/cy/commands/actions/text.coffee index a21b00c085..a5e8e0efe1 100644 --- a/packages/driver/src/cy/commands/actions/text.coffee +++ b/packages/driver/src/cy/commands/actions/text.coffee @@ -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 diff --git a/packages/driver/src/cypress/error_messages.coffee b/packages/driver/src/cypress/error_messages.coffee index 50933aa800..b254aaa71d 100644 --- a/packages/driver/src/cypress/error_messages.coffee +++ b/packages/driver/src/cypress/error_messages.coffee @@ -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." diff --git a/packages/driver/src/cypress/keyboard.coffee b/packages/driver/src/cypress/keyboard.coffee index 61f0f652a2..3fd1f586c5 100644 --- a/packages/driver/src/cypress/keyboard.coffee +++ b/packages/driver/src/cypress/keyboard.coffee @@ -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") diff --git a/packages/driver/test/support/server/fixtures/dom.html b/packages/driver/test/support/server/fixtures/dom.html index b2a62d513f..f416deb980 100644 --- a/packages/driver/test/support/server/fixtures/dom.html +++ b/packages/driver/test/support/server/fixtures/dom.html @@ -125,10 +125,6 @@ el with tabindex - - - -