diff --git a/README.md b/README.md
index 6b553c8225..4d4571496f 100644
--- a/README.md
+++ b/README.md
@@ -23,6 +23,7 @@ A [live playground](https://mozilla-services.github.io/react-jsonschema-form/) i
- [Alternative widgets](#alternative-widgets)
- [For boolean fields](#for-boolean-fields)
- [For string fields](#for-string-fields)
+ - [String formats](#string-formats)
- [For number and integer fields](#for-number-and-integer-fields)
- [Hidden widgets](#hidden-widgets)
- [Object fields ordering](#object-fields-ordering)
@@ -215,13 +216,22 @@ Here's a list of supported alternative widgets for different JSONSchema data typ
* `password`: an `input[type=password]` element is used;
* by default, a regular `input[type=text]` element is used.
-The built-in string field also supports the JSONSchema `format` property, and will render an appropriate widget by default for the following formats:
+##### String formats
+
+The built-in string field also supports the JSONSchema `format` property, and will render an appropriate widget by default for the following string formats:
-- `date-time`: Six `select` elements are used to select the year, the month, the day, the hour, the minute and the second;
- * If you don't want to deal with time, a `"ui:widget": "date"` uiSchema widget is alternatively available, exposing three selects for year, month and day only;
- `email`: An `input[type=email]` element is used;
- `uri`: An `input[type=url]` element is used;
-- More formats could be supported in a near future, feel free to help us going faster!
+- `date-time`: By default, an `input[type=datetime-local]` element is used; if you solely want to rely on a date, a `date` uiSchema alternative widget is available:
+
+![](http://i.imgur.com/xqu6Lcp.png)
+
+Please note that while standardized, `datetime-local` and `date` input elements are not yet supported by Firefox and IE. If you plan on targetting these platforms, two alternative widgets are available:
+
+- `alt-datetime`: Six `select` elements are used to select the year, the month, the day, the hour, the minute and the second;
+- `alt-date`: Three `select` elements are used to select the year, month and the day.
+
+![](http://i.imgur.com/VF5tY60.png)
#### For `number` and `integer` fields
diff --git a/playground/samples/date.js b/playground/samples/date.js
new file mode 100644
index 0000000000..0ecf66a9ba
--- /dev/null
+++ b/playground/samples/date.js
@@ -0,0 +1,54 @@
+module.exports = {
+ schema: {
+ title: "Date and time widgets",
+ type: "object",
+ properties: {
+ native: {
+ title: "Native",
+ description: "May not work on some browsers, notably Firefox Desktop and IE.",
+ type: "object",
+ properties: {
+ "datetime": {
+ type: "string",
+ format: "date-time"
+ },
+ "date": {
+ type: "string",
+ format: "date-time"
+ }
+ }
+ },
+ alternative: {
+ title: "Alternative",
+ description: "These work on every platform.",
+ type: "object",
+ properties: {
+ "alt-datetime": {
+ type: "string",
+ format: "date-time"
+ },
+ "alt-date": {
+ type: "string",
+ format: "date-time"
+ }
+ }
+ }
+ }
+ },
+ uiSchema: {
+ native: {
+ date: {
+ "ui:widget": "date"
+ }
+ },
+ alternative: {
+ "alt-datetime": {
+ "ui:widget": "alt-datetime"
+ },
+ "alt-date": {
+ "ui:widget": "alt-date"
+ }
+ }
+ },
+ formData: {}
+};
diff --git a/playground/samples/index.js b/playground/samples/index.js
index a05e5b5e13..b6d642095d 100644
--- a/playground/samples/index.js
+++ b/playground/samples/index.js
@@ -8,6 +8,7 @@ import references from "./references";
import custom from "./custom";
import errors from "./errors";
import large from "./large";
+import date from "./date";
export const samples = {
Simple: simple,
@@ -20,4 +21,5 @@ export const samples = {
Custom: custom,
Errors: errors,
Large: large,
+ "Date & time": date,
};
diff --git a/playground/samples/simple.js b/playground/samples/simple.js
index 7f6665066a..7d93af7e60 100644
--- a/playground/samples/simple.js
+++ b/playground/samples/simple.js
@@ -24,11 +24,6 @@ module.exports = {
type: "string",
title: "Password",
minLength: 3
- },
- date: {
- type: "string",
- format: "date-time",
- title: "Subscription date"
}
}
},
@@ -42,6 +37,9 @@ module.exports = {
password: {
"ui:widget": "password",
"ui:help": "Hint: Make it strong!"
+ },
+ date: {
+ "ui:widget": "alt-datetime"
}
},
formData: {
@@ -49,7 +47,6 @@ module.exports = {
lastName: "Norris",
age: 75,
bio: "Roundhouse kicking asses since 1940",
- password: "noneed",
- date: new Date().toJSON()
+ password: "noneed"
}
};
diff --git a/playground/samples/widgets.js b/playground/samples/widgets.js
index 759fa01356..80c2971b0d 100644
--- a/playground/samples/widgets.js
+++ b/playground/samples/widgets.js
@@ -14,14 +14,6 @@ module.exports = {
uri: {
type: "string",
format: "uri"
- },
- datetime: {
- type: "string",
- format: "date-time"
- },
- date: {
- type: "string",
- format: "date-time"
}
}
},
@@ -77,11 +69,6 @@ module.exports = {
"ui:widget": "textarea"
}
},
- stringFormats: {
- date: {
- "ui:widget": "date"
- }
- },
secret: {
"ui:widget": "hidden"
}
diff --git a/src/components/widgets/AltDateTimeWidget.js b/src/components/widgets/AltDateTimeWidget.js
new file mode 100644
index 0000000000..cf36536e4d
--- /dev/null
+++ b/src/components/widgets/AltDateTimeWidget.js
@@ -0,0 +1,21 @@
+import React, { PropTypes } from "react";
+
+import AltDateWidget from "./AltDateWidget";
+
+
+function AltDateTimeWidget(props) {
+ return ;
+}
+
+if (process.env.NODE_ENV !== "production") {
+ AltDateTimeWidget.propTypes = {
+ schema: PropTypes.object.isRequired,
+ id: PropTypes.string.isRequired,
+ placeholder: PropTypes.string,
+ value: React.PropTypes.string,
+ required: PropTypes.bool,
+ onChange: PropTypes.func,
+ };
+}
+
+export default AltDateTimeWidget;
diff --git a/src/components/widgets/AltDateWidget.js b/src/components/widgets/AltDateWidget.js
new file mode 100644
index 0000000000..e388720d75
--- /dev/null
+++ b/src/components/widgets/AltDateWidget.js
@@ -0,0 +1,125 @@
+import React, { Component, PropTypes } from "react";
+
+import { shouldRender, parseDateString, toDateString, pad } from "../../utils";
+import SelectWidget from "../widgets/SelectWidget";
+
+
+function rangeOptions(type, start, stop) {
+ let options = [{value: -1, label: type}];
+ for (let i=start; i<= stop; i++) {
+ options.push({value: i, label: pad(i, 2)});
+ }
+ return options;
+}
+
+function valid(state) {
+ return Object.keys(state).every(key => state[key] !== -1);
+}
+
+function DateElement({type, range, value, select, rootId}) {
+ const id = rootId + "_" + type;
+ return (
+ select(type, value)} />
+ );
+}
+
+class AltDateWidget extends Component {
+ static defaultProps = {
+ time: false
+ };
+
+ constructor(props) {
+ super(props);
+ this.state = parseDateString(props.value, props.time);
+ }
+
+ componentWillReceiveProps(nextProps) {
+ this.setState(parseDateString(nextProps.value, nextProps.time));
+ }
+
+ shouldComponentUpdate(nextProps, nextState) {
+ return shouldRender(this, nextProps, nextState);
+ }
+
+ onChange = (property, value) => {
+ this.setState({[property]: value}, () => {
+ // Only propagate to parent state if we have a complete date{time}
+ if (valid(this.state)) {
+ this.props.onChange(toDateString(this.state));
+ }
+ });
+ };
+
+ setNow = (event) => {
+ event.preventDefault();
+ const {time, onChange} = this.props;
+ const nowDateObj = parseDateString(new Date().toJSON(), time);
+ this.setState(nowDateObj, () => onChange(toDateString(this.state)));
+ };
+
+ clear = (event) => {
+ event.preventDefault();
+ const {time, onChange} = this.props;
+ this.setState(parseDateString("", time), () => onChange(undefined));
+ };
+
+ get dateElementProps() {
+ const {time} = this.props;
+ const {year, month, day, hour, minute, second} = this.state;
+ const data = [
+ {type: "year", range: [1900, 2020], value: year},
+ {type: "month", range: [1, 12], value: month},
+ {type: "day", range: [1, 31], value: day},
+ ];
+ if (time) {
+ data.push(
+ {type: "hour", range: [0, 23], value: hour},
+ {type: "minute", range: [0, 59], value: minute},
+ {type: "second", range: [0, 59], value: second}
+ );
+ }
+ return data;
+ }
+
+ render() {
+ const {id} = this.props;
+ return (
+ {
+ this.dateElementProps.map((props, i) => (
+ -
+
+
+ ))
+ }
+ -
+ Now
+
+ -
+ Clear
+
+
+ );
+ }
+}
+
+if (process.env.NODE_ENV !== "production") {
+ AltDateWidget.propTypes = {
+ schema: PropTypes.object.isRequired,
+ id: PropTypes.string.isRequired,
+ placeholder: PropTypes.string,
+ value: React.PropTypes.string,
+ required: PropTypes.bool,
+ onChange: PropTypes.func,
+ time: PropTypes.bool,
+ };
+}
+
+export default AltDateWidget;
diff --git a/src/components/widgets/DateTimeWidget.js b/src/components/widgets/DateTimeWidget.js
index 47c351b9a4..f3a6f6e6c4 100644
--- a/src/components/widgets/DateTimeWidget.js
+++ b/src/components/widgets/DateTimeWidget.js
@@ -1,10 +1,31 @@
import React, { PropTypes } from "react";
-import DateWidget from "./DateWidget";
+function fromJSONDate(jsonDate) {
+ return jsonDate ? jsonDate.slice(0, 19) : "";
+}
+
+function toJSONDate(dateString) {
+ if (dateString) {
+ return new Date(dateString).toJSON();
+ }
+}
-function DateTimeWidget(props) {
- return ;
+function DateTimeWidget({
+ schema,
+ id,
+ value,
+ required,
+ onChange
+}) {
+ return (
+ onChange(toJSONDate(event.target.value))} />
+ );
}
if (process.env.NODE_ENV !== "production") {
@@ -12,7 +33,7 @@ if (process.env.NODE_ENV !== "production") {
schema: PropTypes.object.isRequired,
id: PropTypes.string.isRequired,
placeholder: PropTypes.string,
- value: React.PropTypes.string,
+ value: PropTypes.string,
required: PropTypes.bool,
onChange: PropTypes.func,
};
diff --git a/src/components/widgets/DateWidget.js b/src/components/widgets/DateWidget.js
index 16cd164b6b..5375348cbd 100644
--- a/src/components/widgets/DateWidget.js
+++ b/src/components/widgets/DateWidget.js
@@ -1,124 +1,41 @@
-import React, { Component, PropTypes } from "react";
+import React, { PropTypes } from "react";
-import { shouldRender, parseDateString, toDateString, pad } from "../../utils";
-import SelectWidget from "../widgets/SelectWidget";
-
-function rangeOptions(type, start, stop) {
- let options = [{value: -1, label: type}];
- for (let i=start; i<= stop; i++) {
- options.push({value: i, label: pad(i, 2)});
- }
- return options;
+function fromJSONDate(jsonDate) {
+ return jsonDate ? jsonDate.slice(0, 10) : "";
}
-function valid(state) {
- return Object.keys(state).every(key => state[key] !== -1);
+function toJSONDate(dateString) {
+ if (dateString) {
+ return new Date(dateString).toJSON();
+ }
}
-function DateElement({type, range, value, select, rootId}) {
- const id = rootId + "_" + type;
+function DateWidget({
+ schema,
+ id,
+ value,
+ required,
+ onChange
+}) {
return (
- select(type, value)} />
+ value={fromJSONDate(value)}
+ required={required}
+ onChange={(event) => onChange(toJSONDate(event.target.value))} />
);
}
-class DateWidget extends Component {
- static defaultProps = {
- time: false
- };
-
- constructor(props) {
- super(props);
- this.state = parseDateString(props.value, props.time);
- }
-
- componentWillReceiveProps(nextProps) {
- this.setState(parseDateString(nextProps.value, nextProps.time));
- }
-
- shouldComponentUpdate(nextProps, nextState) {
- return shouldRender(this, nextProps, nextState);
- }
-
- onChange = (property, value) => {
- this.setState({[property]: value}, () => {
- // Only propagate to parent state if we have a complete date{time}
- if (valid(this.state)) {
- this.props.onChange(toDateString(this.state));
- }
- });
- };
-
- setNow = (event) => {
- event.preventDefault();
- const {time, onChange} = this.props;
- const nowDateObj = parseDateString(new Date().toJSON(), time);
- this.setState(nowDateObj, () => onChange(toDateString(this.state)));
- };
-
- clear = (event) => {
- event.preventDefault();
- const {time, onChange} = this.props;
- this.setState(parseDateString("", time), () => onChange(undefined));
- };
-
- get dateElementProps() {
- const {time} = this.props;
- const {year, month, day, hour, minute, second} = this.state;
- const data = [
- {type: "year", range: [1900, 2020], value: year},
- {type: "month", range: [1, 12], value: month},
- {type: "day", range: [1, 31], value: day},
- ];
- if (time) {
- data.push(
- {type: "hour", range: [0, 23], value: hour},
- {type: "minute", range: [0, 59], value: minute},
- {type: "second", range: [0, 59], value: second}
- );
- }
- return data;
- }
-
- render() {
- const {id} = this.props;
- return (
- {
- this.dateElementProps.map((props, i) => (
- -
-
-
- ))
- }
- -
- Now
-
- -
- Clear
-
-
- );
- }
-}
-
if (process.env.NODE_ENV !== "production") {
DateWidget.propTypes = {
schema: PropTypes.object.isRequired,
id: PropTypes.string.isRequired,
placeholder: PropTypes.string,
- value: React.PropTypes.string,
+ value: PropTypes.string,
required: PropTypes.bool,
onChange: PropTypes.func,
- time: PropTypes.bool,
};
}
diff --git a/src/utils.js b/src/utils.js
index 4ca5299d46..bef3d00594 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -9,6 +9,8 @@ import SelectWidget from "./components/widgets/SelectWidget";
import TextWidget from "./components/widgets/TextWidget";
import DateWidget from "./components/widgets/DateWidget";
import DateTimeWidget from "./components/widgets/DateTimeWidget";
+import AltDateWidget from "./components/widgets/AltDateWidget";
+import AltDateTimeWidget from "./components/widgets/AltDateTimeWidget";
import EmailWidget from "./components/widgets/EmailWidget";
import URLWidget from "./components/widgets/URLWidget";
import TextareaWidget from "./components/widgets/TextareaWidget";
@@ -29,6 +31,9 @@ const altWidgetMap = {
textarea: TextareaWidget,
hidden: HiddenWidget,
date: DateWidget,
+ datetime: DateTimeWidget,
+ "alt-date": AltDateWidget,
+ "alt-datetime": AltDateTimeWidget,
},
number: {
updown: UpDownWidget,
diff --git a/test/StringField_test.js b/test/StringField_test.js
index 1359934349..41b7c3c200 100644
--- a/test/StringField_test.js
+++ b/test/StringField_test.js
@@ -176,12 +176,160 @@ describe("StringField", () => {
});
describe("DateTimeWidget", () => {
- it("should render a datetime field", () => {
+ it("should render an datetime-local field", () => {
+ const {node} = createFormComponent({schema: {
+ type: "string",
+ format: "date-time",
+ }});
+
+ expect(node.querySelectorAll(".field [type=datetime-local]"))
+ .to.have.length.of(1);
+ });
+
+ it("should assign a default value", () => {
+ const datetime = new Date().toJSON();
+ const {comp} = createFormComponent({schema: {
+ type: "string",
+ format: "date-time",
+ default: datetime,
+ }});
+
+ expect(comp.state.formData).eql(datetime);
+ });
+
+ it("should reflect the change into the dom", () => {
+ const {node} = createFormComponent({schema: {
+ type: "string",
+ format: "date-time",
+ }});
+
+ const newDatetime = new Date().toJSON();
+ return SimulateAsync().change(node.querySelector("[type=datetime-local]"), {
+ target: {value: newDatetime}
+ })
+ .then(() => {
+ return expect(node.querySelector("[type=datetime-local]").value)
+ // XXX import and use conversion helper
+ .eql(newDatetime.slice(0, 19));
+ });
+ });
+
+ it("should fill field with data", () => {
+ const datetime = new Date().toJSON();
+ const {comp} = createFormComponent({schema: {
+ type: "string",
+ format: "date-time",
+ }, formData: datetime});
+
+ expect(comp.state.formData).eql(datetime);
+ });
+
+ it("should render the widget with the expected id", () => {
const {node} = createFormComponent({schema: {
type: "string",
format: "date-time",
}});
+ expect(node.querySelector("[type=datetime-local]").id)
+ .eql("root");
+ });
+
+ it("should reject an invalid entered datetime", () => {
+ const {comp, node} = createFormComponent({schema: {
+ type: "string",
+ format: "date-time",
+ }, liveValidate: true});
+
+ return SimulateAsync().change(node.querySelector("[type=datetime-local]"), {
+ target: {value: "invalid"}
+ })
+ .then(() => expect(comp.state.errors).to.have.length.of(1));
+ });
+ });
+
+ describe("DateWidget", () => {
+ const uiSchema = {"ui:widget": "date"};
+
+ it("should render a date field", () => {
+ const {node} = createFormComponent({schema: {
+ type: "string",
+ format: "date-time",
+ }, uiSchema});
+
+ expect(node.querySelectorAll(".field [type=date]"))
+ .to.have.length.of(1);
+ });
+
+ it("should assign a default value", () => {
+ const datetime = new Date().toJSON();
+ const {comp} = createFormComponent({schema: {
+ type: "string",
+ format: "date-time",
+ default: datetime,
+ }, uiSchema});
+
+ expect(comp.state.formData).eql(datetime);
+ });
+
+ it("should reflect the change into the dom", () => {
+ const {node} = createFormComponent({schema: {
+ type: "string",
+ format: "date-time",
+ }, uiSchema});
+
+ const newDatetime = new Date().toJSON();
+ return SimulateAsync().change(node.querySelector("[type=date]"), {
+ target: {value: newDatetime}
+ })
+ .then(() => {
+ return expect(node.querySelector("[type=date]").value)
+ // XXX import and use conversion helper
+ .eql(newDatetime.slice(0, 10));
+ });
+ });
+
+ it("should fill field with data", () => {
+ const datetime = new Date().toJSON();
+ const {comp} = createFormComponent({schema: {
+ type: "string",
+ format: "date-time",
+ }, formData: datetime});
+
+ expect(comp.state.formData).eql(datetime);
+ });
+
+ it("should render the widget with the expected id", () => {
+ const {node} = createFormComponent({schema: {
+ type: "string",
+ format: "date-time",
+ }, uiSchema});
+
+ expect(node.querySelector("[type=date]").id)
+ .eql("root");
+ });
+
+ it("should reject an invalid entered datetime", () => {
+ const {comp, node} = createFormComponent({schema: {
+ type: "string",
+ format: "date-time",
+ }, uiSchema, liveValidate: true});
+
+ return SimulateAsync().change(node.querySelector("[type=date]"), {
+ target: {value: "invalid"}
+ })
+ .then(() => expect(comp.state.errors).to.have.length.of(1));
+ });
+ });
+
+ describe("AltDateTimeWidget", () => {
+ const uiSchema = {"ui:widget": "alt-datetime"};
+
+ it("should render a datetime field", () => {
+ const {node} = createFormComponent({schema: {
+ type: "string",
+ format: "date-time",
+ }, uiSchema});
+
expect(node.querySelectorAll(".field select"))
.to.have.length.of(6);
});
@@ -191,7 +339,7 @@ describe("StringField", () => {
type: "string",
format: "date-time",
title: "foo",
- }});
+ }, uiSchema});
expect(node.querySelector(".field label").textContent)
.eql("foo");
@@ -203,7 +351,7 @@ describe("StringField", () => {
type: "string",
format: "date-time",
default: datetime,
- }});
+ }, uiSchema});
expect(comp.state.formData).eql(datetime);
});
@@ -212,15 +360,21 @@ describe("StringField", () => {
const {comp, node} = createFormComponent({schema: {
type: "string",
format: "date-time",
- }});
+ }, uiSchema});
return Promise.all([
- SimulateAsync().change(node.querySelector("#root_year"), {target: {value: 2012}}),
- SimulateAsync().change(node.querySelector("#root_month"), {target: {value: 10}}),
- SimulateAsync().change(node.querySelector("#root_day"), {target: {value: 2}}),
- SimulateAsync().change(node.querySelector("#root_hour"), {target: {value: 1}}),
- SimulateAsync().change(node.querySelector("#root_minute"), {target: {value: 2}}),
- SimulateAsync().change(node.querySelector("#root_second"), {target: {value: 3}}),
+ SimulateAsync().change(
+ node.querySelector("#root_year"), {target: {value: 2012}}),
+ SimulateAsync().change(
+ node.querySelector("#root_month"), {target: {value: 10}}),
+ SimulateAsync().change(
+ node.querySelector("#root_day"), {target: {value: 2}}),
+ SimulateAsync().change(
+ node.querySelector("#root_hour"), {target: {value: 1}}),
+ SimulateAsync().change(
+ node.querySelector("#root_minute"), {target: {value: 2}}),
+ SimulateAsync().change(
+ node.querySelector("#root_second"), {target: {value: 3}}),
])
.then(() => {
expect(comp.state.formData).eql("2012-10-02T01:02:03.000Z");
@@ -241,7 +395,7 @@ describe("StringField", () => {
const {node} = createFormComponent({schema: {
type: "string",
format: "date-time",
- }});
+ }, uiSchema});
const ids = [].map.call(node.querySelectorAll("select"), node => node.id);
@@ -259,9 +413,10 @@ describe("StringField", () => {
const {node} = createFormComponent({schema: {
type: "string",
format: "date-time",
- }});
+ }, uiSchema});
- const lengths = [].map.call(node.querySelectorAll("select"), node => node.length);
+ const lengths = [].map.call(node.querySelectorAll("select"),
+ node => node.length);
expect(lengths).eql([
121 + 1, // from 1900 to 2020 + undefined
@@ -272,29 +427,31 @@ describe("StringField", () => {
60 + 1
]);
const monthOptions = node.querySelectorAll("select#root_month option");
- const monthOptionsValues = [].map.call(monthOptions, option => option.value);
+ const monthOptionsValues = [].map.call(monthOptions, o => o.value);
expect(monthOptionsValues).eql([
- "-1", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]);
+ "-1", "1", "2", "3", "4", "5", "6",
+ "7", "8", "9", "10", "11", "12"]);
});
it("should render the widgets with the expected options' labels", () => {
const {node} = createFormComponent({schema: {
type: "string",
format: "date-time",
- }});
+ }, uiSchema});
const monthOptions = node.querySelectorAll("select#root_month option");
- const monthOptionsLabels = [].map.call(monthOptions, option => option.text);
+ const monthOptionsLabels = [].map.call(monthOptions, o => o.text);
expect(monthOptionsLabels).eql([
- "month", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"]);
+ "month", "01", "02", "03", "04", "05", "06",
+ "07", "08", "09", "10", "11", "12"]);
});
describe("Action buttons", () => {
- it("should render a action buttons", () => {
+ it("should render action buttons", () => {
const {node} = createFormComponent({schema: {
type: "string",
format: "date-time",
- }});
+ }, uiSchema});
const buttonLabels = [].map.call(node.querySelectorAll("a.btn"),
x => x.textContent);
@@ -305,7 +462,7 @@ describe("StringField", () => {
const {comp, node} = createFormComponent({schema: {
type: "string",
format: "date-time",
- }});
+ }, uiSchema});
return SimulateAsync().click(node.querySelector("a.btn-now"))
.then(() => {
@@ -318,7 +475,7 @@ describe("StringField", () => {
const {comp, node} = createFormComponent({schema: {
type: "string",
format: "date-time",
- }});
+ }, uiSchema});
return SimulateAsync().click(node.querySelector("a.btn-now"))
.then(() => SimulateAsync().click(node.querySelector("a.btn-clear")))
@@ -327,8 +484,8 @@ describe("StringField", () => {
});
});
- describe("DateWidget", () => {
- const uiSchema = {"ui:widget": "date"};
+ describe("AltDateWidget", () => {
+ const uiSchema = {"ui:widget": "alt-date"};
it("should render a date field", () => {
const {node} = createFormComponent({schema: {
@@ -369,9 +526,12 @@ describe("StringField", () => {
}, uiSchema});
return Promise.all([
- SimulateAsync().change(node.querySelector("#root_year"), {target: {value: 2012}}),
- SimulateAsync().change(node.querySelector("#root_month"), {target: {value: 10}}),
- SimulateAsync().change(node.querySelector("#root_day"), {target: {value: 2}}),
+ SimulateAsync().change(
+ node.querySelector("#root_year"), {target: {value: 2012}}),
+ SimulateAsync().change(
+ node.querySelector("#root_month"), {target: {value: 10}}),
+ SimulateAsync().change(
+ node.querySelector("#root_day"), {target: {value: 2}}),
])
.then(() => {
expect(comp.state.formData).eql("2012-10-02T00:00:00.000Z");
@@ -409,7 +569,8 @@ describe("StringField", () => {
format: "date-time",
}, uiSchema});
- const lengths = [].map.call(node.querySelectorAll("select"), node => node.length);
+ const lengths = [].map.call(node.querySelectorAll("select"),
+ node => node.length);
expect(lengths).eql([
121 + 1, // from 1900 to 2020 + undefined
@@ -417,7 +578,7 @@ describe("StringField", () => {
31 + 1,
]);
const monthOptions = node.querySelectorAll("select#root_month option");
- const monthOptionsValues = [].map.call(monthOptions, option => option.value);
+ const monthOptionsValues = [].map.call(monthOptions, o => o.value);
expect(monthOptionsValues).eql([
"-1", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]);
});
@@ -429,13 +590,14 @@ describe("StringField", () => {
}, uiSchema});
const monthOptions = node.querySelectorAll("select#root_month option");
- const monthOptionsLabels = [].map.call(monthOptions, option => option.text);
+ const monthOptionsLabels = [].map.call(monthOptions, o => o.text);
expect(monthOptionsLabels).eql([
- "month", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"]);
+ "month", "01", "02", "03", "04", "05", "06",
+ "07", "08", "09", "10", "11", "12"]);
});
describe("Action buttons", () => {
- it("should render a action buttons", () => {
+ it("should render action buttons", () => {
const {node} = createFormComponent({schema: {
type: "string",
format: "date-time",
@@ -526,7 +688,10 @@ describe("StringField", () => {
return SimulateAsync().change(node.querySelector("[type=email]"), {
target: {value: newDatetime}
})
- .then(() => expect(node.querySelector("[type=email]").value).eql(newDatetime));
+ .then(() => {
+ return expect(node.querySelector("[type=email]").value)
+ .eql(newDatetime);
+ });
});
it("should fill field with data", () => {
@@ -639,7 +804,7 @@ describe("StringField", () => {
.eql("root");
});
- it("should reject an invalid entered email", () => {
+ it("should reject an invalid entered url", () => {
const {comp, node} = createFormComponent({schema: {
type: "string",
format: "uri",