Skip to content

Commit

Permalink
Refs #113: Added support for the url string format.
Browse files Browse the repository at this point in the history
  • Loading branch information
n1k0 committed Apr 4, 2016
1 parent d17491e commit b94e854
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ The built-in string field also supports the JSONSchema `format` property, and wi

- `date-time`: An `input[type=datetime-local]` element is used;
- `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!

#### For `number` and `integer` fields
Expand Down
37 changes: 37 additions & 0 deletions src/components/widgets/EmailWidget.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React, { PropTypes } from "react";


function EmailWidget({
schema,
id,
placeholder,
value,
defaultValue,
required,
onChange
}) {
return (
<input type="email"
id={id}
className="form-control"
value={value}
defaultValue={defaultValue}
placeholder={placeholder}
required={required}
onChange={(event) => onChange(event.target.value)} />
);
}

if (process.env.NODE_ENV !== "production") {
EmailWidget.propTypes = {
schema: PropTypes.object.isRequired,
id: PropTypes.string.isRequired,
placeholder: PropTypes.string,
value: React.PropTypes.string,
defaultValue: React.PropTypes.string,
required: PropTypes.bool,
onChange: PropTypes.func,
};
}

export default EmailWidget;
37 changes: 37 additions & 0 deletions src/components/widgets/URLWidget.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React, { PropTypes } from "react";


function URLWidget({
schema,
id,
placeholder,
value,
defaultValue,
required,
onChange
}) {
return (
<input type="url"
id={id}
className="form-control"
value={value}
defaultValue={defaultValue}
placeholder={placeholder}
required={required}
onChange={(event) => onChange(event.target.value)} />
);
}

if (process.env.NODE_ENV !== "production") {
URLWidget.propTypes = {
schema: PropTypes.object.isRequired,
id: PropTypes.string.isRequired,
placeholder: PropTypes.string,
value: React.PropTypes.string,
defaultValue: React.PropTypes.string,
required: PropTypes.bool,
onChange: PropTypes.func,
};
}

export default URLWidget;
3 changes: 2 additions & 1 deletion src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import SelectWidget from "./components/widgets/SelectWidget";
import TextWidget from "./components/widgets/TextWidget";
import DateTimeWidget from "./components/widgets/DateTimeWidget";
import EmailWidget from "./components/widgets/EmailWidget";
import URLWidget from "./components/widgets/URLWidget";
import TextareaWidget from "./components/widgets/TextareaWidget";
import HiddenWidget from "./components/widgets/HiddenWidget";

Expand Down Expand Up @@ -45,7 +46,7 @@ const stringFormatWidgets = {
"hostname": TextWidget,
"ipv4": TextWidget,
"ipv6": TextWidget,
"uri": TextWidget, // XXX: to customize appropriately
"uri": URLWidget,
};

export function defaultTypeValue(type) {
Expand Down
92 changes: 92 additions & 0 deletions test/StringField_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -347,4 +347,96 @@ describe("StringField", () => {
expect(comp.state.errors).to.have.length.of(1);
});
});

describe("URLWidget", () => {
it("should render an url field", () => {
const {node} = createFormComponent({schema: {
type: "string",
format: "uri",
}});

expect(node.querySelectorAll(".field [type=url]"))
.to.have.length.of(1);
});

it("should render a string field with a label", () => {
const {node} = createFormComponent({schema: {
type: "string",
format: "uri",
title: "foo",
}});

expect(node.querySelector(".field label").textContent)
.eql("foo");
});

it("should render a select field with a placeholder", () => {
const {node} = createFormComponent({schema: {
type: "string",
format: "uri",
description: "baz",
}});

expect(node.querySelector(".field [type=url]").getAttribute("placeholder"))
.eql("baz");
});

it("should assign a default value", () => {
const url = "http://foo.bar/baz";
const {comp} = createFormComponent({schema: {
type: "string",
format: "uri",
default: url,
}});

expect(comp.state.formData).eql(url);
});

it("should reflect the change into the dom", () => {
const {node} = createFormComponent({schema: {
type: "string",
format: "uri",
}});

const newDatetime = new Date().toJSON();
Simulate.change(node.querySelector("[type=url]"), {
target: {value: newDatetime}
});

expect(node.querySelector("[type=url]").value).eql(newDatetime);
});

it("should fill field with data", () => {
const url = "http://foo.bar/baz";
const {comp} = createFormComponent({schema: {
type: "string",
format: "uri",
}, formData: url});

expect(comp.state.formData).eql(url);
});

it("should render the widget with the expected id", () => {
const {node} = createFormComponent({schema: {
type: "string",
format: "uri",
}});

expect(node.querySelector("[type=url]").id)
.eql("root");
});

it("should reject an invalid entered email", () => {
const {comp, node} = createFormComponent({schema: {
type: "string",
format: "uri",
}, liveValidate: true});

Simulate.change(node.querySelector("[type=url]"), {
target: {value: "invalid"}
});

expect(comp.state.errors).to.have.length.of(1);
});
});
});

0 comments on commit b94e854

Please sign in to comment.