infrastructure-components
Version:
Infrastructure-Components configure the infrastructure of your React-App as part of your React-Components.
1,336 lines (1,146 loc) • 124 kB
JavaScript
/* eslint max-nested-callbacks: [1, 7] */
/* eslint-disable import/no-named-as-default */
import React from "react";
import ReactDOM from "react-dom";
import ReactServer from "react-dom/server";
import {Helmet} from "../src/Helmet";
import {requestAnimationFrame} from "../src/HelmetUtils.js";
const HELMET_ATTRIBUTE = "data-react-helmet";
describe("Helmet", () => {
let headElement;
const container = document.createElement("div");
beforeEach(() => {
headElement =
headElement || document.head || document.querySelector("head");
// resets DOM after each run
headElement.innerHTML = "";
});
afterEach(() => {
ReactDOM.unmountComponentAtNode(container);
});
describe("api", () => {
describe("title", () => {
it("updates page title", done => {
ReactDOM.render(
<Helmet defaultTitle={"Fallback"} title={"Test Title"} />,
container
);
requestAnimationFrame(() => {
expect(document.title).to.equal("Test Title");
done();
});
});
it("updates page title with multiple children", done => {
ReactDOM.render(
<div>
<Helmet title={"Test Title"} />
<Helmet title={"Child One Title"} />
<Helmet title={"Child Two Title"} />
</div>,
container
);
requestAnimationFrame(() => {
expect(document.title).to.equal("Child Two Title");
done();
});
});
it("sets title based on deepest nested component", done => {
ReactDOM.render(
<div>
<Helmet title={"Main Title"} />
<Helmet title={"Nested Title"} />
</div>,
container
);
requestAnimationFrame(() => {
expect(document.title).to.equal("Nested Title");
done();
});
});
it("sets title using deepest nested component with a defined title", done => {
ReactDOM.render(
<div>
<Helmet title={"Main Title"} />
<Helmet />
</div>,
container
);
requestAnimationFrame(() => {
expect(document.title).to.equal("Main Title");
done();
});
});
it("uses defaultTitle if no title is defined", done => {
ReactDOM.render(
<Helmet
defaultTitle={"Fallback"}
title={""}
titleTemplate={
"This is a %s of the titleTemplate feature"
}
/>,
container
);
requestAnimationFrame(() => {
expect(document.title).to.equal("Fallback");
done();
});
});
it("uses a titleTemplate if defined", done => {
ReactDOM.render(
<Helmet
defaultTitle={"Fallback"}
title={"Test"}
titleTemplate={
"This is a %s of the titleTemplate feature"
}
/>,
container
);
requestAnimationFrame(() => {
expect(document.title).to.equal(
"This is a Test of the titleTemplate feature"
);
done();
});
});
it("replaces multiple title strings in titleTemplate", done => {
ReactDOM.render(
<Helmet
title={"Test"}
titleTemplate={
"This is a %s of the titleTemplate feature. Another %s."
}
/>,
container
);
requestAnimationFrame(() => {
expect(document.title).to.equal(
"This is a Test of the titleTemplate feature. Another Test."
);
done();
});
});
it("uses a titleTemplate based on deepest nested component", done => {
ReactDOM.render(
<div>
<Helmet
title={"Test"}
titleTemplate={
"This is a %s of the titleTemplate feature"
}
/>
<Helmet
title={"Second Test"}
titleTemplate={
"A %s using nested titleTemplate attributes"
}
/>
</div>,
container
);
requestAnimationFrame(() => {
expect(document.title).to.equal(
"A Second Test using nested titleTemplate attributes"
);
done();
});
});
it("merges deepest component title with nearest upstream titleTemplate", done => {
ReactDOM.render(
<div>
<Helmet
title={"Test"}
titleTemplate={
"This is a %s of the titleTemplate feature"
}
/>
<Helmet title={"Second Test"} />
</div>,
container
);
requestAnimationFrame(() => {
expect(document.title).to.equal(
"This is a Second Test of the titleTemplate feature"
);
done();
});
});
it("renders dollar characters in a title correctly when titleTemplate present", done => {
const dollarTitle = "te$t te$$t te$$$t te$$$$t";
ReactDOM.render(
<Helmet
title={dollarTitle}
titleTemplate={"This is a %s"}
/>,
container
);
requestAnimationFrame(() => {
expect(document.title).to.equal(
"This is a te$t te$$t te$$$t te$$$$t"
);
done();
});
});
it("does not encode all characters with HTML character entity equivalents", done => {
const chineseTitle = "膣膗 鍆錌雔";
ReactDOM.render(
<div>
<Helmet title={chineseTitle} />
</div>,
container
);
requestAnimationFrame(() => {
expect(document.title).to.equal(chineseTitle);
done();
});
});
it("page title with prop itemprop", done => {
ReactDOM.render(
<Helmet
defaultTitle={"Fallback"}
title={"Test Title with itemProp"}
titleAttributes={{itemprop: "name"}}
/>,
container
);
requestAnimationFrame(() => {
const titleTag = document.getElementsByTagName("title")[0];
expect(document.title).to.equal("Test Title with itemProp");
expect(titleTag.getAttribute("itemprop")).to.equal("name");
done();
});
});
});
describe("title attributes", () => {
beforeEach(() => {
headElement.innerHTML = `<title>Test Title</title>`;
});
it("update title attributes", done => {
ReactDOM.render(
<Helmet
titleAttributes={{
itemprop: "name"
}}
/>,
container
);
requestAnimationFrame(() => {
const titleTag = document.getElementsByTagName("title")[0];
expect(titleTag.getAttribute("itemprop")).to.equal("name");
expect(titleTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(
"itemprop"
);
done();
});
});
it("sets attributes based on the deepest nested component", done => {
ReactDOM.render(
<div>
<Helmet
titleAttributes={{
lang: "en",
hidden: undefined
}}
/>
<Helmet
titleAttributes={{
lang: "ja"
}}
/>
</div>,
container
);
requestAnimationFrame(() => {
const titleTag = document.getElementsByTagName("title")[0];
expect(titleTag.getAttribute("lang")).to.equal("ja");
expect(titleTag.getAttribute("hidden")).to.equal("");
expect(titleTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(
"lang,hidden"
);
done();
});
});
it("handles valueless attributes", done => {
ReactDOM.render(
<Helmet
titleAttributes={{
hidden: undefined
}}
/>,
container
);
requestAnimationFrame(() => {
const titleTag = document.getElementsByTagName("title")[0];
expect(titleTag.getAttribute("hidden")).to.equal("");
expect(titleTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(
"hidden"
);
done();
});
});
it("clears title attributes that are handled within helmet", done => {
ReactDOM.render(
<Helmet
titleAttributes={{
lang: "en",
hidden: undefined
}}
/>,
container
);
requestAnimationFrame(() => {
ReactDOM.render(<Helmet />, container);
requestAnimationFrame(() => {
const titleTag = document.getElementsByTagName(
"title"
)[0];
expect(titleTag.getAttribute("lang")).to.be.null;
expect(titleTag.getAttribute("hidden")).to.be.null;
expect(
titleTag.getAttribute(HELMET_ATTRIBUTE)
).to.equal(null);
done();
});
});
});
});
describe("html attributes", () => {
it("updates html attributes", done => {
ReactDOM.render(
<Helmet
htmlAttributes={{
class: "myClassName",
lang: "en"
}}
lang="en"
/>,
container
);
requestAnimationFrame(() => {
const htmlTag = document.getElementsByTagName("html")[0];
expect(htmlTag.getAttribute("class")).to.equal(
"myClassName"
);
expect(htmlTag.getAttribute("lang")).to.equal("en");
expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(
"class,lang"
);
done();
});
});
it("sets attributes based on the deepest nested component", done => {
ReactDOM.render(
<div>
<Helmet
htmlAttributes={{
lang: "en"
}}
/>
<Helmet
htmlAttributes={{
lang: "ja"
}}
/>
</div>,
container
);
requestAnimationFrame(() => {
const htmlTag = document.getElementsByTagName("html")[0];
expect(htmlTag.getAttribute("lang")).to.equal("ja");
expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(
"lang"
);
done();
});
});
it("handles valueless attributes", done => {
ReactDOM.render(
<Helmet
htmlAttributes={{
amp: undefined
}}
/>,
container
);
requestAnimationFrame(() => {
const htmlTag = document.getElementsByTagName("html")[0];
expect(htmlTag.getAttribute("amp")).to.equal("");
expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(
"amp"
);
done();
});
});
it("clears html attributes that are handled within helmet", done => {
ReactDOM.render(
<Helmet
htmlAttributes={{
lang: "en",
amp: undefined
}}
/>,
container
);
requestAnimationFrame(() => {
ReactDOM.render(<Helmet />, container);
requestAnimationFrame(() => {
const htmlTag = document.getElementsByTagName(
"html"
)[0];
expect(htmlTag.getAttribute("lang")).to.be.null;
expect(htmlTag.getAttribute("amp")).to.be.null;
expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(
null
);
done();
});
});
});
it("updates with multiple additions and removals - overwrite and new", done => {
ReactDOM.render(
<Helmet
htmlAttributes={{
lang: "en",
amp: undefined
}}
/>,
container
);
requestAnimationFrame(() => {
ReactDOM.render(
<Helmet
htmlAttributes={{
lang: "ja",
id: "html-tag",
title: "html tag"
}}
/>,
container
);
requestAnimationFrame(() => {
const htmlTag = document.getElementsByTagName(
"html"
)[0];
expect(htmlTag.getAttribute("amp")).to.equal(null);
expect(htmlTag.getAttribute("lang")).to.equal("ja");
expect(htmlTag.getAttribute("id")).to.equal("html-tag");
expect(htmlTag.getAttribute("title")).to.equal(
"html tag"
);
expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(
"lang,id,title"
);
done();
});
});
});
it("updates with multiple additions and removals - all new", done => {
ReactDOM.render(
<Helmet
htmlAttributes={{
lang: "en",
amp: undefined
}}
/>,
container
);
requestAnimationFrame(() => {
ReactDOM.render(
<Helmet
htmlAttributes={{
id: "html-tag",
title: "html tag"
}}
/>,
container
);
requestAnimationFrame(() => {
const htmlTag = document.getElementsByTagName(
"html"
)[0];
expect(htmlTag.getAttribute("amp")).to.equal(null);
expect(htmlTag.getAttribute("lang")).to.equal(null);
expect(htmlTag.getAttribute("id")).to.equal("html-tag");
expect(htmlTag.getAttribute("title")).to.equal(
"html tag"
);
expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(
"id,title"
);
done();
});
});
});
context("initialized outside of helmet", () => {
before(() => {
const htmlTag = document.getElementsByTagName("html")[0];
htmlTag.setAttribute("test", "test");
});
it("attributes are not cleared", done => {
ReactDOM.render(<Helmet />, container);
requestAnimationFrame(() => {
const htmlTag = document.getElementsByTagName(
"html"
)[0];
expect(htmlTag.getAttribute("test")).to.equal("test");
expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(
null
);
done();
});
});
it("attributes are overwritten if specified in helmet", done => {
ReactDOM.render(
<Helmet
htmlAttributes={{
test: "helmet-attr"
}}
/>,
container
);
requestAnimationFrame(() => {
const htmlTag = document.getElementsByTagName(
"html"
)[0];
expect(htmlTag.getAttribute("test")).to.equal(
"helmet-attr"
);
expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(
"test"
);
done();
});
});
it("attributes are cleared once managed in helmet", done => {
ReactDOM.render(
<Helmet
htmlAttributes={{
test: "helmet-attr"
}}
/>,
container
);
requestAnimationFrame(() => {
ReactDOM.render(<Helmet />, container);
requestAnimationFrame(() => {
const htmlTag = document.getElementsByTagName(
"html"
)[0];
expect(htmlTag.getAttribute("test")).to.equal(null);
expect(
htmlTag.getAttribute(HELMET_ATTRIBUTE)
).to.equal(null);
done();
});
});
});
});
});
describe("onChangeClientState", () => {
it("when handling client state change, calls the function with new state, addedTags and removedTags ", done => {
const spy = sinon.spy();
ReactDOM.render(
<div>
<Helmet
base={{href: "http://mysite.com/"}}
link={[
{
href: "http://localhost/helmet",
rel: "canonical"
}
]}
meta={[{charset: "utf-8"}]}
script={[
{
src: "http://localhost/test.js",
type: "text/javascript"
}
]}
title={"Main Title"}
onChangeClientState={spy}
/>
</div>,
container
);
requestAnimationFrame(() => {
expect(spy.called).to.equal(true);
const newState = spy.getCall(0).args[0];
const addedTags = spy.getCall(0).args[1];
const removedTags = spy.getCall(0).args[2];
expect(newState).to.contain({title: "Main Title"});
expect(newState.baseTag).to.contain({
href: "http://mysite.com/"
});
expect(newState.metaTags).to.contain({charset: "utf-8"});
expect(newState.linkTags).to.contain({
href: "http://localhost/helmet",
rel: "canonical"
});
expect(newState.scriptTags).to.contain({
src: "http://localhost/test.js",
type: "text/javascript"
});
expect(addedTags).to.have.property("baseTag");
expect(addedTags.baseTag).to.have.deep.property("[0]");
expect(addedTags.baseTag[0].outerHTML).to.equal(
`<base href="http://mysite.com/" data-react-helmet="true">`
);
expect(addedTags).to.have.property("metaTags");
expect(addedTags.metaTags).to.have.deep.property("[0]");
expect(addedTags.metaTags[0].outerHTML).to.equal(
`<meta charset="utf-8" data-react-helmet="true">`
);
expect(addedTags).to.have.property("linkTags");
expect(addedTags.linkTags).to.have.deep.property("[0]");
expect(addedTags.linkTags[0].outerHTML).to.equal(
`<link href="http://localhost/helmet" rel="canonical" data-react-helmet="true">`
);
expect(addedTags).to.have.property("scriptTags");
expect(addedTags.scriptTags).to.have.deep.property("[0]");
expect(addedTags.scriptTags[0].outerHTML).to.equal(
`<script src="http://localhost/test.js" type="text/javascript" data-react-helmet="true"></script>`
);
expect(removedTags).to.be.empty;
done();
});
});
it("calls the deepest defined callback with the deepest state", done => {
const spy = sinon.spy();
ReactDOM.render(
<div>
<Helmet
title={"Main Title"}
onChangeClientState={spy}
/>
<Helmet title={"Deeper Title"} />
</div>,
container
);
requestAnimationFrame(() => {
expect(spy.callCount).to.equal(1);
expect(spy.getCall(0).args[0]).to.contain({
title: "Deeper Title"
});
done();
});
});
});
describe("base tag", () => {
it("updates base tag", done => {
ReactDOM.render(
<Helmet base={{href: "http://mysite.com/"}} />,
container
);
requestAnimationFrame(() => {
const existingTags = headElement.querySelectorAll(
`base[${HELMET_ATTRIBUTE}]`
);
expect(existingTags).to.not.equal(undefined);
const filteredTags = [].slice
.call(existingTags)
.filter(tag => {
return (
tag.getAttribute("href") ===
"http://mysite.com/"
);
});
expect(filteredTags.length).to.equal(1);
done();
});
});
it("clears the base tag if one is not specified", done => {
ReactDOM.render(
<Helmet base={{href: "http://mysite.com/"}} />,
container
);
requestAnimationFrame(() => {
ReactDOM.render(<Helmet />, container);
requestAnimationFrame(() => {
const existingTags = headElement.querySelectorAll(
`base[${HELMET_ATTRIBUTE}]`
);
expect(existingTags).to.not.equal(undefined);
expect(existingTags.length).to.equal(0);
done();
});
});
});
it("tags without 'href' are not accepted", done => {
ReactDOM.render(
<Helmet base={{property: "won't work"}} />,
container
);
requestAnimationFrame(() => {
const existingTags = headElement.querySelectorAll(
`base[${HELMET_ATTRIBUTE}]`
);
expect(existingTags).to.not.equal(undefined);
expect(existingTags.length).to.equal(0);
done();
});
});
it("sets base tag based on deepest nested component", done => {
ReactDOM.render(
<div>
<Helmet base={{href: "http://mysite.com/"}} />
<Helmet base={{href: "http://mysite.com/public"}} />
</div>,
container
);
requestAnimationFrame(() => {
const existingTags = headElement.querySelectorAll(
`base[${HELMET_ATTRIBUTE}]`
);
const firstTag = Array.prototype.slice.call(
existingTags
)[0];
expect(existingTags).to.not.equal(undefined);
expect(existingTags.length).to.be.equal(1);
expect(existingTags).to.have.deep
.property("[0]")
.that.is.an.instanceof(Element);
expect(firstTag).to.have.property("getAttribute");
expect(firstTag.getAttribute("href")).to.equal(
"http://mysite.com/public"
);
expect(firstTag.outerHTML).to.equal(
`<base href="http://mysite.com/public" ${HELMET_ATTRIBUTE}="true">`
);
done();
});
});
it("does not render tag when primary attribute is null", done => {
ReactDOM.render(<Helmet base={{href: undefined}} />, container);
requestAnimationFrame(() => {
const tagNodes = headElement.querySelectorAll(
`base[${HELMET_ATTRIBUTE}]`
);
const existingTags = Array.prototype.slice.call(tagNodes);
expect(existingTags).to.be.empty;
done();
});
});
});
describe("meta tags", () => {
it("updates meta tags", done => {
ReactDOM.render(
<Helmet
meta={[
{charset: "utf-8"},
{
name: "description",
content: "Test description"
},
{
"http-equiv": "content-type",
content: "text/html"
},
{property: "og:type", content: "article"},
{itemprop: "name", content: "Test name itemprop"}
]}
/>,
container
);
requestAnimationFrame(() => {
const tagNodes = headElement.querySelectorAll(
`meta[${HELMET_ATTRIBUTE}]`
);
const existingTags = Array.prototype.slice.call(tagNodes);
expect(existingTags).to.not.equal(undefined);
const filteredTags = [].slice
.call(existingTags)
.filter(tag => {
return (
tag.getAttribute("charset") === "utf-8" ||
(tag.getAttribute("name") === "description" &&
tag.getAttribute("content") ===
"Test description") ||
(tag.getAttribute("http-equiv") ===
"content-type" &&
tag.getAttribute("content") ===
"text/html") ||
(tag.getAttribute("itemprop") === "name" &&
tag.getAttribute("content") ===
"Test name itemprop")
);
});
expect(filteredTags.length).to.be.at.least(4);
done();
});
});
it("clears all meta tags if none are specified", done => {
ReactDOM.render(
<Helmet
meta={[
{name: "description", content: "Test description"}
]}
/>,
container
);
requestAnimationFrame(() => {
ReactDOM.render(<Helmet />, container);
requestAnimationFrame(() => {
const existingTags = headElement.querySelectorAll(
`meta[${HELMET_ATTRIBUTE}]`
);
expect(existingTags).to.not.equal(undefined);
expect(existingTags.length).to.equal(0);
done();
});
});
});
it("tags without 'name', 'http-equiv', 'property', 'charset', or 'itemprop' are not accepted", done => {
ReactDOM.render(
<Helmet meta={[{href: "won't work"}]} />,
container
);
requestAnimationFrame(() => {
const existingTags = headElement.querySelectorAll(
`meta[${HELMET_ATTRIBUTE}]`
);
expect(existingTags).to.not.equal(undefined);
expect(existingTags.length).to.equal(0);
done();
});
});
it("sets meta tags based on deepest nested component", done => {
ReactDOM.render(
<div>
<Helmet
meta={[
{charset: "utf-8"},
{
name: "description",
content: "Test description"
}
]}
/>
<Helmet
meta={[
{
name: "description",
content: "Inner description"
},
{name: "keywords", content: "test,meta,tags"}
]}
/>
</div>,
container
);
requestAnimationFrame(() => {
const tagNodes = headElement.querySelectorAll(
`meta[${HELMET_ATTRIBUTE}]`
);
const existingTags = Array.prototype.slice.call(tagNodes);
const firstTag = existingTags[0];
const secondTag = existingTags[1];
const thirdTag = existingTags[2];
expect(existingTags).to.not.equal(undefined);
expect(existingTags.length).to.be.equal(3);
expect(existingTags).to.have.deep
.property("[0]")
.that.is.an.instanceof(Element);
expect(firstTag).to.have.property("getAttribute");
expect(firstTag.getAttribute("charset")).to.equal("utf-8");
expect(firstTag.outerHTML).to.equal(
`<meta charset="utf-8" ${HELMET_ATTRIBUTE}="true">`
);
expect(existingTags).to.have.deep
.property("[1]")
.that.is.an.instanceof(Element);
expect(secondTag).to.have.property("getAttribute");
expect(secondTag.getAttribute("name")).to.equal(
"description"
);
expect(secondTag.getAttribute("content")).to.equal(
"Inner description"
);
expect(secondTag.outerHTML).to.equal(
`<meta name="description" content="Inner description" ${HELMET_ATTRIBUTE}="true">`
);
expect(existingTags).to.have.deep
.property("[2]")
.that.is.an.instanceof(Element);
expect(thirdTag).to.have.property("getAttribute");
expect(thirdTag.getAttribute("name")).to.equal("keywords");
expect(thirdTag.getAttribute("content")).to.equal(
"test,meta,tags"
);
expect(thirdTag.outerHTML).to.equal(
`<meta name="keywords" content="test,meta,tags" ${HELMET_ATTRIBUTE}="true">`
);
done();
});
});
it("allows duplicate meta tags if specified in the same component", done => {
ReactDOM.render(
<Helmet
meta={[
{
name: "description",
content: "Test description"
},
{
name: "description",
content: "Duplicate description"
}
]}
/>,
container
);
requestAnimationFrame(() => {
const tagNodes = headElement.querySelectorAll(
`meta[${HELMET_ATTRIBUTE}]`
);
const existingTags = Array.prototype.slice.call(tagNodes);
const firstTag = existingTags[0];
const secondTag = existingTags[1];
expect(existingTags).to.not.equal(undefined);
expect(existingTags.length).to.equal(2);
expect(existingTags).to.have.deep
.property("[0]")
.that.is.an.instanceof(Element);
expect(firstTag).to.have.property("getAttribute");
expect(firstTag.getAttribute("name")).to.equal(
"description"
);
expect(firstTag.getAttribute("content")).to.equal(
"Test description"
);
expect(firstTag.outerHTML).to.equal(
`<meta name="description" content="Test description" ${HELMET_ATTRIBUTE}="true">`
);
expect(existingTags).to.have.deep
.property("[1]")
.that.is.an.instanceof(Element);
expect(secondTag).to.have.property("getAttribute");
expect(secondTag.getAttribute("name")).to.equal(
"description"
);
expect(secondTag.getAttribute("content")).to.equal(
"Duplicate description"
);
expect(secondTag.outerHTML).to.equal(
`<meta name="description" content="Duplicate description" ${HELMET_ATTRIBUTE}="true">`
);
done();
});
});
it("overrides duplicate meta tags with single meta tag in a nested component", done => {
ReactDOM.render(
<div>
<Helmet
meta={[
{
name: "description",
content: "Test description"
},
{
name: "description",
content: "Duplicate description"
}
]}
/>
<Helmet
meta={[
{
name: "description",
content: "Inner description"
}
]}
/>
</div>,
container
);
requestAnimationFrame(() => {
const tagNodes = headElement.querySelectorAll(
`meta[${HELMET_ATTRIBUTE}]`
);
const existingTags = Array.prototype.slice.call(tagNodes);
const firstTag = existingTags[0];
expect(existingTags).to.not.equal(undefined);
expect(existingTags.length).to.equal(1);
expect(existingTags).to.have.deep
.property("[0]")
.that.is.an.instanceof(Element);
expect(firstTag).to.have.property("getAttribute");
expect(firstTag.getAttribute("name")).to.equal(
"description"
);
expect(firstTag.getAttribute("content")).to.equal(
"Inner description"
);
expect(firstTag.outerHTML).to.equal(
`<meta name="description" content="Inner description" ${HELMET_ATTRIBUTE}="true">`
);
done();
});
});
it("overrides single meta tag with duplicate meta tags in a nested component", done => {
ReactDOM.render(
<div>
<Helmet
meta={[
{
name: "description",
content: "Test description"
}
]}
/>
<Helmet
meta={[
{
name: "description",
content: "Inner description"
},
{
name: "description",
content: "Inner duplicate description"
}
]}
/>
</div>,
container
);
requestAnimationFrame(() => {
const tagNodes = headElement.querySelectorAll(
`meta[${HELMET_ATTRIBUTE}]`
);
const existingTags = Array.prototype.slice.call(tagNodes);
const firstTag = existingTags[0];
const secondTag = existingTags[1];
expect(existingTags).to.not.equal(undefined);
expect(existingTags.length).to.equal(2);
expect(existingTags).to.have.deep
.property("[0]")
.that.is.an.instanceof(Element);
expect(firstTag).to.have.property("getAttribute");
expect(firstTag.getAttribute("name")).to.equal(
"description"
);
expect(firstTag.getAttribute("content")).to.equal(
"Inner description"
);
expect(firstTag.outerHTML).to.equal(
`<meta name="description" content="Inner description" ${HELMET_ATTRIBUTE}="true">`
);
expect(existingTags).to.have.deep
.property("[1]")
.that.is.an.instanceof(Element);
expect(secondTag).to.have.property("getAttribute");
expect(secondTag.getAttribute("name")).to.equal(
"description"
);
expect(secondTag.getAttribute("content")).to.equal(
"Inner duplicate description"
);
expect(secondTag.outerHTML).to.equal(
`<meta name="description" content="Inner duplicate description" ${HELMET_ATTRIBUTE}="true">`
);
done();
});
});
it("does not render tag when primary attribute is null", done => {
ReactDOM.render(
<Helmet
meta={[
{
name: undefined,
content: "Inner duplicate description"
}
]}
/>,
container
);
requestAnimationFrame(() => {
const tagNodes = headElement.querySelectorAll(
`meta[${HELMET_ATTRIBUTE}]`
);
const existingTags = Array.prototype.slice.call(tagNodes);
expect(existingTags).to.be.empty;
done();
});
});
it("fails gracefully when meta is wrong shape", done => {
const error = sinon.stub(console, "error");
const warn = sinon.stub(console, "warn");
ReactDOM.render(
<Helmet meta={{name: "title", content: "some title"}} />,
container
);
requestAnimationFrame(() => {
const tagNodes = headElement.querySelectorAll(
`meta[${HELMET_ATTRIBUTE}]`
);
const existingTags = Array.prototype.slice.call(tagNodes);
expect(existingTags).to.be.empty;
expect(error.called).to.be.true;
expect(warn.called).to.be.true;
const [warning] = warn.getCall(0).args;
expect(warning).to.equal(
`Helmet: meta should be of type "Array". Instead found type "object"`
);
error.restore();
warn.restore();
done();
});
});
});
describe("link tags", () => {
it("updates link tags", done => {
ReactDOM.render(
<Helmet
link={[
{
href: "http://localhost/helmet",
rel: "canonical"
},
{
href: "http://localhost/style.css",
rel: "stylesheet",
type: "text/css"
}
]}
/>,
container
);
requestAnimationFrame(() => {
const tagNodes = headElement.querySelectorAll(
`link[${HELMET_ATTRIBUTE}]`
);
const existingTags = Array.prototype.slice.call(tagNodes);
expect(existingTags).to.not.equal(undefined);
const filteredTags = [].slice
.call(existingTags)
.filter(tag => {
return (
(tag.getAttribute("href") ===
"http://localhost/style.css" &&
tag.getAttribute("rel") === "stylesheet" &&
tag.getAttribute("type") === "text/css") ||
(tag.getAttribute("href") ===
"http://localhost/helmet" &&
tag.getAttribute("rel") === "canonical")
);
});
expect(filteredTags.length).to.be.at.least(2);
done();
});
});
it("clears all link tags if none are specified", done => {
ReactDOM.render(
<Helmet
link={[
{
href: "http://localhost/helmet",
rel: "canonical"
}
]}
/>,
container
);
requestAnimationFrame(() => {
ReactDOM.render(<Helmet />, container);
requestAnimationFrame(() => {
const tagNodes = headElemen