[
  {
    "path": ".babelrc",
    "content": "{\n    \"presets\": [\n        [\"env\", {\n            \"targets\": {\n                \"browsers\": [\"last 1 versions\", \"ie >= 10\"]\n            },\n            \"modules\": false,\n            \"loose\": true\n        }],\n        \"react\"\n    ],\n    \"plugins\": [\n        \"transform-class-properties\",\n        \"transform-object-rest-spread\",\n        \"external-helpers\"\n    ]\n}\n"
  },
  {
    "path": ".editorconfig",
    "content": "# editorconfig.org\nroot = true\n\n[*]\nindent_style = space\nindent_size = 4\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[package.json]\nindent_style = space\nindent_size = 2\n\n[.travis.yml]\nindent_style = space\nindent_size = 2\n"
  },
  {
    "path": ".eslintrc",
    "content": "{\n    \"extends\": [\"nfl\", \"prettier\"],\n    \"env\": {\n        \"browser\": true,\n        \"mocha\": true,\n        \"es6\": true\n    },\n    \"globals\": {\n        \"expect\": false,\n        \"sinon\": false\n    },\n    \"plugins\": [\n        \"prettier\"\n    ],\n    \"rules\": {\n        \"prettier/prettier\": [\"error\", {\n                \"printWidth\": 80,\n                \"tabWidth\": 4,\n                \"singleQuote\": false,\n                \"trailingComma\": \"none\",\n                \"bracketSpacing\": false,\n                \"semi\": true,\n                \"useTabs\": false,\n                \"parser\": \"babylon\",\n                \"jsxBracketSameLine\": false\n            }\n        ]\n    }\n}\n"
  },
  {
    "path": ".gitignore",
    "content": ".DS_Store\n.eslintcache\n.idea\ncoverage\nes\nlib\nnode_modules\nnpm-debug.log\n"
  },
  {
    "path": ".npmignore",
    "content": ".arcconfig\n.babelrc\n.editorconfig\n.eslintrc\n.nvmrc\n*.yml\nCHANGELOG.md\nCONTRIBUTING.md\ncoverage\nkarma.config.js\ntest/\nnode_modules\nsrc\ntravis.yml\nrollup.config.js\n"
  },
  {
    "path": ".nvmrc",
    "content": "v6.6.0\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\n\nservices:\n  - xvfb\n\naddons:\n  apt:\n    packages:\n      - google-chrome-stable\n\nnode_js:\n  - \"node\"\n  - 12\n  - 11\n  - 10\n  - 8\n\nbefore_install:\n  - export CHROME_BIN=/usr/bin/google-chrome\n\ncache:\n  yarn: true\n  directories:\n    - node_modules\n\nafter_success: codecov\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "<a name=\"6.1.0\"></a>\n\n# [6.1.0](https://github.com/nfl/react-helmet/compare/6.0.0...6.1.0) (2020-06-08)\n\n### Features\n\n-   Re-add Helmet as a default export [(#547)](https://github.com/nfl/react-helmet/pull/547)\n    -   Note: You may now choose `import Helmet` or `import {Helmet}`\n-   Updates react-fast-compare to get support for Preact [(#559)](https://github.com/nfl/react-helmet/pull/559)\n\n<a name=\"6.0.0\"></a>\n\n# [6.0.0](https://github.com/nfl/react-helmet/compare/5.2.0...6.0.0) (2020-04-09)\n\n### Features\n\n-   Bundle with Rollup instead of Webpack - As a result, the default export was removed and Helmet must now be imported as a named component - `import {Helmet} from \"react-helmet\"` [(#395)](https://github.com/nfl/react-helmet/pull/395)\n-   Replace deepEqual with isEqual [(#402)](https://github.com/nfl/react-helmet/pull/402)\n\n<a name=\"6.0.0-beta.2\"></a>\n\n# [6.0.0-beta.2](https://github.com/nfl/react-helmet/compare/6.0.0-beta...6.0.0-beta.2) (2020-01-27)\n\n<a name=\"6.0.0-beta\"></a>\n\n# [6.0.0-beta](https://github.com/nfl/react-helmet/compare/5.2.0...6.0.0-beta) (2018-12-07)\n\n<a name=\"5.2.0\"></a>\n\n# [5.2.0](https://github.com/nfl/react-helmet/compare/5.1.3...5.2.0) (2017-08-29)\n\n### Features\n\n-   Adds support for synchronously updated tags\n    ([#297](https://github.com/nfl/react-helmet/pull/297))\n    ([6a3d3bf](https://github.com/nfl/react-helmet/commit/6a3d3bf)), closes [#291](https://github.com/nfl/react-helmet/issues/291)\n\n### Bug Fixes\n\n-   Remove unexpected comma in server-rendered title ([#289](https://github.com/nfl/react-helmet/pull/289)) ([66b8212](https://github.com/nfl/react-helmet/commit/66b8212)), closes [#286](https://github.com/nfl/react-helmet/issues/286)\n-   Replace requestIdleCallback with requestAnimationFrame for a more consistent DOM write cycle. ([#307](https://github.com/nfl/react-helmet/issues/307)) ([a2323ad](https://github.com/nfl/react-helmet/commit/a2323ad))\n\n<a name=\"5.1.3\"></a>\n\n## [5.1.3](https://github.com/nfl/react-helmet/compare/5.0.3...5.1.3) (2017-05-18)\n\n### Bug Fixes\n\n-   Add support for renderable Arrays of strings ([#275](https://github.com/nfl/react-helmet/issues/275)) ([aad5457](https://github.com/nfl/react-helmet/commit/aad5457)), closes [#272](https://github.com/nfl/react-helmet/issues/272)\n\n<a name=\"5.0.3\"></a>\n\n## [5.0.3](https://github.com/nfl/react-helmet/compare/5.0.2...5.0.3) (2017-04-10)\n\n### Bug Fixes\n\n-   React.propTypes -> PropTypes ([#265](https://github.com/nfl/react-helmet/issues/265)) ([68ece0c](https://github.com/nfl/react-helmet/commit/68ece0c))\n\n<a name=\"5.0.2\"></a>\n\n## [5.0.2](https://github.com/nfl/react-helmet/compare/5.0.1...5.0.2) (2017-03-28)\n\n### Bug Fixes\n\n-   prevent clearing existing title ([#259](https://github.com/nfl/react-helmet/issues/259)) ([549b603](https://github.com/nfl/react-helmet/commit/549b603))\n\n<a name=\"5.0.1\"></a>\n\n## [5.0.1](https://github.com/nfl/react-helmet/compare/5.0.0...5.0.1) (2017-03-24)\n\n### Bug Fixes\n\n-   handle falsy children values ([#256](https://github.com/nfl/react-helmet/issues/256)) ([4a60765](https://github.com/nfl/react-helmet/commit/4a60765))\n\n<a name=\"5.0.0\"></a>\n\n# [5.0.0](https://github.com/nfl/react-helmet/compare/4.0.0...5.0.0) (2017-03-21)\n\n### Features\n\n-   New Simplified API (fully backward-compatible) - Helmet now takes plain HTML tags for the majority of the API with just a few remaining props for Helmet - retaining `titleTemplate`, `defaultTitle`, `onChangeClientState`, and one new - `encodeSpecialCharacters` - refer to README for details. Directly passing Helmet props will be deprecated in the future. [(#246)](https://github.com/nfl/react-helmet/pull/246)\n-   `requestIdleCallback` utilized to consolidate DOM changes and makes these non-blocking for things like animations. Fixes first client-side render not matching server-side render. Maintains one DOM change between route changes on the client-side as well. [(#248)](https://github.com/nfl/react-helmet/pull/248)\n-   On server-side, `Helmet.renderStatic()` aliased to `Helmet.rewind()` for more clarity. `rewind` will be deprecated in the future.\n-   Yarn support\n\n# 4.0.0\n\n### Features\n\n-   Replacing PlainComponent with stateless functional component `NullComponent`, with a hard requirement to use React 15 or higher.\n\n# 3.3.2\n\n### Bugfixes\n\n-   Removed stateless functional component `NullComponent` because of it's incompatibility with React 14 and reverted back to PlainComponent.\n\n# 3.3.1 [BROKEN]\n\n### Bugfixes\n\n-   README updates - npm badge and helmet image\n-   Bump react-side-effect to 1.1.0\n-   Removing PlainComponent, replaced with NullComponent defined within Helmet.js\n-   Refactored code - cut lines of code and used `reduce` to simplify functions\n-   Replaced PlainComponent with NullComponent (now within Helmet.js)\n\n# 3.3.0\n\n### Features\n\n-   `itemprop` available in meta tags\n-   New API - `titleAttributes` to add attributes to the title tag\n-   `class` support for html tag\n\n# 3.2.3\n\n### Bugfixes\n\n-   applied previous fix (undefined value for primary attribute key) to base tag\n-   fix htmlAttributes fallback value when calling rewind() on blank Helmet\n-   Removed unneeded dependencies - shallowequal, warning\n-   babel configuration moved into .babelrc\n-   eslint configuration moved into .eslintrc\n\n# 3.2.2\n\n### Bugfixes\n\n-   Removed breaking changes `jsnext:main` and `module` from package.json. `es` version required special babel configuration for end users and needs to be re-thought for major release.\n-   Reverted `canUseDOM` setter in `Helmet.js`, as this was a breaking change for some users.\n-   [fix] runtime error when providing undefined value for primary attribute key (applies to meta, link, script, noscript, style)\n\n# 3.2.1 [BROKEN]\n\n### Bugfixes\n\n-   Removing \"engines\" field in package.json.\n\n# 3.2.0 [BROKEN]\n\n### Features\n\n-   `<noscript>` support\n\n### Bugfixes\n\n-   Prevent stripping dollar signs from title when titleTemplate is present\n-   Offering jsnext:main build\n-   Removed Gulp Dependency\n-   Bump Dependencies\n-   IE8 Support\n\n# 3.1.0\n\n### Features\n\n-   Add support for `<style>` elements.\n\n# 3.0.2\n\n### Bugfixes\n\n-   Avoids rendering \"undefined\" if it's passed in as a value of an attribute, but instead renders just the attribute name.\n-   When htmlAttributes gets cleared, or is blank, the helmet attribute on the html tag, used for tracking, is cleaned up.\n-   Upgrading devDependency of React to 15.\n\n# 3.0.1\n\n### Bugfixes\n\n-   The htmlAttributes feature will no longer remove existing attributes on the HTML tag\n\n# 3.0.0\n\n### Features\n\n-   innerHTML for scripts. Originally added to support the use of JSON-LD (https://developers.google.com/schemas/formats/json-ld?hl=en), but this can be used for any inline scripts you would like in your document head.\n-   New htmlAttributes prop which allows users to add attributes to their html tag.\n-   New defaultTitle prop which allows users to have a fallback title in the scenario where a Helmet wants to define a titleTemplate for it's nested routes, but not for itself (for example, at the root component level). See README for use cases.\n\n### Bugfixes\n\n-   Removed all polyfills from Helmet. Due to reported conflicts, to remove bloat, and to encourage users to polyfill at the application level. Please double-check that you weren't relying solely on Helmet for polyfilling certain features.\n\n# 2.3.1\n\n### Bugfixes\n\n-   Fallback values for rewind on the server threw a `tags.map` error in Node. Changing the tag default values to `[]` fixes it.\n\n# 2.3.0\n\n### Bugfixes\n\n-   FOUC fix - existing tags that persist between route changes, will not be removed and re-added to the DOM. They will remain unchanged. This will avoid, in particular, stylesheets being removed and re-added causing an unstyled flash when the new Helmet is rendered.\n-   onChangeClientState enhanced to also return the html tags that were added and removed.\n-   provide fallback object for rewind() result - If no Helmets are rendered, rewind() will still return head.base, head.title, etc.\n-   Tag attributes ordering does not matter. It no longer looks at the first valid attribute to identify the tag. All attributes of the tag will be searched for names that can be found in HelmetConstants.js. When rel=\"canonical\" is included, it will take priority over href.\n-   Bump dependencies\n\n# 2.2.0\n\n### Features\n\n-   New prop `onChangeClientState` to set a callback function that is called in the event the DOM is changed by Helmet. When set on a Helmet, it will apply to all subsequent Helmet instances downstream (similar to titleTemplate).\n\n### Bugfixes\n\n-   Fix for double encoding when returning state to the server as React components.\n-   dist -> lib\n-   Added CLA url to CONTRIBUTING.\n-   Added .babelrc to .npmignore (fix for now, as the settings were not compatible with Babel 6)\n-   Bump dependencies (except Babel 6 as a dev dependency - coming soon)\n\n# 2.1.1\n\n### Bugfixes\n\n-   Remove npm he dependency\n-   HTML entitiy encode only special characters instead of all characters that have HTML entity equivalents\n\n# 2.1.0\n\n### Features\n\n-   All head attributes (title / base / meta / link / script) returned with `.toComponent()` and `.toString()` methods to use in any scenario when calling rewind on the server.\n-   Helmet using React 14 for unit testing.\n\n### Bugfixes\n\n-   Bump dependencies\n\n# 2.0.0\n\n### Features\n\n-   Base tag support.\n-   Script tag support.\n-   All head attributes (title / base / meta / link / script) returned as React components on the server with toString() support\n-   Removed ability to nest children in Helmet.\n-   Decorated component from react-side-effect, now wrapped by Helmet in order to enforce deep equal check on shouldComponentUpdate. This will limit unnecessary DOM changes and rendering.\n\n### Bugfixes\n\n-   Bump dependencies\n\n# 1.1.5\n\n### Bugfixes\n\n-   Adding webpack under devDependencies, as it's no longer automatically installed as a peer dependency\n-   Bump dependencies\n\n# 1.1.4\n\n### Bugfixes\n\n-   Bumping to react-side-effect 1.0.2\n-   Updating peer dependences for react 0.14.0-rc1\n-   Bump dependencies\n\n# 1.1.3\n\n### Bugfixes\n\n-   Externalize react-side-effect\n-   shouldComponentUpdate compares props with deep equal\n-   handleClientStateChange compares DOM changes with deep equal to prevent unnecessary DOM changes\n-   Warning users to not nest children in their Helmet components. We found that when Helmet contains children, those children are part of the props that are compared in shouldComponentUpdate. And this causes unnecessary renders as the props are always different, even with the same Helmet title/meta/link props.\n-   Adding react-helmet-example to README\n-   Bumping to react-side-effect 1.0.1\n-   Bump dependencies.\n\n# 1.1.2\n\n### Bugfixes\n\n-   Use named exports in HelmetConstants\n-   Allow all React 0.14 betas in peer dependencies\n-   Bump dependencies.\n-   Fixed invariant check in CreateSideEffect\n\n# 1.1.1\n\n### Bugfixes\n\n-   Externalizing of React helpers - exenv, invariant, shallowequal\n-   Using ES6 collections to manage tags\n-   Bumping peer dependency for use in React 0.14.0-beta.\n-   Title encoded when being rendered on the server\n-   Import a smaller subset of core-js modules instead of the whole shim.\n\n# 1.1.0\n\n### Features\n\n-   titleTemplate attribute to help format `document.title`\n\n### Bugfixes\n\n-   Bump dependencies.\n-   Title will never be overwritten with blank title. Lifts constraint where every component with Helmet needed to define a title.\n-   Re-organization of unit tests.\n\n# 1.0.1\n\n### Bugfixes\n\n-   Bump dependencies\n-   rewind() saves title/meta/link values before disposing\n-   Typo in README - use Helmet.rewind()\n-   \"he\" package added to dependencies\n-   Added Travis CI integration\n-   npm requirement removed - removed reference in README (System Requirements) and in package.json (engines)\n\n# 1.0.0\n\n### Features\n\n-   Initial release\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, we as\ncontributors and maintainers pledge to making participation in our project and\nour community a harassment-free experience for everyone, regardless of age, body\nsize, disability, ethnicity, sex characteristics, gender identity and expression,\nlevel of experience, education, socio-economic status, nationality, personal\nappearance, race, religion, or sexual identity and orientation.\n\n## Our Standards\n\nExamples of behavior that contributes to creating a positive environment\ninclude:\n\n* Using welcoming and inclusive language\n* Being respectful of differing viewpoints and experiences\n* Gracefully accepting constructive criticism\n* Focusing on what is best for the community\n* Showing empathy towards other community members\n\nExamples of unacceptable behavior by participants include:\n\n* The use of sexualized language or imagery and unwelcome sexual attention or\n advances\n* Trolling, insulting/derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or electronic\n address, without explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n professional setting\n\n## Our Responsibilities\n\nProject maintainers are responsible for clarifying the standards of acceptable\nbehavior and are expected to take appropriate and fair corrective action in\nresponse to any instances of unacceptable behavior.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct, or to ban temporarily or\npermanently any contributor for other behaviors that they deem inappropriate,\nthreatening, offensive, or harmful.\n\n## Scope\n\nThis Code of Conduct applies both within project spaces and in public spaces\nwhen an individual is representing the project or its community. Examples of\nrepresenting a project or community include using an official project e-mail\naddress, posting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event. Representation of a project may be\nfurther defined and clarified by project maintainers.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by contacting the project team at engineers@nfl.com. All\ncomplaints will be reviewed and investigated and will result in a response that\nis deemed necessary and appropriate to the circumstances. The project team is\nobligated to maintain confidentiality with regard to the reporter of an incident.\nFurther details of specific enforcement policies may be posted separately.\n\nProject maintainers who do not follow or enforce the Code of Conduct in good\nfaith may face temporary or permanent repercussions as determined by other\nmembers of the project's leadership.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,\navailable at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see\nhttps://www.contributor-covenant.org/faq\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [Contributing to this project](#contributing-to-this-project)\n  - [Pull requests](#pull-requests)\n  - [Development Process](#development-process)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n# Contributing to this project\n\nPlease take a moment to review this document in order to make the contribution\nprocess easy and effective for everyone involved.\n\n_**Please Note:** These guidelines are adapted from [@necolas](https://github.com/necolas)'s\n[issue-guidelines](https://github.com/necolas/issue-guidelines) and serve as\nan excellent starting point for contributing to any open source project._\n\n<a name=\"pull-requests\"></a>\n## Pull requests\n\nGood pull requests - patches, improvements, new features - are a fantastic\nhelp. They should remain focused in scope and avoid containing unrelated\ncommits.\n\n**Please ask first** before embarking on any significant pull request (e.g.\nimplementing features, refactoring code, porting to a different language),\notherwise you risk spending a lot of time working on something that the\nproject's developers might not want to merge into the project.\n\nMake sure to sign the CLA - https://cla-assistant.io/nfl/react-helmet along with your PR submission.\n\n<a name=\"development\"></a>\n## Development Process\nHere are some guidelines to making changes and preparing your PR:\n\n1. Make your proposed changes to the repository, along with updating/adding test cases.\n2. (Optional) If you prefer to also test your changes in a real application, you can do the following:\n  1. Run `npm link` in `react-helmet` repository.\n  2. `cd` to your favorite React application, run `npm link react-helmet` to point to your local repository.\n  3. Run your application to verify your changes.\n3. Run `npm test` to verify all test cases pass.\n4. Run `npm run lint` to verify there are no linting errors.\n"
  },
  {
    "path": "ISSUE_TEMPLATE.md",
    "content": "**Do you want to request a *feature* or report a *bug*?**\n\n**What is the current behavior?**\n\n**If the current behavior is a bug, \nplease provide the steps to reproduce and if \npossible a minimal demo of the problem. \nYour bug will get fixed much faster if we can run your \ncode and it doesn't have dependencies other than React and react-helmet. \nPaste the link to your JSFiddle (https://jsfiddle.net/Luktwrdm/) or \nCodeSandbox (https://codesandbox.io/s/new) example below:**\n\n**What is the expected behavior?**\n\n**Which versions of React and react-helmet, and which browser / OS are affected by this issue? \nDid this work in previous versions of React and/or react-helmet?**\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2015 NFL\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<img align=\"right\" width=\"200\" src=\"http://static.nfl.com/static/content/public/static/img/logos/react-helmet.jpg\" />\n\n# React Helmet\n\n[![npm Version](https://img.shields.io/npm/v/react-helmet.svg?style=flat-square)](https://www.npmjs.org/package/react-helmet)\n[![codecov.io](https://img.shields.io/codecov/c/github/nfl/react-helmet.svg?branch=master&style=flat-square)](https://codecov.io/github/nfl/react-helmet?branch=master)\n[![Build Status](https://img.shields.io/travis/nfl/react-helmet/master.svg?style=flat-square)](https://travis-ci.org/nfl/react-helmet)\n[![Dependency Status](https://img.shields.io/david/nfl/react-helmet.svg?style=flat-square)](https://david-dm.org/nfl/react-helmet)\n[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](CONTRIBUTING.md#pull-requests)\n\nThis reusable React component will manage all of your changes to the document head.\n\nHelmet _takes_ plain HTML tags and _outputs_ plain HTML tags. It's dead simple, and React beginner friendly.\n\n## [6.1.0 Major Changes](https://github.com/nfl/react-helmet/releases/tag/6.1.0)\n\n\n## Example\n```javascript\nimport React from \"react\";\nimport {Helmet} from \"react-helmet\";\n\nclass Application extends React.Component {\n  render () {\n    return (\n        <div className=\"application\">\n            <Helmet>\n                <meta charSet=\"utf-8\" />\n                <title>My Title</title>\n                <link rel=\"canonical\" href=\"http://mysite.com/example\" />\n            </Helmet>\n            ...\n        </div>\n    );\n  }\n};\n```\n\nNested or latter components will override duplicate changes:\n\n```javascript\n<Parent>\n    <Helmet>\n        <title>My Title</title>\n        <meta name=\"description\" content=\"Helmet application\" />\n    </Helmet>\n\n    <Child>\n        <Helmet>\n            <title>Nested Title</title>\n            <meta name=\"description\" content=\"Nested component\" />\n        </Helmet>\n    </Child>\n</Parent>\n```\n\noutputs:\n\n```html\n<head>\n    <title>Nested Title</title>\n    <meta name=\"description\" content=\"Nested component\">\n</head>\n```\n\nSee below for a full reference guide.\n\n## Features\n- Supports all valid head tags: `title`, `base`, `meta`, `link`, `script`, `noscript`, and `style` tags.\n- Supports attributes for `body`, `html` and `title` tags.\n- Supports server-side rendering.\n- Nested components override duplicate head changes.\n- Duplicate head changes are preserved when specified in the same component (support for tags like \"apple-touch-icon\").\n- Callback for tracking DOM changes.\n\n## Compatibility\n\nHelmet 5 is fully backward-compatible with previous Helmet releases, so you can upgrade at any time without fear of breaking changes. We encourage you to update your code to our more semantic API, but please feel free to do so at your own pace.\n\n## Installation\n\nYarn:\n```bash\nyarn add react-helmet\n```\n\nnpm:\n```bash\nnpm install --save react-helmet\n```\n\n## Server Usage\nTo use on the server, call `Helmet.renderStatic()` after `ReactDOMServer.renderToString` or `ReactDOMServer.renderToStaticMarkup` to get the head data for use in your prerender.\n\nBecause this component keeps track of mounted instances, **you have to make sure to call `renderStatic` on server**, or you'll get a memory leak.\n\n```javascript\nReactDOMServer.renderToString(<Handler />);\nconst helmet = Helmet.renderStatic();\n```\n\nThis `helmet` instance contains the following properties:\n- `base`\n- `bodyAttributes`\n- `htmlAttributes`\n- `link`\n- `meta`\n- `noscript`\n- `script`\n- `style`\n- `title`\n\nEach property contains `toComponent()` and `toString()` methods. Use whichever is appropriate for your environment. For attributes, use the JSX spread operator on the object returned by `toComponent()`. E.g:\n\n### As string output\n```javascript\nconst html = `\n    <!doctype html>\n    <html ${helmet.htmlAttributes.toString()}>\n        <head>\n            ${helmet.title.toString()}\n            ${helmet.meta.toString()}\n            ${helmet.link.toString()}\n        </head>\n        <body ${helmet.bodyAttributes.toString()}>\n            <div id=\"content\">\n                // React stuff here\n            </div>\n        </body>\n    </html>\n`;\n```\n\n### As React components\n```javascript\nfunction HTML () {\n    const htmlAttrs = helmet.htmlAttributes.toComponent();\n    const bodyAttrs = helmet.bodyAttributes.toComponent();\n\n    return (\n        <html {...htmlAttrs}>\n            <head>\n                {helmet.title.toComponent()}\n                {helmet.meta.toComponent()}\n                {helmet.link.toComponent()}\n            </head>\n            <body {...bodyAttrs}>\n                <div id=\"content\">\n                    // React stuff here\n                </div>\n            </body>\n        </html>\n    );\n}\n```\n\n### Note: Use the same instance\nIf you are using a prebuilt compilation of your app with webpack in the server be sure to include this in the `webpack file` so that the same instance of `react-helmet` is used.\n```\nexternals: [\"react-helmet\"],\n```\nOr to import the *react-helmet* instance from the app on the server.\n\n### Reference Guide\n\n```javascript\n<Helmet\n    {/* (optional) set to false to disable string encoding (server-only) */}\n    encodeSpecialCharacters={true}\n\n    {/*\n        (optional) Useful when you want titles to inherit from a template:\n\n        <Helmet\n            titleTemplate=\"%s | MyAwesomeWebsite.com\"\n        >\n            <title>Nested Title</title>\n        </Helmet>\n\n        outputs:\n\n        <head>\n            <title>Nested Title | MyAwesomeWebsite.com</title>\n        </head>\n    */}\n    titleTemplate=\"MySite.com - %s\"\n\n    {/*\n        (optional) used as a fallback when a template exists but a title is not defined\n\n        <Helmet\n            defaultTitle=\"My Site\"\n            titleTemplate=\"My Site - %s\"\n        />\n\n        outputs:\n\n        <head>\n            <title>My Site</title>\n        </head>\n    */}\n    defaultTitle=\"My Default Title\"\n    \n    {/* (optional) set to false to not use requestAnimationFrame and instead update the DOM as soon as possible.\n        Useful if you want to update the title when the tab is out of focus \n    */}\n    defer={false}\n\n    {/* (optional) callback that tracks DOM changes */}\n    onChangeClientState={(newState, addedTags, removedTags) => console.log(newState, addedTags, removedTags)}\n>\n    {/* html attributes */}\n    <html lang=\"en\" amp />\n\n    {/* body attributes */}\n    <body className=\"root\" />\n\n    {/* title attributes and value */}\n    <title itemProp=\"name\" lang=\"en\">My Plain Title or {`dynamic`} title</title>\n\n    {/* base element */}\n    <base target=\"_blank\" href=\"http://mysite.com/\" />\n\n    {/* multiple meta elements */}\n    <meta name=\"description\" content=\"Helmet application\" />\n    <meta property=\"og:type\" content=\"article\" />\n\n    {/* multiple link elements */}\n    <link rel=\"canonical\" href=\"http://mysite.com/example\" />\n    <link rel=\"apple-touch-icon\" href=\"http://mysite.com/img/apple-touch-icon-57x57.png\" />\n    <link rel=\"apple-touch-icon\" sizes=\"72x72\" href=\"http://mysite.com/img/apple-touch-icon-72x72.png\" />\n    {locales.map((locale) => {\n        <link rel=\"alternate\" href=\"http://example.com/{locale}\" hrefLang={locale} key={locale}/>\n    })}\n\n    {/* multiple script elements */}\n    <script src=\"http://include.com/pathtojs.js\" type=\"text/javascript\" />\n\n    {/* inline script elements */}\n    <script type=\"application/ld+json\">{`\n        {\n            \"@context\": \"http://schema.org\"\n        }\n    `}</script>\n\n    {/* noscript elements */}\n    <noscript>{`\n        <link rel=\"stylesheet\" type=\"text/css\" href=\"foo.css\" />\n    `}</noscript>\n\n    {/* inline style elements */}\n    <style type=\"text/css\">{`\n        body {\n            background-color: blue;\n        }\n\n        p {\n            font-size: 12px;\n        }\n    `}</style>\n</Helmet>\n```\n\n## Contributing to this project\nPlease take a moment to review the [guidelines for contributing](CONTRIBUTING.md).\n\n* [Pull requests](CONTRIBUTING.md#pull-requests)\n* [Development Process](CONTRIBUTING.md#development)\n\n## License\n\nMIT\n\n<img align=\"left\" height=\"200\" src=\"http://static.nfl.com/static/content/public/static/img/logos/ENG_SigilLockup_4C_POS_RGB.png\" />\n"
  },
  {
    "path": "karma.config.js",
    "content": "// Karma configuration\n\nmodule.exports = function(config) {\n    function normalizationBrowserName(browser) {\n        return browser.toLowerCase().split(/[ /-]/)[0];\n    }\n\n    config.set({\n        // ... normal karma configuration\n        basePath: \"\",\n\n        // How long will Karma wait for a message from a browser before disconnecting from it (in ms).\n        browserNoActivityTimeout: 60000,\n\n        client: {\n            mocha: {\n                bail: true,\n                reporter: \"html\"\n            }\n        },\n\n        // frameworks to use\n        frameworks: [\"chai-sinon\", \"mocha\"],\n\n        files: [\"./test/*.js\"],\n\n        preprocessors: {\n            \"./test/*.js\": [\"rollup\", \"sourcemap\"]\n        },\n\n        coverageReporter: {\n            dir: \"coverage/json\",\n            includeAllSources: true,\n            reporters: [\n                {\n                    type: \"json\",\n                    subdir: normalizationBrowserName\n                }\n            ]\n        },\n\n        rollupPreprocessor: {\n            output: {\n                format: \"iife\",\n                name: \"helmet\",\n                sourcemap: \"inline\"\n            },\n            plugins: [\n                require(\"rollup-plugin-replace\")({\n                    \"process.env.NODE_ENV\": \"'development'\"\n                }),\n                require(\"rollup-plugin-babel\")({\n                    exclude: \"node_modules/**\",\n                    plugins: [\n                        [\n                            \"istanbul\",\n                            {\n                                exclude: [\"**/node_modules/**\", \"**/test/**\"]\n                            }\n                        ]\n                    ]\n                }),\n                require(\"rollup-plugin-node-resolve\")({\n                    browser: true\n                }),\n                require(\"rollup-plugin-commonjs\")()\n            ]\n        },\n\n        // test results reporter to use\n        // possible values: \"dots\", \"progress\", \"junit\", \"growl\", \"coverage\"\n        reporters: [\"coverage\", \"spec\"],\n\n        // web server port\n        port: 9876,\n\n        // enable / disable colors in the output (reporters and logs)\n        colors: true,\n\n        // level of logging\n        // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG\n        logLevel: config.LOG_INFO,\n\n        // enable / disable watching file and executing tests whenever any file changes\n        autoWatch: true,\n\n        // Start these browsers, currently available:\n        // - Chrome\n        // - ChromeCanary\n        // - Firefox\n        // - Opera (has to be installed with `npm install karma-opera-launcher`)\n        // - Safari (only Mac; has to be installed with `npm install karma-safari-launcher`)\n        // - PhantomJS\n        // - IE (only Windows; has to be installed with `npm install karma-ie-launcher`)\n        browsers: process.env.TRAVIS ? [\"ChromeTravis\"] : [\"Chrome\", \"Firefox\"],\n\n        customLaunchers: {\n            ChromeTravis: {\n                base: \"Chrome\",\n                flags: [\"--no-sandbox\"]\n            }\n        },\n\n        // If browser does not capture in given timeout [ms], kill it\n        captureTimeout: 60000,\n\n        // Continuous Integration mode\n        // if true, it capture browsers, run tests and exit\n        singleRun: true\n    });\n};\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"react-helmet\",\n  \"description\": \"A document head manager for React\",\n  \"version\": \"6.1.0\",\n  \"main\": \"./lib/Helmet.js\",\n  \"module\": \"./es/Helmet.js\",\n  \"author\": \"NFL <engineers@nfl.com>\",\n  \"contributors\": [\n    \"Chris Welch <chris.welch@nfl.com>\",\n    \"Robert dela Victoria <robert.delavictoria@nfl.com>\"\n  ],\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/nfl/react-helmet\"\n  },\n  \"keywords\": [\n    \"react-helmet\",\n    \"nfl\",\n    \"react\",\n    \"document\",\n    \"head\",\n    \"title\",\n    \"meta\",\n    \"link\",\n    \"script\",\n    \"base\",\n    \"noscript\",\n    \"style\"\n  ],\n  \"peerDependencies\": {\n    \"react\": \">=16.3.0\"\n  },\n  \"dependencies\": {\n    \"object-assign\": \"^4.1.1\",\n    \"prop-types\": \"^15.7.2\",\n    \"react-fast-compare\": \"^3.1.1\",\n    \"react-side-effect\": \"^2.1.0\"\n  },\n  \"devDependencies\": {\n    \"babel-core\": \"^6.24.0\",\n    \"babel-eslint\": \"^9.0.0\",\n    \"babel-plugin-external-helpers\": \"^6.22.0\",\n    \"babel-plugin-istanbul\": \"^4.0.0\",\n    \"babel-plugin-transform-class-properties\": \"^6.23.0\",\n    \"babel-plugin-transform-object-rest-spread\": \"^6.23.0\",\n    \"babel-preset-env\": \"^1.2.2\",\n    \"babel-preset-react\": \"^6.23.0\",\n    \"chai\": \"^3.5.0\",\n    \"codecov\": \"^3.6.5\",\n    \"conventional-changelog-cli\": \"^1.3.1\",\n    \"cz-conventional-changelog\": \"^2.0.0\",\n    \"eslint\": \"^3.18.0\",\n    \"eslint-config-nfl\": \"^11.1.0\",\n    \"eslint-config-prettier\": \"^6.11.0\",\n    \"eslint-plugin-import\": \"^2.2.0\",\n    \"eslint-plugin-jsx-a11y\": \"^6.2.3\",\n    \"eslint-plugin-mocha\": \"^4.9.0\",\n    \"eslint-plugin-prettier\": \"^2.1.2\",\n    \"eslint-plugin-react\": \"^6.10.2\",\n    \"istanbul\": \"^0.4.5\",\n    \"karma\": \"^1.5.0\",\n    \"karma-chai\": \"^0.1.0\",\n    \"karma-chai-sinon\": \"^0.1.5\",\n    \"karma-chrome-launcher\": \"^3.1.0\",\n    \"karma-coverage\": \"^1.1.1\",\n    \"karma-firefox-launcher\": \"^1.0.1\",\n    \"karma-html-reporter\": \"^0.2.7\",\n    \"karma-mocha\": \"^2.0.1\",\n    \"karma-rollup-preprocessor\": \"^6.1.0\",\n    \"karma-sourcemap-loader\": \"^0.3.7\",\n    \"karma-spec-reporter\": \"^0.0.32\",\n    \"karma-tap-reporter\": \"^0.0.6\",\n    \"mocha\": \"^7.2.0\",\n    \"prettier\": \"^1.4.4\",\n    \"react\": \"16.13.1\",\n    \"react-dom\": \"16.13.1\",\n    \"rimraf\": \"^3.0.2\",\n    \"rollup\": \"^0.67.0\",\n    \"rollup-plugin-babel\": \"^3.0.7\",\n    \"rollup-plugin-commonjs\": \"^9.2.0\",\n    \"rollup-plugin-node-resolve\": \"^3.4.0\",\n    \"rollup-plugin-replace\": \"^2.1.0\",\n    \"sinon\": \"^2.1.0\",\n    \"sinon-chai\": \"^2.8.0\"\n  },\n  \"scripts\": {\n    \"changelog\": \"conventional-changelog -p angular -i CHANGELOG.md -s\",\n    \"clean\": \"rimraf lib coverage es\",\n    \"lint\": \"eslint --ignore-path .gitignore --fix -- .\",\n    \"test\": \"karma start karma.config.js\",\n    \"posttest\": \"istanbul report lcov text\",\n    \"pretest\": \"npm run clean && npm run lint\",\n    \"commit\": \"git-cz\",\n    \"build\": \"rollup -c\",\n    \"prepublish\": \"npm run build\"\n  },\n  \"config\": {\n    \"commitizen\": {\n      \"path\": \"./node_modules/cz-conventional-changelog\"\n    }\n  }\n}\n"
  },
  {
    "path": "rollup.config.js",
    "content": "import babel from \"rollup-plugin-babel\";\n\nimport pkg from \"./package.json\";\n\nconst baseConfig = {\n    input: \"src/Helmet.js\",\n    plugins: [\n        babel({\n            exclude: \"node_modules/**\"\n        })\n    ],\n    external: [\n        ...Object.keys(pkg.dependencies),\n        ...Object.keys(pkg.peerDependencies)\n    ]\n};\n\nexport default [\n    Object.assign(\n        {\n            output: {\n                file: pkg.main,\n                format: \"cjs\"\n            }\n        },\n        baseConfig\n    ),\n    Object.assign(\n        {\n            output: {\n                file: \"es/Helmet.js\",\n                format: \"esm\"\n            }\n        },\n        baseConfig\n    )\n];\n"
  },
  {
    "path": "src/Helmet.js",
    "content": "import React from \"react\";\nimport PropTypes from \"prop-types\";\nimport withSideEffect from \"react-side-effect\";\nimport isEqual from \"react-fast-compare\";\nimport {\n    convertReactPropstoHtmlAttributes,\n    handleClientStateChange,\n    mapStateOnServer,\n    reducePropsToState,\n    warn\n} from \"./HelmetUtils.js\";\nimport {TAG_NAMES, VALID_TAG_NAMES} from \"./HelmetConstants.js\";\n\nconst Helmet = Component =>\n    class HelmetWrapper extends React.Component {\n        /**\n         * @param {Object} base: {\"target\": \"_blank\", \"href\": \"http://mysite.com/\"}\n         * @param {Object} bodyAttributes: {\"className\": \"root\"}\n         * @param {String} defaultTitle: \"Default Title\"\n         * @param {Boolean} defer: true\n         * @param {Boolean} encodeSpecialCharacters: true\n         * @param {Object} htmlAttributes: {\"lang\": \"en\", \"amp\": undefined}\n         * @param {Array} link: [{\"rel\": \"canonical\", \"href\": \"http://mysite.com/example\"}]\n         * @param {Array} meta: [{\"name\": \"description\", \"content\": \"Test description\"}]\n         * @param {Array} noscript: [{\"innerHTML\": \"<img src='http://mysite.com/js/test.js'\"}]\n         * @param {Function} onChangeClientState: \"(newState) => console.log(newState)\"\n         * @param {Array} script: [{\"type\": \"text/javascript\", \"src\": \"http://mysite.com/js/test.js\"}]\n         * @param {Array} style: [{\"type\": \"text/css\", \"cssText\": \"div { display: block; color: blue; }\"}]\n         * @param {String} title: \"Title\"\n         * @param {Object} titleAttributes: {\"itemprop\": \"name\"}\n         * @param {String} titleTemplate: \"MySite.com - %s\"\n         */\n        static propTypes = {\n            base: PropTypes.object,\n            bodyAttributes: PropTypes.object,\n            children: PropTypes.oneOfType([\n                PropTypes.arrayOf(PropTypes.node),\n                PropTypes.node\n            ]),\n            defaultTitle: PropTypes.string,\n            defer: PropTypes.bool,\n            encodeSpecialCharacters: PropTypes.bool,\n            htmlAttributes: PropTypes.object,\n            link: PropTypes.arrayOf(PropTypes.object),\n            meta: PropTypes.arrayOf(PropTypes.object),\n            noscript: PropTypes.arrayOf(PropTypes.object),\n            onChangeClientState: PropTypes.func,\n            script: PropTypes.arrayOf(PropTypes.object),\n            style: PropTypes.arrayOf(PropTypes.object),\n            title: PropTypes.string,\n            titleAttributes: PropTypes.object,\n            titleTemplate: PropTypes.string\n        };\n\n        static defaultProps = {\n            defer: true,\n            encodeSpecialCharacters: true\n        };\n\n        // Component.peek comes from react-side-effect:\n        // For testing, you may use a static peek() method available on the returned component.\n        // It lets you get the current state without resetting the mounted instance stack.\n        // Don’t use it for anything other than testing.\n        static peek = Component.peek;\n\n        static rewind = () => {\n            let mappedState = Component.rewind();\n            if (!mappedState) {\n                // provide fallback if mappedState is undefined\n                mappedState = mapStateOnServer({\n                    baseTag: [],\n                    bodyAttributes: {},\n                    encodeSpecialCharacters: true,\n                    htmlAttributes: {},\n                    linkTags: [],\n                    metaTags: [],\n                    noscriptTags: [],\n                    scriptTags: [],\n                    styleTags: [],\n                    title: \"\",\n                    titleAttributes: {}\n                });\n            }\n\n            return mappedState;\n        };\n\n        static set canUseDOM(canUseDOM) {\n            Component.canUseDOM = canUseDOM;\n        }\n\n        shouldComponentUpdate(nextProps) {\n            return !isEqual(this.props, nextProps);\n        }\n\n        mapNestedChildrenToProps(child, nestedChildren) {\n            if (!nestedChildren) {\n                return null;\n            }\n\n            switch (child.type) {\n                case TAG_NAMES.SCRIPT:\n                case TAG_NAMES.NOSCRIPT:\n                    return {\n                        innerHTML: nestedChildren\n                    };\n\n                case TAG_NAMES.STYLE:\n                    return {\n                        cssText: nestedChildren\n                    };\n            }\n\n            throw new Error(\n                `<${\n                    child.type\n                } /> elements are self-closing and can not contain children. Refer to our API for more information.`\n            );\n        }\n\n        flattenArrayTypeChildren({\n            child,\n            arrayTypeChildren,\n            newChildProps,\n            nestedChildren\n        }) {\n            return {\n                ...arrayTypeChildren,\n                [child.type]: [\n                    ...(arrayTypeChildren[child.type] || []),\n                    {\n                        ...newChildProps,\n                        ...this.mapNestedChildrenToProps(child, nestedChildren)\n                    }\n                ]\n            };\n        }\n\n        mapObjectTypeChildren({\n            child,\n            newProps,\n            newChildProps,\n            nestedChildren\n        }) {\n            switch (child.type) {\n                case TAG_NAMES.TITLE:\n                    return {\n                        ...newProps,\n                        [child.type]: nestedChildren,\n                        titleAttributes: {...newChildProps}\n                    };\n\n                case TAG_NAMES.BODY:\n                    return {\n                        ...newProps,\n                        bodyAttributes: {...newChildProps}\n                    };\n\n                case TAG_NAMES.HTML:\n                    return {\n                        ...newProps,\n                        htmlAttributes: {...newChildProps}\n                    };\n            }\n\n            return {\n                ...newProps,\n                [child.type]: {...newChildProps}\n            };\n        }\n\n        mapArrayTypeChildrenToProps(arrayTypeChildren, newProps) {\n            let newFlattenedProps = {...newProps};\n\n            Object.keys(arrayTypeChildren).forEach(arrayChildName => {\n                newFlattenedProps = {\n                    ...newFlattenedProps,\n                    [arrayChildName]: arrayTypeChildren[arrayChildName]\n                };\n            });\n\n            return newFlattenedProps;\n        }\n\n        warnOnInvalidChildren(child, nestedChildren) {\n            if (process.env.NODE_ENV !== \"production\") {\n                if (!VALID_TAG_NAMES.some(name => child.type === name)) {\n                    if (typeof child.type === \"function\") {\n                        return warn(\n                            `You may be attempting to nest <Helmet> components within each other, which is not allowed. Refer to our API for more information.`\n                        );\n                    }\n\n                    return warn(\n                        `Only elements types ${VALID_TAG_NAMES.join(\n                            \", \"\n                        )} are allowed. Helmet does not support rendering <${\n                            child.type\n                        }> elements. Refer to our API for more information.`\n                    );\n                }\n\n                if (\n                    nestedChildren &&\n                    typeof nestedChildren !== \"string\" &&\n                    (!Array.isArray(nestedChildren) ||\n                        nestedChildren.some(\n                            nestedChild => typeof nestedChild !== \"string\"\n                        ))\n                ) {\n                    throw new Error(\n                        `Helmet expects a string as a child of <${\n                            child.type\n                        }>. Did you forget to wrap your children in braces? ( <${\n                            child.type\n                        }>{\\`\\`}</${\n                            child.type\n                        }> ) Refer to our API for more information.`\n                    );\n                }\n            }\n\n            return true;\n        }\n\n        mapChildrenToProps(children, newProps) {\n            let arrayTypeChildren = {};\n\n            React.Children.forEach(children, child => {\n                if (!child || !child.props) {\n                    return;\n                }\n\n                const {children: nestedChildren, ...childProps} = child.props;\n                const newChildProps = convertReactPropstoHtmlAttributes(\n                    childProps\n                );\n\n                this.warnOnInvalidChildren(child, nestedChildren);\n\n                switch (child.type) {\n                    case TAG_NAMES.LINK:\n                    case TAG_NAMES.META:\n                    case TAG_NAMES.NOSCRIPT:\n                    case TAG_NAMES.SCRIPT:\n                    case TAG_NAMES.STYLE:\n                        arrayTypeChildren = this.flattenArrayTypeChildren({\n                            child,\n                            arrayTypeChildren,\n                            newChildProps,\n                            nestedChildren\n                        });\n                        break;\n\n                    default:\n                        newProps = this.mapObjectTypeChildren({\n                            child,\n                            newProps,\n                            newChildProps,\n                            nestedChildren\n                        });\n                        break;\n                }\n            });\n\n            newProps = this.mapArrayTypeChildrenToProps(\n                arrayTypeChildren,\n                newProps\n            );\n            return newProps;\n        }\n\n        render() {\n            const {children, ...props} = this.props;\n            let newProps = {...props};\n\n            if (children) {\n                newProps = this.mapChildrenToProps(children, newProps);\n            }\n\n            return <Component {...newProps} />;\n        }\n    };\n\nconst NullComponent = () => null;\n\nconst HelmetSideEffects = withSideEffect(\n    reducePropsToState,\n    handleClientStateChange,\n    mapStateOnServer\n)(NullComponent);\n\nconst HelmetExport = Helmet(HelmetSideEffects);\nHelmetExport.renderStatic = HelmetExport.rewind;\n\nexport {HelmetExport as Helmet};\nexport default HelmetExport;\n"
  },
  {
    "path": "src/HelmetConstants.js",
    "content": "export const ATTRIBUTE_NAMES = {\n    BODY: \"bodyAttributes\",\n    HTML: \"htmlAttributes\",\n    TITLE: \"titleAttributes\"\n};\n\nexport const TAG_NAMES = {\n    BASE: \"base\",\n    BODY: \"body\",\n    HEAD: \"head\",\n    HTML: \"html\",\n    LINK: \"link\",\n    META: \"meta\",\n    NOSCRIPT: \"noscript\",\n    SCRIPT: \"script\",\n    STYLE: \"style\",\n    TITLE: \"title\"\n};\n\nexport const VALID_TAG_NAMES = Object.values(TAG_NAMES);\n\nexport const TAG_PROPERTIES = {\n    CHARSET: \"charset\",\n    CSS_TEXT: \"cssText\",\n    HREF: \"href\",\n    HTTPEQUIV: \"http-equiv\",\n    INNER_HTML: \"innerHTML\",\n    ITEM_PROP: \"itemprop\",\n    NAME: \"name\",\n    PROPERTY: \"property\",\n    REL: \"rel\",\n    SRC: \"src\",\n    TARGET: \"target\"\n};\n\nexport const REACT_TAG_MAP = {\n    accesskey: \"accessKey\",\n    charset: \"charSet\",\n    class: \"className\",\n    contenteditable: \"contentEditable\",\n    contextmenu: \"contextMenu\",\n    \"http-equiv\": \"httpEquiv\",\n    itemprop: \"itemProp\",\n    tabindex: \"tabIndex\"\n};\n\nexport const HELMET_PROPS = {\n    DEFAULT_TITLE: \"defaultTitle\",\n    DEFER: \"defer\",\n    ENCODE_SPECIAL_CHARACTERS: \"encodeSpecialCharacters\",\n    ON_CHANGE_CLIENT_STATE: \"onChangeClientState\",\n    TITLE_TEMPLATE: \"titleTemplate\"\n};\n\nexport const HTML_TAG_MAP = Object.keys(REACT_TAG_MAP).reduce((obj, key) => {\n    obj[REACT_TAG_MAP[key]] = key;\n    return obj;\n}, {});\n\nexport const SELF_CLOSING_TAGS = [\n    TAG_NAMES.NOSCRIPT,\n    TAG_NAMES.SCRIPT,\n    TAG_NAMES.STYLE\n];\n\nexport const HELMET_ATTRIBUTE = \"data-react-helmet\";\n"
  },
  {
    "path": "src/HelmetUtils.js",
    "content": "import React from \"react\";\nimport objectAssign from \"object-assign\";\nimport {\n    ATTRIBUTE_NAMES,\n    HELMET_ATTRIBUTE,\n    HELMET_PROPS,\n    HTML_TAG_MAP,\n    REACT_TAG_MAP,\n    SELF_CLOSING_TAGS,\n    TAG_NAMES,\n    TAG_PROPERTIES\n} from \"./HelmetConstants.js\";\n\nconst encodeSpecialCharacters = (str, encode = true) => {\n    if (encode === false) {\n        return String(str);\n    }\n\n    return String(str)\n        .replace(/&/g, \"&amp;\")\n        .replace(/</g, \"&lt;\")\n        .replace(/>/g, \"&gt;\")\n        .replace(/\"/g, \"&quot;\")\n        .replace(/'/g, \"&#x27;\");\n};\n\nconst getTitleFromPropsList = propsList => {\n    const innermostTitle = getInnermostProperty(propsList, TAG_NAMES.TITLE);\n    const innermostTemplate = getInnermostProperty(\n        propsList,\n        HELMET_PROPS.TITLE_TEMPLATE\n    );\n\n    if (innermostTemplate && innermostTitle) {\n        // use function arg to avoid need to escape $ characters\n        return innermostTemplate.replace(\n            /%s/g,\n            () =>\n                Array.isArray(innermostTitle)\n                    ? innermostTitle.join(\"\")\n                    : innermostTitle\n        );\n    }\n\n    const innermostDefaultTitle = getInnermostProperty(\n        propsList,\n        HELMET_PROPS.DEFAULT_TITLE\n    );\n\n    return innermostTitle || innermostDefaultTitle || undefined;\n};\n\nconst getOnChangeClientState = propsList => {\n    return (\n        getInnermostProperty(propsList, HELMET_PROPS.ON_CHANGE_CLIENT_STATE) ||\n        (() => {})\n    );\n};\n\nconst getAttributesFromPropsList = (tagType, propsList) => {\n    return propsList\n        .filter(props => typeof props[tagType] !== \"undefined\")\n        .map(props => props[tagType])\n        .reduce((tagAttrs, current) => {\n            return {...tagAttrs, ...current};\n        }, {});\n};\n\nconst getBaseTagFromPropsList = (primaryAttributes, propsList) => {\n    return propsList\n        .filter(props => typeof props[TAG_NAMES.BASE] !== \"undefined\")\n        .map(props => props[TAG_NAMES.BASE])\n        .reverse()\n        .reduce((innermostBaseTag, tag) => {\n            if (!innermostBaseTag.length) {\n                const keys = Object.keys(tag);\n\n                for (let i = 0; i < keys.length; i++) {\n                    const attributeKey = keys[i];\n                    const lowerCaseAttributeKey = attributeKey.toLowerCase();\n\n                    if (\n                        primaryAttributes.indexOf(lowerCaseAttributeKey) !==\n                            -1 &&\n                        tag[lowerCaseAttributeKey]\n                    ) {\n                        return innermostBaseTag.concat(tag);\n                    }\n                }\n            }\n\n            return innermostBaseTag;\n        }, []);\n};\n\nconst getTagsFromPropsList = (tagName, primaryAttributes, propsList) => {\n    // Calculate list of tags, giving priority innermost component (end of the propslist)\n    const approvedSeenTags = {};\n\n    return propsList\n        .filter(props => {\n            if (Array.isArray(props[tagName])) {\n                return true;\n            }\n            if (typeof props[tagName] !== \"undefined\") {\n                warn(\n                    `Helmet: ${tagName} should be of type \"Array\". Instead found type \"${typeof props[\n                        tagName\n                    ]}\"`\n                );\n            }\n            return false;\n        })\n        .map(props => props[tagName])\n        .reverse()\n        .reduce((approvedTags, instanceTags) => {\n            const instanceSeenTags = {};\n\n            instanceTags\n                .filter(tag => {\n                    let primaryAttributeKey;\n                    const keys = Object.keys(tag);\n                    for (let i = 0; i < keys.length; i++) {\n                        const attributeKey = keys[i];\n                        const lowerCaseAttributeKey = attributeKey.toLowerCase();\n\n                        // Special rule with link tags, since rel and href are both primary tags, rel takes priority\n                        if (\n                            primaryAttributes.indexOf(lowerCaseAttributeKey) !==\n                                -1 &&\n                            !(\n                                primaryAttributeKey === TAG_PROPERTIES.REL &&\n                                tag[primaryAttributeKey].toLowerCase() ===\n                                    \"canonical\"\n                            ) &&\n                            !(\n                                lowerCaseAttributeKey === TAG_PROPERTIES.REL &&\n                                tag[lowerCaseAttributeKey].toLowerCase() ===\n                                    \"stylesheet\"\n                            )\n                        ) {\n                            primaryAttributeKey = lowerCaseAttributeKey;\n                        }\n                        // Special case for innerHTML which doesn't work lowercased\n                        if (\n                            primaryAttributes.indexOf(attributeKey) !== -1 &&\n                            (attributeKey === TAG_PROPERTIES.INNER_HTML ||\n                                attributeKey === TAG_PROPERTIES.CSS_TEXT ||\n                                attributeKey === TAG_PROPERTIES.ITEM_PROP)\n                        ) {\n                            primaryAttributeKey = attributeKey;\n                        }\n                    }\n\n                    if (!primaryAttributeKey || !tag[primaryAttributeKey]) {\n                        return false;\n                    }\n\n                    const value = tag[primaryAttributeKey].toLowerCase();\n\n                    if (!approvedSeenTags[primaryAttributeKey]) {\n                        approvedSeenTags[primaryAttributeKey] = {};\n                    }\n\n                    if (!instanceSeenTags[primaryAttributeKey]) {\n                        instanceSeenTags[primaryAttributeKey] = {};\n                    }\n\n                    if (!approvedSeenTags[primaryAttributeKey][value]) {\n                        instanceSeenTags[primaryAttributeKey][value] = true;\n                        return true;\n                    }\n\n                    return false;\n                })\n                .reverse()\n                .forEach(tag => approvedTags.push(tag));\n\n            // Update seen tags with tags from this instance\n            const keys = Object.keys(instanceSeenTags);\n            for (let i = 0; i < keys.length; i++) {\n                const attributeKey = keys[i];\n                const tagUnion = objectAssign(\n                    {},\n                    approvedSeenTags[attributeKey],\n                    instanceSeenTags[attributeKey]\n                );\n\n                approvedSeenTags[attributeKey] = tagUnion;\n            }\n\n            return approvedTags;\n        }, [])\n        .reverse();\n};\n\nconst getInnermostProperty = (propsList, property) => {\n    for (let i = propsList.length - 1; i >= 0; i--) {\n        const props = propsList[i];\n\n        if (props.hasOwnProperty(property)) {\n            return props[property];\n        }\n    }\n\n    return null;\n};\n\nconst reducePropsToState = propsList => ({\n    baseTag: getBaseTagFromPropsList(\n        [TAG_PROPERTIES.HREF, TAG_PROPERTIES.TARGET],\n        propsList\n    ),\n    bodyAttributes: getAttributesFromPropsList(ATTRIBUTE_NAMES.BODY, propsList),\n    defer: getInnermostProperty(propsList, HELMET_PROPS.DEFER),\n    encode: getInnermostProperty(\n        propsList,\n        HELMET_PROPS.ENCODE_SPECIAL_CHARACTERS\n    ),\n    htmlAttributes: getAttributesFromPropsList(ATTRIBUTE_NAMES.HTML, propsList),\n    linkTags: getTagsFromPropsList(\n        TAG_NAMES.LINK,\n        [TAG_PROPERTIES.REL, TAG_PROPERTIES.HREF],\n        propsList\n    ),\n    metaTags: getTagsFromPropsList(\n        TAG_NAMES.META,\n        [\n            TAG_PROPERTIES.NAME,\n            TAG_PROPERTIES.CHARSET,\n            TAG_PROPERTIES.HTTPEQUIV,\n            TAG_PROPERTIES.PROPERTY,\n            TAG_PROPERTIES.ITEM_PROP\n        ],\n        propsList\n    ),\n    noscriptTags: getTagsFromPropsList(\n        TAG_NAMES.NOSCRIPT,\n        [TAG_PROPERTIES.INNER_HTML],\n        propsList\n    ),\n    onChangeClientState: getOnChangeClientState(propsList),\n    scriptTags: getTagsFromPropsList(\n        TAG_NAMES.SCRIPT,\n        [TAG_PROPERTIES.SRC, TAG_PROPERTIES.INNER_HTML],\n        propsList\n    ),\n    styleTags: getTagsFromPropsList(\n        TAG_NAMES.STYLE,\n        [TAG_PROPERTIES.CSS_TEXT],\n        propsList\n    ),\n    title: getTitleFromPropsList(propsList),\n    titleAttributes: getAttributesFromPropsList(\n        ATTRIBUTE_NAMES.TITLE,\n        propsList\n    )\n});\n\nconst rafPolyfill = (() => {\n    let clock = Date.now();\n\n    return (callback: Function) => {\n        const currentTime = Date.now();\n\n        if (currentTime - clock > 16) {\n            clock = currentTime;\n            callback(currentTime);\n        } else {\n            setTimeout(() => {\n                rafPolyfill(callback);\n            }, 0);\n        }\n    };\n})();\n\nconst cafPolyfill = (id: string | number) => clearTimeout(id);\n\nconst requestAnimationFrame =\n    typeof window !== \"undefined\"\n        ? (window.requestAnimationFrame &&\n              window.requestAnimationFrame.bind(window)) ||\n          window.webkitRequestAnimationFrame ||\n          window.mozRequestAnimationFrame ||\n          rafPolyfill\n        : global.requestAnimationFrame || rafPolyfill;\n\nconst cancelAnimationFrame =\n    typeof window !== \"undefined\"\n        ? window.cancelAnimationFrame ||\n          window.webkitCancelAnimationFrame ||\n          window.mozCancelAnimationFrame ||\n          cafPolyfill\n        : global.cancelAnimationFrame || cafPolyfill;\n\nconst warn = msg => {\n    return console && typeof console.warn === \"function\" && console.warn(msg);\n};\n\nlet _helmetCallback = null;\n\nconst handleClientStateChange = newState => {\n    if (_helmetCallback) {\n        cancelAnimationFrame(_helmetCallback);\n    }\n\n    if (newState.defer) {\n        _helmetCallback = requestAnimationFrame(() => {\n            commitTagChanges(newState, () => {\n                _helmetCallback = null;\n            });\n        });\n    } else {\n        commitTagChanges(newState);\n        _helmetCallback = null;\n    }\n};\n\nconst commitTagChanges = (newState, cb) => {\n    const {\n        baseTag,\n        bodyAttributes,\n        htmlAttributes,\n        linkTags,\n        metaTags,\n        noscriptTags,\n        onChangeClientState,\n        scriptTags,\n        styleTags,\n        title,\n        titleAttributes\n    } = newState;\n    updateAttributes(TAG_NAMES.BODY, bodyAttributes);\n    updateAttributes(TAG_NAMES.HTML, htmlAttributes);\n\n    updateTitle(title, titleAttributes);\n\n    const tagUpdates = {\n        baseTag: updateTags(TAG_NAMES.BASE, baseTag),\n        linkTags: updateTags(TAG_NAMES.LINK, linkTags),\n        metaTags: updateTags(TAG_NAMES.META, metaTags),\n        noscriptTags: updateTags(TAG_NAMES.NOSCRIPT, noscriptTags),\n        scriptTags: updateTags(TAG_NAMES.SCRIPT, scriptTags),\n        styleTags: updateTags(TAG_NAMES.STYLE, styleTags)\n    };\n\n    const addedTags = {};\n    const removedTags = {};\n\n    Object.keys(tagUpdates).forEach(tagType => {\n        const {newTags, oldTags} = tagUpdates[tagType];\n\n        if (newTags.length) {\n            addedTags[tagType] = newTags;\n        }\n        if (oldTags.length) {\n            removedTags[tagType] = tagUpdates[tagType].oldTags;\n        }\n    });\n\n    cb && cb();\n\n    onChangeClientState(newState, addedTags, removedTags);\n};\n\nconst flattenArray = possibleArray => {\n    return Array.isArray(possibleArray)\n        ? possibleArray.join(\"\")\n        : possibleArray;\n};\n\nconst updateTitle = (title, attributes) => {\n    if (typeof title !== \"undefined\" && document.title !== title) {\n        document.title = flattenArray(title);\n    }\n\n    updateAttributes(TAG_NAMES.TITLE, attributes);\n};\n\nconst updateAttributes = (tagName, attributes) => {\n    const elementTag = document.getElementsByTagName(tagName)[0];\n\n    if (!elementTag) {\n        return;\n    }\n\n    const helmetAttributeString = elementTag.getAttribute(HELMET_ATTRIBUTE);\n    const helmetAttributes = helmetAttributeString\n        ? helmetAttributeString.split(\",\")\n        : [];\n    const attributesToRemove = [].concat(helmetAttributes);\n    const attributeKeys = Object.keys(attributes);\n\n    for (let i = 0; i < attributeKeys.length; i++) {\n        const attribute = attributeKeys[i];\n        const value = attributes[attribute] || \"\";\n\n        if (elementTag.getAttribute(attribute) !== value) {\n            elementTag.setAttribute(attribute, value);\n        }\n\n        if (helmetAttributes.indexOf(attribute) === -1) {\n            helmetAttributes.push(attribute);\n        }\n\n        const indexToSave = attributesToRemove.indexOf(attribute);\n        if (indexToSave !== -1) {\n            attributesToRemove.splice(indexToSave, 1);\n        }\n    }\n\n    for (let i = attributesToRemove.length - 1; i >= 0; i--) {\n        elementTag.removeAttribute(attributesToRemove[i]);\n    }\n\n    if (helmetAttributes.length === attributesToRemove.length) {\n        elementTag.removeAttribute(HELMET_ATTRIBUTE);\n    } else if (\n        elementTag.getAttribute(HELMET_ATTRIBUTE) !== attributeKeys.join(\",\")\n    ) {\n        elementTag.setAttribute(HELMET_ATTRIBUTE, attributeKeys.join(\",\"));\n    }\n};\n\nconst updateTags = (type, tags) => {\n    const headElement = document.head || document.querySelector(TAG_NAMES.HEAD);\n    const tagNodes = headElement.querySelectorAll(\n        `${type}[${HELMET_ATTRIBUTE}]`\n    );\n    const oldTags = Array.prototype.slice.call(tagNodes);\n    const newTags = [];\n    let indexToDelete;\n\n    if (tags && tags.length) {\n        tags.forEach(tag => {\n            const newElement = document.createElement(type);\n\n            for (const attribute in tag) {\n                if (tag.hasOwnProperty(attribute)) {\n                    if (attribute === TAG_PROPERTIES.INNER_HTML) {\n                        newElement.innerHTML = tag.innerHTML;\n                    } else if (attribute === TAG_PROPERTIES.CSS_TEXT) {\n                        if (newElement.styleSheet) {\n                            newElement.styleSheet.cssText = tag.cssText;\n                        } else {\n                            newElement.appendChild(\n                                document.createTextNode(tag.cssText)\n                            );\n                        }\n                    } else {\n                        const value =\n                            typeof tag[attribute] === \"undefined\"\n                                ? \"\"\n                                : tag[attribute];\n                        newElement.setAttribute(attribute, value);\n                    }\n                }\n            }\n\n            newElement.setAttribute(HELMET_ATTRIBUTE, \"true\");\n\n            // Remove a duplicate tag from domTagstoRemove, so it isn't cleared.\n            if (\n                oldTags.some((existingTag, index) => {\n                    indexToDelete = index;\n                    return newElement.isEqualNode(existingTag);\n                })\n            ) {\n                oldTags.splice(indexToDelete, 1);\n            } else {\n                newTags.push(newElement);\n            }\n        });\n    }\n\n    oldTags.forEach(tag => tag.parentNode.removeChild(tag));\n    newTags.forEach(tag => headElement.appendChild(tag));\n\n    return {\n        oldTags,\n        newTags\n    };\n};\n\nconst generateElementAttributesAsString = attributes =>\n    Object.keys(attributes).reduce((str, key) => {\n        const attr =\n            typeof attributes[key] !== \"undefined\"\n                ? `${key}=\"${attributes[key]}\"`\n                : `${key}`;\n        return str ? `${str} ${attr}` : attr;\n    }, \"\");\n\nconst generateTitleAsString = (type, title, attributes, encode) => {\n    const attributeString = generateElementAttributesAsString(attributes);\n    const flattenedTitle = flattenArray(title);\n    return attributeString\n        ? `<${type} ${HELMET_ATTRIBUTE}=\"true\" ${attributeString}>${encodeSpecialCharacters(\n              flattenedTitle,\n              encode\n          )}</${type}>`\n        : `<${type} ${HELMET_ATTRIBUTE}=\"true\">${encodeSpecialCharacters(\n              flattenedTitle,\n              encode\n          )}</${type}>`;\n};\n\nconst generateTagsAsString = (type, tags, encode) =>\n    tags.reduce((str, tag) => {\n        const attributeHtml = Object.keys(tag)\n            .filter(\n                attribute =>\n                    !(\n                        attribute === TAG_PROPERTIES.INNER_HTML ||\n                        attribute === TAG_PROPERTIES.CSS_TEXT\n                    )\n            )\n            .reduce((string, attribute) => {\n                const attr =\n                    typeof tag[attribute] === \"undefined\"\n                        ? attribute\n                        : `${attribute}=\"${encodeSpecialCharacters(\n                              tag[attribute],\n                              encode\n                          )}\"`;\n                return string ? `${string} ${attr}` : attr;\n            }, \"\");\n\n        const tagContent = tag.innerHTML || tag.cssText || \"\";\n\n        const isSelfClosing = SELF_CLOSING_TAGS.indexOf(type) === -1;\n\n        return `${str}<${type} ${HELMET_ATTRIBUTE}=\"true\" ${attributeHtml}${\n            isSelfClosing ? `/>` : `>${tagContent}</${type}>`\n        }`;\n    }, \"\");\n\nconst convertElementAttributestoReactProps = (attributes, initProps = {}) => {\n    return Object.keys(attributes).reduce((obj, key) => {\n        obj[REACT_TAG_MAP[key] || key] = attributes[key];\n        return obj;\n    }, initProps);\n};\n\nconst convertReactPropstoHtmlAttributes = (props, initAttributes = {}) => {\n    return Object.keys(props).reduce((obj, key) => {\n        obj[HTML_TAG_MAP[key] || key] = props[key];\n        return obj;\n    }, initAttributes);\n};\n\nconst generateTitleAsReactComponent = (type, title, attributes) => {\n    // assigning into an array to define toString function on it\n    const initProps = {\n        key: title,\n        [HELMET_ATTRIBUTE]: true\n    };\n    const props = convertElementAttributestoReactProps(attributes, initProps);\n\n    return [React.createElement(TAG_NAMES.TITLE, props, title)];\n};\n\nconst generateTagsAsReactComponent = (type, tags) =>\n    tags.map((tag, i) => {\n        const mappedTag = {\n            key: i,\n            [HELMET_ATTRIBUTE]: true\n        };\n\n        Object.keys(tag).forEach(attribute => {\n            const mappedAttribute = REACT_TAG_MAP[attribute] || attribute;\n\n            if (\n                mappedAttribute === TAG_PROPERTIES.INNER_HTML ||\n                mappedAttribute === TAG_PROPERTIES.CSS_TEXT\n            ) {\n                const content = tag.innerHTML || tag.cssText;\n                mappedTag.dangerouslySetInnerHTML = {__html: content};\n            } else {\n                mappedTag[mappedAttribute] = tag[attribute];\n            }\n        });\n\n        return React.createElement(type, mappedTag);\n    });\n\nconst getMethodsForTag = (type, tags, encode) => {\n    switch (type) {\n        case TAG_NAMES.TITLE:\n            return {\n                toComponent: () =>\n                    generateTitleAsReactComponent(\n                        type,\n                        tags.title,\n                        tags.titleAttributes,\n                        encode\n                    ),\n                toString: () =>\n                    generateTitleAsString(\n                        type,\n                        tags.title,\n                        tags.titleAttributes,\n                        encode\n                    )\n            };\n        case ATTRIBUTE_NAMES.BODY:\n        case ATTRIBUTE_NAMES.HTML:\n            return {\n                toComponent: () => convertElementAttributestoReactProps(tags),\n                toString: () => generateElementAttributesAsString(tags)\n            };\n        default:\n            return {\n                toComponent: () => generateTagsAsReactComponent(type, tags),\n                toString: () => generateTagsAsString(type, tags, encode)\n            };\n    }\n};\n\nconst mapStateOnServer = ({\n    baseTag,\n    bodyAttributes,\n    encode,\n    htmlAttributes,\n    linkTags,\n    metaTags,\n    noscriptTags,\n    scriptTags,\n    styleTags,\n    title = \"\",\n    titleAttributes\n}) => ({\n    base: getMethodsForTag(TAG_NAMES.BASE, baseTag, encode),\n    bodyAttributes: getMethodsForTag(\n        ATTRIBUTE_NAMES.BODY,\n        bodyAttributes,\n        encode\n    ),\n    htmlAttributes: getMethodsForTag(\n        ATTRIBUTE_NAMES.HTML,\n        htmlAttributes,\n        encode\n    ),\n    link: getMethodsForTag(TAG_NAMES.LINK, linkTags, encode),\n    meta: getMethodsForTag(TAG_NAMES.META, metaTags, encode),\n    noscript: getMethodsForTag(TAG_NAMES.NOSCRIPT, noscriptTags, encode),\n    script: getMethodsForTag(TAG_NAMES.SCRIPT, scriptTags, encode),\n    style: getMethodsForTag(TAG_NAMES.STYLE, styleTags, encode),\n    title: getMethodsForTag(TAG_NAMES.TITLE, {title, titleAttributes}, encode)\n});\n\nexport {convertReactPropstoHtmlAttributes};\nexport {handleClientStateChange};\nexport {mapStateOnServer};\nexport {reducePropsToState};\nexport {requestAnimationFrame};\nexport {warn};\n"
  },
  {
    "path": "test/HelmetDeclarativeTest.js",
    "content": "/* eslint max-nested-callbacks: [1, 7] */\n/* eslint-disable react/jsx-sort-props */\n/* eslint-disable jsx-a11y/html-has-lang */\n\nimport React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport ReactServer from \"react-dom/server\";\nimport {Helmet} from \"../src/Helmet\";\nimport {HTML_TAG_MAP} from \"../src/HelmetConstants\";\nimport {requestAnimationFrame} from \"../src/HelmetUtils.js\";\n\nconst HELMET_ATTRIBUTE = \"data-react-helmet\";\n\ndescribe(\"Helmet - Declarative API\", () => {\n    let headElement;\n\n    const container = document.createElement(\"div\");\n\n    beforeEach(() => {\n        headElement =\n            headElement || document.head || document.querySelector(\"head\");\n\n        // resets DOM after each run\n        headElement.innerHTML = \"\";\n    });\n\n    afterEach(() => {\n        ReactDOM.unmountComponentAtNode(container);\n    });\n\n    describe(\"api\", () => {\n        describe(\"title\", () => {\n            it(\"updates page title\", done => {\n                ReactDOM.render(\n                    <Helmet defaultTitle={\"Fallback\"}>\n                        <title>Test Title</title>\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\"Test Title\");\n\n                    done();\n                });\n            });\n\n            it(\"updates page title and allows children containing expressions\", done => {\n                const someValue = \"Some Great Title\";\n\n                ReactDOM.render(\n                    <Helmet>\n                        <title>Title: {someValue}</title>\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\"Title: Some Great Title\");\n\n                    done();\n                });\n            });\n\n            it(\"updates page title with multiple children\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet>\n                            <title>Test Title</title>\n                        </Helmet>\n                        <Helmet>\n                            <title>Child One Title</title>\n                        </Helmet>\n                        <Helmet>\n                            <title>Child Two Title</title>\n                        </Helmet>\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\"Child Two Title\");\n\n                    done();\n                });\n            });\n\n            it(\"sets title based on deepest nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet>\n                            <title>Main Title</title>\n                        </Helmet>\n                        <Helmet>\n                            <title>Nested Title</title>\n                        </Helmet>\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\"Nested Title\");\n\n                    done();\n                });\n            });\n\n            it(\"sets title using deepest nested component with a defined title\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet>\n                            <title>Main Title</title>\n                        </Helmet>\n                        <Helmet />\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\"Main Title\");\n\n                    done();\n                });\n            });\n\n            it(\"uses defaultTitle if no title is defined\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        defaultTitle={\"Fallback\"}\n                        titleTemplate={\n                            \"This is a %s of the titleTemplate feature\"\n                        }\n                    >\n                        <title />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\"Fallback\");\n\n                    done();\n                });\n            });\n\n            it(\"uses a titleTemplate if defined\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        defaultTitle={\"Fallback\"}\n                        titleTemplate={\n                            \"This is a %s of the titleTemplate feature\"\n                        }\n                    >\n                        <title>Test</title>\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\n                        \"This is a Test of the titleTemplate feature\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"replaces multiple title strings in titleTemplate\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        titleTemplate={\n                            \"This is a %s of the titleTemplate feature. Another %s.\"\n                        }\n                    >\n                        <title>Test</title>\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\n                        \"This is a Test of the titleTemplate feature. Another Test.\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"uses a titleTemplate based on deepest nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet\n                            titleTemplate={\n                                \"This is a %s of the titleTemplate feature\"\n                            }\n                        >\n                            <title>Test</title>\n                        </Helmet>\n                        <Helmet\n                            titleTemplate={\n                                \"A %s using nested titleTemplate attributes\"\n                            }\n                        >\n                            <title>Second Test</title>\n                        </Helmet>\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\n                        \"A Second Test using nested titleTemplate attributes\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"merges deepest component title with nearest upstream titleTemplate\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet\n                            titleTemplate={\n                                \"This is a %s of the titleTemplate feature\"\n                            }\n                        >\n                            <title>Test</title>\n                        </Helmet>\n                        <Helmet>\n                            <title>Second Test</title>\n                        </Helmet>\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\n                        \"This is a Second Test of the titleTemplate feature\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"renders dollar characters in a title correctly when titleTemplate present\", done => {\n                const dollarTitle = \"te$t te$$t te$$$t te$$$$t\";\n\n                ReactDOM.render(\n                    <Helmet titleTemplate={\"This is a %s\"}>\n                        <title>{dollarTitle}</title>\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\n                        \"This is a te$t te$$t te$$$t te$$$$t\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"properly handles title with children and titleTemplate\", done => {\n                ReactDOM.render(\n                    <Helmet titleTemplate={\"This is an %s\"}>\n                        <title>\n                            {\"extra\"} + {\"test\"}\n                        </title>\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\"This is an extra + test\");\n\n                    done();\n                });\n            });\n\n            it(\"does not encode all characters with HTML character entity equivalents\", done => {\n                const chineseTitle = \"膣膗 鍆錌雔\";\n\n                ReactDOM.render(\n                    <Helmet>\n                        <title>{chineseTitle}</title>\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(chineseTitle);\n\n                    done();\n                });\n            });\n\n            it(\"page title with prop itemProp\", done => {\n                ReactDOM.render(\n                    <Helmet defaultTitle={\"Fallback\"}>\n                        <title itemProp=\"name\">Test Title with itemProp</title>\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const titleTag = document.getElementsByTagName(\"title\")[0];\n                    expect(document.title).to.equal(\"Test Title with itemProp\");\n                    expect(titleTag.getAttribute(\"itemprop\")).to.equal(\"name\");\n\n                    done();\n                });\n            });\n\n            it(\"retains existing title tag when no title tag is defined\", done => {\n                headElement.innerHTML = `<title>Existing Title</title>`;\n\n                ReactDOM.render(\n                    <Helmet>\n                        <meta name=\"keywords\" content=\"stuff\" />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\"Existing Title\");\n\n                    done();\n                });\n            });\n\n            it.skip(\"clears title tag if empty title is defined\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <title>Existing Title</title>\n                        <meta name=\"keywords\" content=\"stuff\" />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\"Existing Title\");\n\n                    ReactDOM.render(\n                        <Helmet>\n                            <title />\n                            <meta name=\"keywords\" content=\"stuff\" />\n                        </Helmet>,\n                        container\n                    );\n\n                    requestAnimationFrame(() => {\n                        expect(document.title).to.equal(\"\");\n                        done();\n                    });\n                });\n            });\n        });\n\n        describe(\"title attributes\", () => {\n            beforeEach(() => {\n                headElement.innerHTML = `<title>Test Title</title>`;\n            });\n\n            it(\"updates title attributes\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <title itemProp=\"name\" />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const titleTag = document.getElementsByTagName(\"title\")[0];\n\n                    expect(titleTag.getAttribute(\"itemprop\")).to.equal(\"name\");\n                    expect(titleTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                        \"itemprop\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"sets attributes based on the deepest nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet>\n                            <title lang=\"en\" hidden />\n                        </Helmet>\n                        <Helmet>\n                            <title lang=\"ja\" />\n                        </Helmet>\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const titleTag = document.getElementsByTagName(\"title\")[0];\n\n                    expect(titleTag.getAttribute(\"lang\")).to.equal(\"ja\");\n                    expect(titleTag.getAttribute(\"hidden\")).to.equal(\"true\");\n                    expect(titleTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                        \"lang,hidden\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"handles valueless attributes\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <title hidden />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const titleTag = document.getElementsByTagName(\"title\")[0];\n\n                    expect(titleTag.getAttribute(\"hidden\")).to.equal(\"true\");\n                    expect(titleTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                        \"hidden\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"clears title attributes that are handled within helmet\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <title lang=\"en\" hidden />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(<Helmet />, container);\n\n                    requestAnimationFrame(() => {\n                        const titleTag = document.getElementsByTagName(\n                            \"title\"\n                        )[0];\n\n                        expect(titleTag.getAttribute(\"lang\")).to.be.null;\n                        expect(titleTag.getAttribute(\"hidden\")).to.be.null;\n                        expect(\n                            titleTag.getAttribute(HELMET_ATTRIBUTE)\n                        ).to.equal(null);\n\n                        done();\n                    });\n                });\n            });\n        });\n\n        describe(\"html attributes\", () => {\n            it(\"updates html attributes\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <html className=\"myClassName\" lang=\"en\" />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const htmlTag = document.getElementsByTagName(\"html\")[0];\n\n                    expect(htmlTag.getAttribute(\"class\")).to.equal(\n                        \"myClassName\"\n                    );\n                    expect(htmlTag.getAttribute(\"lang\")).to.equal(\"en\");\n                    expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                        \"class,lang\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"sets attributes based on the deepest nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet>\n                            <html lang=\"en\" />\n                        </Helmet>\n                        <Helmet>\n                            <html lang=\"ja\" />\n                        </Helmet>\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const htmlTag = document.getElementsByTagName(\"html\")[0];\n\n                    expect(htmlTag.getAttribute(\"lang\")).to.equal(\"ja\");\n                    expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                        \"lang\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"handles valueless attributes\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <html amp />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const htmlTag = document.getElementsByTagName(\"html\")[0];\n\n                    expect(htmlTag.getAttribute(\"amp\")).to.equal(\"true\");\n                    expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                        \"amp\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"clears html attributes that are handled within helmet\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <html lang=\"en\" amp />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(<Helmet />, container);\n\n                    requestAnimationFrame(() => {\n                        const htmlTag = document.getElementsByTagName(\n                            \"html\"\n                        )[0];\n\n                        expect(htmlTag.getAttribute(\"lang\")).to.be.null;\n                        expect(htmlTag.getAttribute(\"amp\")).to.be.null;\n                        expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                            null\n                        );\n\n                        done();\n                    });\n                });\n            });\n\n            it(\"updates with multiple additions and removals - overwrite and new\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <html lang=\"en\" amp />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(\n                        <Helmet>\n                            <html lang=\"ja\" id=\"html-tag\" title=\"html tag\" />\n                        </Helmet>,\n                        container\n                    );\n\n                    requestAnimationFrame(() => {\n                        const htmlTag = document.getElementsByTagName(\n                            \"html\"\n                        )[0];\n\n                        expect(htmlTag.getAttribute(\"amp\")).to.equal(null);\n                        expect(htmlTag.getAttribute(\"lang\")).to.equal(\"ja\");\n                        expect(htmlTag.getAttribute(\"id\")).to.equal(\"html-tag\");\n                        expect(htmlTag.getAttribute(\"title\")).to.equal(\n                            \"html tag\"\n                        );\n                        expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                            \"lang,id,title\"\n                        );\n\n                        done();\n                    });\n                });\n            });\n\n            it(\"updates with multiple additions and removals - all new\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <html lang=\"en\" amp />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(\n                        <Helmet>\n                            <html id=\"html-tag\" title=\"html tag\" />\n                        </Helmet>,\n                        container\n                    );\n\n                    requestAnimationFrame(() => {\n                        const htmlTag = document.getElementsByTagName(\n                            \"html\"\n                        )[0];\n\n                        expect(htmlTag.getAttribute(\"amp\")).to.equal(null);\n                        expect(htmlTag.getAttribute(\"lang\")).to.equal(null);\n                        expect(htmlTag.getAttribute(\"id\")).to.equal(\"html-tag\");\n                        expect(htmlTag.getAttribute(\"title\")).to.equal(\n                            \"html tag\"\n                        );\n                        expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                            \"id,title\"\n                        );\n\n                        done();\n                    });\n                });\n            });\n\n            context(\"initialized outside of helmet\", () => {\n                before(() => {\n                    const htmlTag = document.getElementsByTagName(\"html\")[0];\n                    htmlTag.setAttribute(\"test\", \"test\");\n                });\n\n                it(\"are not cleared\", done => {\n                    ReactDOM.render(<Helmet />, container);\n\n                    requestAnimationFrame(() => {\n                        const htmlTag = document.getElementsByTagName(\n                            \"html\"\n                        )[0];\n\n                        expect(htmlTag.getAttribute(\"test\")).to.equal(\"test\");\n                        expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                            null\n                        );\n\n                        done();\n                    });\n                });\n\n                it(\"overwritten if specified in helmet\", done => {\n                    ReactDOM.render(\n                        <Helmet>\n                            <html test=\"helmet-attr\" />\n                        </Helmet>,\n                        container\n                    );\n\n                    requestAnimationFrame(() => {\n                        const htmlTag = document.getElementsByTagName(\n                            \"html\"\n                        )[0];\n\n                        expect(htmlTag.getAttribute(\"test\")).to.equal(\n                            \"helmet-attr\"\n                        );\n                        expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                            \"test\"\n                        );\n\n                        done();\n                    });\n                });\n\n                it(\"cleared once it is managed in helmet\", done => {\n                    ReactDOM.render(\n                        <Helmet>\n                            <html test=\"helmet-attr\" />\n                        </Helmet>,\n                        container\n                    );\n\n                    requestAnimationFrame(() => {\n                        ReactDOM.render(<Helmet />, container);\n\n                        requestAnimationFrame(() => {\n                            const htmlTag = document.getElementsByTagName(\n                                \"html\"\n                            )[0];\n\n                            expect(htmlTag.getAttribute(\"test\")).to.equal(null);\n                            expect(\n                                htmlTag.getAttribute(HELMET_ATTRIBUTE)\n                            ).to.equal(null);\n\n                            done();\n                        });\n                    });\n                });\n            });\n        });\n\n        describe(\"body attributes\", () => {\n            context(\"valid attributes\", () => {\n                const attributeList = {\n                    accessKey: \"c\",\n                    className: \"test\",\n                    contentEditable: \"true\",\n                    contextMenu: \"mymenu\",\n                    \"data-animal-type\": \"lion\",\n                    dir: \"rtl\",\n                    draggable: \"true\",\n                    dropzone: \"copy\",\n                    hidden: \"true\",\n                    id: \"test\",\n                    lang: \"fr\",\n                    spellcheck: \"true\",\n                    style: \"color:green\",\n                    tabIndex: \"-1\",\n                    title: \"test\",\n                    translate: \"no\"\n                };\n\n                Object.keys(attributeList).forEach(attribute => {\n                    it(attribute, done => {\n                        const attrValue = attributeList[attribute];\n\n                        const attr = {\n                            [attribute]: attrValue\n                        };\n\n                        ReactDOM.render(\n                            <Helmet>\n                                <body {...attr} />\n                            </Helmet>,\n                            container\n                        );\n\n                        requestAnimationFrame(() => {\n                            const bodyTag = document.body;\n\n                            const reactCompatAttr =\n                                HTML_TAG_MAP[attribute] || attribute;\n                            expect(\n                                bodyTag.getAttribute(reactCompatAttr)\n                            ).to.equal(attrValue);\n                            expect(\n                                bodyTag.getAttribute(HELMET_ATTRIBUTE)\n                            ).to.equal(reactCompatAttr);\n\n                            done();\n                        });\n                    });\n                });\n            });\n\n            it(\"updates multiple body attributes\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <body className=\"myClassName\" tabIndex={-1} />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const bodyTag = document.body;\n\n                    expect(bodyTag.getAttribute(\"class\")).to.equal(\n                        \"myClassName\"\n                    );\n                    expect(bodyTag.getAttribute(\"tabindex\")).to.equal(\"-1\");\n                    expect(bodyTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                        \"class,tabindex\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"sets attributes based on the deepest nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet>\n                            <body lang=\"en\" />\n                        </Helmet>\n                        <Helmet>\n                            <body lang=\"ja\" />\n                        </Helmet>\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const bodyTag = document.body;\n\n                    expect(bodyTag.getAttribute(\"lang\")).to.equal(\"ja\");\n                    expect(bodyTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                        \"lang\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"handles valueless attributes\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <body hidden />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const bodyTag = document.body;\n\n                    expect(bodyTag.getAttribute(\"hidden\")).to.equal(\"true\");\n                    expect(bodyTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                        \"hidden\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"clears body attributes that are handled within helmet\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <body lang=\"en\" hidden />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(<Helmet />, container);\n\n                    requestAnimationFrame(() => {\n                        const bodyTag = document.body;\n\n                        expect(bodyTag.getAttribute(\"lang\")).to.be.null;\n                        expect(bodyTag.getAttribute(\"hidden\")).to.be.null;\n                        expect(bodyTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                            null\n                        );\n\n                        done();\n                    });\n                });\n            });\n\n            it(\"updates with multiple additions and removals - overwrite and new\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <body lang=\"en\" hidden />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(\n                        <Helmet>\n                            <body lang=\"ja\" id=\"body-tag\" title=\"body tag\" />\n                        </Helmet>,\n                        container\n                    );\n\n                    requestAnimationFrame(() => {\n                        const bodyTag = document.body;\n\n                        expect(bodyTag.getAttribute(\"hidden\")).to.equal(null);\n                        expect(bodyTag.getAttribute(\"lang\")).to.equal(\"ja\");\n                        expect(bodyTag.getAttribute(\"id\")).to.equal(\"body-tag\");\n                        expect(bodyTag.getAttribute(\"title\")).to.equal(\n                            \"body tag\"\n                        );\n                        expect(bodyTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                            \"lang,id,title\"\n                        );\n\n                        done();\n                    });\n                });\n            });\n\n            it(\"updates with multiple additions and removals - all new\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <body lang=\"en\" hidden />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(\n                        <Helmet>\n                            <body id=\"body-tag\" title=\"body tag\" />\n                        </Helmet>,\n                        container\n                    );\n\n                    requestAnimationFrame(() => {\n                        const bodyTag = document.body;\n\n                        expect(bodyTag.getAttribute(\"hidden\")).to.equal(null);\n                        expect(bodyTag.getAttribute(\"lang\")).to.equal(null);\n                        expect(bodyTag.getAttribute(\"id\")).to.equal(\"body-tag\");\n                        expect(bodyTag.getAttribute(\"title\")).to.equal(\n                            \"body tag\"\n                        );\n                        expect(bodyTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                            \"id,title\"\n                        );\n\n                        done();\n                    });\n                });\n            });\n\n            context(\"initialized outside of helmet\", () => {\n                before(() => {\n                    const bodyTag = document.body;\n                    bodyTag.setAttribute(\"test\", \"test\");\n                });\n\n                it(\"attributes are not cleared\", done => {\n                    ReactDOM.render(<Helmet />, container);\n\n                    requestAnimationFrame(() => {\n                        const bodyTag = document.body;\n\n                        expect(bodyTag.getAttribute(\"test\")).to.equal(\"test\");\n                        expect(bodyTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                            null\n                        );\n\n                        done();\n                    });\n                });\n\n                it(\"attributes are overwritten if specified in helmet\", done => {\n                    ReactDOM.render(\n                        <Helmet>\n                            <body test=\"helmet-attr\" />\n                        </Helmet>,\n                        container\n                    );\n\n                    requestAnimationFrame(() => {\n                        const bodyTag = document.body;\n\n                        expect(bodyTag.getAttribute(\"test\")).to.equal(\n                            \"helmet-attr\"\n                        );\n                        expect(bodyTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                            \"test\"\n                        );\n\n                        done();\n                    });\n                });\n\n                it(\"attributes are cleared once managed in helmet\", done => {\n                    ReactDOM.render(\n                        <Helmet>\n                            <body test=\"helmet-attr\" />\n                        </Helmet>,\n                        container\n                    );\n\n                    requestAnimationFrame(() => {\n                        ReactDOM.render(<Helmet />, container);\n\n                        requestAnimationFrame(() => {\n                            const bodyTag = document.body;\n\n                            expect(bodyTag.getAttribute(\"test\")).to.equal(null);\n                            expect(\n                                bodyTag.getAttribute(HELMET_ATTRIBUTE)\n                            ).to.equal(null);\n\n                            done();\n                        });\n                    });\n                });\n            });\n        });\n\n        describe(\"onChangeClientState\", () => {\n            it(\"when handling client state change, calls the function with new state, addedTags and removedTags \", done => {\n                const spy = sinon.spy();\n                ReactDOM.render(\n                    <div>\n                        <Helmet onChangeClientState={spy}>\n                            <base href=\"http://mysite.com/\" />\n                            <link\n                                href=\"http://localhost/helmet\"\n                                rel=\"canonical\"\n                            />\n                            <meta charSet=\"utf-8\" />\n                            <script\n                                src=\"http://localhost/test.js\"\n                                type=\"text/javascript\"\n                            />\n                            <title>Main Title</title>\n                        </Helmet>\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(spy.called).to.equal(true);\n                    const newState = spy.getCall(0).args[0];\n                    const addedTags = spy.getCall(0).args[1];\n                    const removedTags = spy.getCall(0).args[2];\n\n                    expect(newState).to.contain({title: \"Main Title\"});\n                    expect(newState.baseTag).to.contain({\n                        href: \"http://mysite.com/\"\n                    });\n                    expect(newState.metaTags).to.contain({charset: \"utf-8\"});\n                    expect(newState.linkTags).to.contain({\n                        href: \"http://localhost/helmet\",\n                        rel: \"canonical\"\n                    });\n                    expect(newState.scriptTags).to.contain({\n                        src: \"http://localhost/test.js\",\n                        type: \"text/javascript\"\n                    });\n\n                    expect(addedTags).to.have.property(\"baseTag\");\n                    expect(addedTags.baseTag).to.have.deep.property(\"[0]\");\n                    expect(addedTags.baseTag[0].outerHTML).to.equal(\n                        `<base href=\"http://mysite.com/\" data-react-helmet=\"true\">`\n                    );\n\n                    expect(addedTags).to.have.property(\"metaTags\");\n                    expect(addedTags.metaTags).to.have.deep.property(\"[0]\");\n                    expect(addedTags.metaTags[0].outerHTML).to.equal(\n                        `<meta charset=\"utf-8\" data-react-helmet=\"true\">`\n                    );\n\n                    expect(addedTags).to.have.property(\"linkTags\");\n                    expect(addedTags.linkTags).to.have.deep.property(\"[0]\");\n                    expect(addedTags.linkTags[0].outerHTML).to.equal(\n                        `<link href=\"http://localhost/helmet\" rel=\"canonical\" data-react-helmet=\"true\">`\n                    );\n\n                    expect(addedTags).to.have.property(\"scriptTags\");\n                    expect(addedTags.scriptTags).to.have.deep.property(\"[0]\");\n                    expect(addedTags.scriptTags[0].outerHTML).to.equal(\n                        `<script src=\"http://localhost/test.js\" type=\"text/javascript\" data-react-helmet=\"true\"></script>`\n                    );\n\n                    expect(removedTags).to.be.empty;\n\n                    done();\n                });\n            });\n\n            it(\"calls the deepest defined callback with the deepest state\", done => {\n                const spy = sinon.spy();\n                ReactDOM.render(\n                    <div>\n                        <Helmet onChangeClientState={spy}>\n                            <title>Main Title</title>\n                        </Helmet>\n                        <Helmet>\n                            <title>Deeper Title</title>\n                        </Helmet>\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(spy.callCount).to.equal(1);\n                    expect(spy.getCall(0).args[0]).to.contain({\n                        title: \"Deeper Title\"\n                    });\n\n                    done();\n                });\n            });\n        });\n\n        describe(\"base tag\", () => {\n            it(\"updates base tag\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <base href=\"http://mysite.com/\" />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const existingTags = headElement.querySelectorAll(\n                        `base[${HELMET_ATTRIBUTE}]`\n                    );\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    const filteredTags = [].slice\n                        .call(existingTags)\n                        .filter(tag => {\n                            return (\n                                tag.getAttribute(\"href\") ===\n                                \"http://mysite.com/\"\n                            );\n                        });\n\n                    expect(filteredTags.length).to.equal(1);\n\n                    done();\n                });\n            });\n\n            it(\"clears the base tag if one is not specified\", done => {\n                ReactDOM.render(\n                    <Helmet base={{href: \"http://mysite.com/\"}} />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(<Helmet />, container);\n\n                    requestAnimationFrame(() => {\n                        const existingTags = headElement.querySelectorAll(\n                            `base[${HELMET_ATTRIBUTE}]`\n                        );\n\n                        expect(existingTags).to.not.equal(undefined);\n                        expect(existingTags.length).to.equal(0);\n\n                        done();\n                    });\n                });\n            });\n\n            it(\"tags without 'href' are not accepted\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <base property=\"won't work\" />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const existingTags = headElement.querySelectorAll(\n                        `base[${HELMET_ATTRIBUTE}]`\n                    );\n\n                    expect(existingTags).to.not.equal(undefined);\n                    expect(existingTags.length).to.equal(0);\n\n                    done();\n                });\n            });\n\n            it(\"sets base tag based on deepest nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet>\n                            <base href=\"http://mysite.com\" />\n                        </Helmet>\n                        <Helmet>\n                            <base href=\"http://mysite.com/public\" />\n                        </Helmet>\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const existingTags = headElement.querySelectorAll(\n                        `base[${HELMET_ATTRIBUTE}]`\n                    );\n                    const firstTag = Array.prototype.slice.call(\n                        existingTags\n                    )[0];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.be.equal(1);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"href\")).to.equal(\n                        \"http://mysite.com/public\"\n                    );\n                    expect(firstTag.outerHTML).to.equal(\n                        `<base href=\"http://mysite.com/public\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"does not render tag when primary attribute is null\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <base href={undefined} />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `base[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    expect(existingTags).to.be.empty;\n\n                    done();\n                });\n            });\n        });\n\n        describe(\"meta tags\", () => {\n            it(\"updates meta tags\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <meta charSet=\"utf-8\" />\n                        <meta name=\"description\" content=\"Test description\" />\n                        <meta httpEquiv=\"content-type\" content=\"text/html\" />\n                        <meta property=\"og:type\" content=\"article\" />\n                        <meta itemProp=\"name\" content=\"Test name itemprop\" />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `meta[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    const filteredTags = [].slice\n                        .call(existingTags)\n                        .filter(tag => {\n                            return (\n                                tag.getAttribute(\"charset\") === \"utf-8\" ||\n                                (tag.getAttribute(\"name\") === \"description\" &&\n                                    tag.getAttribute(\"content\") ===\n                                        \"Test description\") ||\n                                (tag.getAttribute(\"http-equiv\") ===\n                                    \"content-type\" &&\n                                    tag.getAttribute(\"content\") ===\n                                        \"text/html\") ||\n                                (tag.getAttribute(\"itemprop\") === \"name\" &&\n                                    tag.getAttribute(\"content\") ===\n                                        \"Test name itemprop\")\n                            );\n                        });\n\n                    expect(filteredTags.length).to.be.at.least(4);\n\n                    done();\n                });\n            });\n\n            it(\"clears all meta tags if none are specified\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <meta name=\"description\" content=\"Test description\" />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(<Helmet />, container);\n\n                    requestAnimationFrame(() => {\n                        const existingTags = headElement.querySelectorAll(\n                            `meta[${HELMET_ATTRIBUTE}]`\n                        );\n\n                        expect(existingTags).to.not.equal(undefined);\n                        expect(existingTags.length).to.equal(0);\n\n                        done();\n                    });\n                });\n            });\n\n            it(\"tags without 'name', 'http-equiv', 'property', 'charset', or 'itemprop' are not accepted\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <meta href=\"won't work\" />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const existingTags = headElement.querySelectorAll(\n                        `meta[${HELMET_ATTRIBUTE}]`\n                    );\n\n                    expect(existingTags).to.not.equal(undefined);\n                    expect(existingTags.length).to.equal(0);\n\n                    done();\n                });\n            });\n\n            it(\"sets meta tags based on deepest nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet>\n                            <meta charSet=\"utf-8\" />\n                            <meta\n                                name=\"description\"\n                                content=\"Test description\"\n                            />\n                        </Helmet>\n                        <Helmet>\n                            <meta\n                                name=\"description\"\n                                content=\"Inner description\"\n                            />\n                            <meta name=\"keywords\" content=\"test,meta,tags\" />\n                        </Helmet>\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `meta[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n\n                    const firstTag = existingTags[0];\n                    const secondTag = existingTags[1];\n                    const thirdTag = existingTags[2];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.be.equal(3);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"charset\")).to.equal(\"utf-8\");\n                    expect(firstTag.outerHTML).to.equal(\n                        `<meta charset=\"utf-8\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[1]\")\n                        .that.is.an.instanceof(Element);\n                    expect(secondTag).to.have.property(\"getAttribute\");\n                    expect(secondTag.getAttribute(\"name\")).to.equal(\n                        \"description\"\n                    );\n                    expect(secondTag.getAttribute(\"content\")).to.equal(\n                        \"Inner description\"\n                    );\n                    expect(secondTag.outerHTML).to.equal(\n                        `<meta name=\"description\" content=\"Inner description\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[2]\")\n                        .that.is.an.instanceof(Element);\n                    expect(thirdTag).to.have.property(\"getAttribute\");\n                    expect(thirdTag.getAttribute(\"name\")).to.equal(\"keywords\");\n                    expect(thirdTag.getAttribute(\"content\")).to.equal(\n                        \"test,meta,tags\"\n                    );\n                    expect(thirdTag.outerHTML).to.equal(\n                        `<meta name=\"keywords\" content=\"test,meta,tags\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"allows duplicate meta tags if specified in the same component\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <meta name=\"description\" content=\"Test description\" />\n                        <meta\n                            name=\"description\"\n                            content=\"Duplicate description\"\n                        />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `meta[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n                    const secondTag = existingTags[1];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.equal(2);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"name\")).to.equal(\n                        \"description\"\n                    );\n                    expect(firstTag.getAttribute(\"content\")).to.equal(\n                        \"Test description\"\n                    );\n                    expect(firstTag.outerHTML).to.equal(\n                        `<meta name=\"description\" content=\"Test description\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[1]\")\n                        .that.is.an.instanceof(Element);\n                    expect(secondTag).to.have.property(\"getAttribute\");\n                    expect(secondTag.getAttribute(\"name\")).to.equal(\n                        \"description\"\n                    );\n                    expect(secondTag.getAttribute(\"content\")).to.equal(\n                        \"Duplicate description\"\n                    );\n                    expect(secondTag.outerHTML).to.equal(\n                        `<meta name=\"description\" content=\"Duplicate description\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"overrides duplicate meta tags with single meta tag in a nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet>\n                            <meta\n                                name=\"description\"\n                                content=\"Test description\"\n                            />\n                            <meta\n                                name=\"description\"\n                                content=\"Duplicate description\"\n                            />\n                        </Helmet>\n                        <Helmet>\n                            <meta\n                                name=\"description\"\n                                content=\"Inner description\"\n                            />\n                        </Helmet>\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `meta[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.equal(1);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"name\")).to.equal(\n                        \"description\"\n                    );\n                    expect(firstTag.getAttribute(\"content\")).to.equal(\n                        \"Inner description\"\n                    );\n                    expect(firstTag.outerHTML).to.equal(\n                        `<meta name=\"description\" content=\"Inner description\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"overrides single meta tag with duplicate meta tags in a nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet>\n                            <meta\n                                name=\"description\"\n                                content=\"Test description\"\n                            />\n                        </Helmet>\n                        <Helmet>\n                            <meta\n                                name=\"description\"\n                                content=\"Inner description\"\n                            />\n                            <meta\n                                name=\"description\"\n                                content=\"Inner duplicate description\"\n                            />\n                        </Helmet>\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `meta[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n                    const secondTag = existingTags[1];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.equal(2);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"name\")).to.equal(\n                        \"description\"\n                    );\n                    expect(firstTag.getAttribute(\"content\")).to.equal(\n                        \"Inner description\"\n                    );\n                    expect(firstTag.outerHTML).to.equal(\n                        `<meta name=\"description\" content=\"Inner description\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[1]\")\n                        .that.is.an.instanceof(Element);\n                    expect(secondTag).to.have.property(\"getAttribute\");\n                    expect(secondTag.getAttribute(\"name\")).to.equal(\n                        \"description\"\n                    );\n                    expect(secondTag.getAttribute(\"content\")).to.equal(\n                        \"Inner duplicate description\"\n                    );\n                    expect(secondTag.outerHTML).to.equal(\n                        `<meta name=\"description\" content=\"Inner duplicate description\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"does not render tag when primary attribute is null\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <meta\n                            name={undefined}\n                            content=\"Inner duplicate description\"\n                        />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `meta[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    expect(existingTags).to.be.empty;\n\n                    done();\n                });\n            });\n        });\n\n        describe(\"link tags\", () => {\n            it(\"updates link tags\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <link href=\"http://localhost/helmet\" rel=\"canonical\" />\n                        <link\n                            href=\"http://localhost/style.css\"\n                            rel=\"stylesheet\"\n                            type=\"text/css\"\n                        />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `link[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    const filteredTags = [].slice\n                        .call(existingTags)\n                        .filter(tag => {\n                            return (\n                                (tag.getAttribute(\"href\") ===\n                                    \"http://localhost/style.css\" &&\n                                    tag.getAttribute(\"rel\") === \"stylesheet\" &&\n                                    tag.getAttribute(\"type\") === \"text/css\") ||\n                                (tag.getAttribute(\"href\") ===\n                                    \"http://localhost/helmet\" &&\n                                    tag.getAttribute(\"rel\") === \"canonical\")\n                            );\n                        });\n\n                    expect(filteredTags.length).to.be.at.least(2);\n\n                    done();\n                });\n            });\n\n            it(\"clears all link tags if none are specified\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <link href=\"http://localhost/helmet\" rel=\"canonical\" />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(<Helmet />, container);\n\n                    requestAnimationFrame(() => {\n                        const tagNodes = headElement.querySelectorAll(\n                            `link[${HELMET_ATTRIBUTE}]`\n                        );\n                        const existingTags = Array.prototype.slice.call(\n                            tagNodes\n                        );\n\n                        expect(existingTags).to.not.equal(undefined);\n                        expect(existingTags.length).to.equal(0);\n\n                        done();\n                    });\n                });\n            });\n\n            it(\"tags without 'href' or 'rel' are not accepted, even if they are valid for other tags\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <link httpEquiv=\"won't work\" />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `link[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n\n                    expect(existingTags).to.not.equal(undefined);\n                    expect(existingTags.length).to.equal(0);\n\n                    done();\n                });\n            });\n\n            it(\"tags 'rel' and 'href' properly use 'rel' as the primary identification for this tag, regardless of ordering\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet>\n                            <link\n                                href=\"http://localhost/helmet\"\n                                rel=\"canonical\"\n                            />\n                        </Helmet>\n                        <Helmet>\n                            <link\n                                rel=\"canonical\"\n                                href=\"http://localhost/helmet/new\"\n                            />\n                        </Helmet>\n                        <Helmet>\n                            <link\n                                href=\"http://localhost/helmet/newest\"\n                                rel=\"canonical\"\n                            />\n                        </Helmet>\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `link[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.equal(1);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"rel\")).to.equal(\"canonical\");\n                    expect(firstTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/helmet/newest\"\n                    );\n                    expect(firstTag.outerHTML).to.equal(\n                        `<link href=\"http://localhost/helmet/newest\" rel=\"canonical\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"tags with rel='stylesheet' uses the href as the primary identification of the tag, regardless of ordering\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet>\n                            <link\n                                href=\"http://localhost/style.css\"\n                                rel=\"stylesheet\"\n                                type=\"text/css\"\n                                media=\"all\"\n                            />\n                        </Helmet>\n                        <Helmet>\n                            <link\n                                rel=\"stylesheet\"\n                                href=\"http://localhost/inner.css\"\n                                type=\"text/css\"\n                                media=\"all\"\n                            />\n                        </Helmet>\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `link[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n                    const secondTag = existingTags[1];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.equal(2);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/style.css\"\n                    );\n                    expect(firstTag.getAttribute(\"rel\")).to.equal(\"stylesheet\");\n                    expect(firstTag.getAttribute(\"type\")).to.equal(\"text/css\");\n                    expect(firstTag.getAttribute(\"media\")).to.equal(\"all\");\n                    expect(firstTag.outerHTML).to.equal(\n                        `<link href=\"http://localhost/style.css\" rel=\"stylesheet\" type=\"text/css\" media=\"all\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[1]\")\n                        .that.is.an.instanceof(Element);\n                    expect(secondTag).to.have.property(\"getAttribute\");\n                    expect(secondTag.getAttribute(\"rel\")).to.equal(\n                        \"stylesheet\"\n                    );\n                    expect(secondTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/inner.css\"\n                    );\n                    expect(secondTag.getAttribute(\"type\")).to.equal(\"text/css\");\n                    expect(secondTag.getAttribute(\"media\")).to.equal(\"all\");\n                    expect(secondTag.outerHTML).to.equal(\n                        `<link rel=\"stylesheet\" href=\"http://localhost/inner.css\" type=\"text/css\" media=\"all\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"sets link tags based on deepest nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet>\n                            <link\n                                rel=\"canonical\"\n                                href=\"http://localhost/helmet\"\n                            />\n                            <link\n                                href=\"http://localhost/style.css\"\n                                rel=\"stylesheet\"\n                                type=\"text/css\"\n                                media=\"all\"\n                            />\n                        </Helmet>\n                        <Helmet>\n                            <link\n                                rel=\"canonical\"\n                                href=\"http://localhost/helmet/innercomponent\"\n                            />\n                            <link\n                                href=\"http://localhost/inner.css\"\n                                rel=\"stylesheet\"\n                                type=\"text/css\"\n                                media=\"all\"\n                            />\n                        </Helmet>\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `link[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n                    const secondTag = existingTags[1];\n                    const thirdTag = existingTags[2];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.be.at.least(2);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/style.css\"\n                    );\n                    expect(firstTag.getAttribute(\"rel\")).to.equal(\"stylesheet\");\n                    expect(firstTag.getAttribute(\"type\")).to.equal(\"text/css\");\n                    expect(firstTag.getAttribute(\"media\")).to.equal(\"all\");\n                    expect(firstTag.outerHTML).to.equal(\n                        `<link href=\"http://localhost/style.css\" rel=\"stylesheet\" type=\"text/css\" media=\"all\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[1]\")\n                        .that.is.an.instanceof(Element);\n                    expect(secondTag).to.have.property(\"getAttribute\");\n                    expect(secondTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/helmet/innercomponent\"\n                    );\n                    expect(secondTag.getAttribute(\"rel\")).to.equal(\"canonical\");\n                    expect(secondTag.outerHTML).to.equal(\n                        `<link rel=\"canonical\" href=\"http://localhost/helmet/innercomponent\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[2]\")\n                        .that.is.an.instanceof(Element);\n                    expect(thirdTag).to.have.property(\"getAttribute\");\n                    expect(thirdTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/inner.css\"\n                    );\n                    expect(thirdTag.getAttribute(\"rel\")).to.equal(\"stylesheet\");\n                    expect(thirdTag.getAttribute(\"type\")).to.equal(\"text/css\");\n                    expect(thirdTag.getAttribute(\"media\")).to.equal(\"all\");\n                    expect(thirdTag.outerHTML).to.equal(\n                        `<link href=\"http://localhost/inner.css\" rel=\"stylesheet\" type=\"text/css\" media=\"all\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"allows duplicate link tags if specified in the same component\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <link rel=\"canonical\" href=\"http://localhost/helmet\" />\n                        <link\n                            rel=\"canonical\"\n                            href=\"http://localhost/helmet/component\"\n                        />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `link[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n                    const secondTag = existingTags[1];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.be.at.least(2);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"rel\")).to.equal(\"canonical\");\n                    expect(firstTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/helmet\"\n                    );\n                    expect(firstTag.outerHTML).to.equal(\n                        `<link rel=\"canonical\" href=\"http://localhost/helmet\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[1]\")\n                        .that.is.an.instanceof(Element);\n                    expect(secondTag).to.have.property(\"getAttribute\");\n                    expect(secondTag.getAttribute(\"rel\")).to.equal(\"canonical\");\n                    expect(secondTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/helmet/component\"\n                    );\n                    expect(secondTag.outerHTML).to.equal(\n                        `<link rel=\"canonical\" href=\"http://localhost/helmet/component\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"overrides duplicate link tags with a single link tag in a nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet>\n                            <link\n                                rel=\"canonical\"\n                                href=\"http://localhost/helmet\"\n                            />\n                            <link\n                                rel=\"canonical\"\n                                href=\"http://localhost/helmet/component\"\n                            />\n                        </Helmet>\n                        <Helmet>\n                            <link\n                                rel=\"canonical\"\n                                href=\"http://localhost/helmet/innercomponent\"\n                            />\n                        </Helmet>\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `link[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.be.equal(1);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"rel\")).to.equal(\"canonical\");\n                    expect(firstTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/helmet/innercomponent\"\n                    );\n                    expect(firstTag.outerHTML).to.equal(\n                        `<link rel=\"canonical\" href=\"http://localhost/helmet/innercomponent\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"overrides single link tag with duplicate link tags in a nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet>\n                            <link\n                                rel=\"canonical\"\n                                href=\"http://localhost/helmet\"\n                            />\n                        </Helmet>\n                        <Helmet>\n                            <link\n                                rel=\"canonical\"\n                                href=\"http://localhost/helmet/component\"\n                            />\n                            <link\n                                rel=\"canonical\"\n                                href=\"http://localhost/helmet/innercomponent\"\n                            />\n                        </Helmet>\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `link[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n                    const secondTag = existingTags[1];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.be.equal(2);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"rel\")).to.equal(\"canonical\");\n                    expect(firstTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/helmet/component\"\n                    );\n                    expect(firstTag.outerHTML).to.equal(\n                        `<link rel=\"canonical\" href=\"http://localhost/helmet/component\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[1]\")\n                        .that.is.an.instanceof(Element);\n                    expect(secondTag).to.have.property(\"getAttribute\");\n                    expect(secondTag.getAttribute(\"rel\")).to.equal(\"canonical\");\n                    expect(secondTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/helmet/innercomponent\"\n                    );\n                    expect(secondTag.outerHTML).to.equal(\n                        `<link rel=\"canonical\" href=\"http://localhost/helmet/innercomponent\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"does not render tag when primary attribute is null\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <link rel=\"icon\" sizes=\"192x192\" href={null} />\n                        <link\n                            rel=\"canonical\"\n                            href=\"http://localhost/helmet/component\"\n                        />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `link[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n\n                    expect(existingTags).to.not.equal(undefined);\n                    expect(existingTags.length).to.be.equal(1);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"rel\")).to.equal(\"canonical\");\n                    expect(firstTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/helmet/component\"\n                    );\n                    expect(firstTag.outerHTML).to.equal(\n                        `<link rel=\"canonical\" href=\"http://localhost/helmet/component\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n        });\n\n        describe(\"script tags\", () => {\n            it(\"updates script tags\", done => {\n                const scriptInnerHTML = `\n                  {\n                    \"@context\": \"http://schema.org\",\n                    \"@type\": \"NewsArticle\",\n                    \"url\": \"http://localhost/helmet\"\n                  }\n                `;\n                ReactDOM.render(\n                    <Helmet>\n                        <script\n                            src=\"http://localhost/test.js\"\n                            type=\"text/javascript\"\n                        />\n                        <script\n                            src=\"http://localhost/test2.js\"\n                            type=\"text/javascript\"\n                        />\n                        <script type=\"application/ld+json\">\n                            {scriptInnerHTML}\n                        </script>\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const existingTags = headElement.getElementsByTagName(\n                        \"script\"\n                    );\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    const filteredTags = [].slice\n                        .call(existingTags)\n                        .filter(tag => {\n                            return (\n                                (tag.getAttribute(\"src\") ===\n                                    \"http://localhost/test.js\" &&\n                                    tag.getAttribute(\"type\") ===\n                                        \"text/javascript\") ||\n                                (tag.getAttribute(\"src\") ===\n                                    \"http://localhost/test2.js\" &&\n                                    tag.getAttribute(\"type\") ===\n                                        \"text/javascript\") ||\n                                (tag.getAttribute(\"type\") ===\n                                    \"application/ld+json\" &&\n                                    tag.innerHTML === scriptInnerHTML)\n                            );\n                        });\n\n                    expect(filteredTags.length).to.be.at.least(3);\n\n                    done();\n                });\n            });\n\n            it(\"clears all scripts tags if none are specified\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <script\n                            src=\"http://localhost/test.js\"\n                            type=\"text/javascript\"\n                        />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(<Helmet />, container);\n\n                    requestAnimationFrame(() => {\n                        const existingTags = headElement.querySelectorAll(\n                            `script[${HELMET_ATTRIBUTE}]`\n                        );\n\n                        expect(existingTags).to.not.equal(undefined);\n                        expect(existingTags.length).to.equal(0);\n\n                        done();\n                    });\n                });\n            });\n\n            it(\"tags without 'src' are not accepted\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <script property=\"won't work\" />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const existingTags = headElement.querySelectorAll(\n                        `script[${HELMET_ATTRIBUTE}]`\n                    );\n\n                    expect(existingTags).to.not.equal(undefined);\n                    expect(existingTags.length).to.equal(0);\n\n                    done();\n                });\n            });\n\n            it(\"sets script tags based on deepest nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet>\n                            <script\n                                src=\"http://localhost/test.js\"\n                                type=\"text/javascript\"\n                            />\n                            <script\n                                src=\"http://localhost/test2.js\"\n                                type=\"text/javascript\"\n                            />\n                        </Helmet>\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `script[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n                    const secondTag = existingTags[1];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.be.at.least(2);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"src\")).to.equal(\n                        \"http://localhost/test.js\"\n                    );\n                    expect(firstTag.getAttribute(\"type\")).to.equal(\n                        \"text/javascript\"\n                    );\n                    expect(firstTag.outerHTML).to.equal(\n                        `<script src=\"http://localhost/test.js\" type=\"text/javascript\" ${HELMET_ATTRIBUTE}=\"true\"></script>`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[1]\")\n                        .that.is.an.instanceof(Element);\n                    expect(secondTag).to.have.property(\"getAttribute\");\n                    expect(secondTag.getAttribute(\"src\")).to.equal(\n                        \"http://localhost/test2.js\"\n                    );\n                    expect(secondTag.getAttribute(\"type\")).to.equal(\n                        \"text/javascript\"\n                    );\n                    expect(secondTag.outerHTML).to.equal(\n                        `<script src=\"http://localhost/test2.js\" type=\"text/javascript\" ${HELMET_ATTRIBUTE}=\"true\"></script>`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"sets undefined attribute values to empty strings\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <script src=\"foo.js\" async={undefined} />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const existingTag = headElement.querySelector(\n                        `script[${HELMET_ATTRIBUTE}]`\n                    );\n\n                    expect(existingTag).to.not.equal(undefined);\n                    expect(existingTag.outerHTML)\n                        .to.be.a(\"string\")\n                        .that.equals(\n                            `<script src=\"foo.js\" async=\"\" ${HELMET_ATTRIBUTE}=\"true\"></script>`\n                        );\n\n                    done();\n                });\n            });\n\n            it(\"does not render tag when primary attribute (src) is null\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <script src={undefined} type=\"text/javascript\" />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `script[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    expect(existingTags).to.be.empty;\n\n                    done();\n                });\n            });\n\n            it(\"does not render tag when primary attribute (innerHTML) is null\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <script innerHTML={undefined} />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `script[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    expect(existingTags).to.be.empty;\n\n                    done();\n                });\n            });\n        });\n\n        describe(\"noscript tags\", () => {\n            it(\"updates noscript tags\", done => {\n                const noscriptInnerHTML = `<link rel=\"stylesheet\" type=\"text/css\" href=\"foo.css\" />`;\n                ReactDOM.render(\n                    <Helmet>\n                        <noscript id=\"bar\">{noscriptInnerHTML}</noscript>\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const existingTags = headElement.getElementsByTagName(\n                        \"noscript\"\n                    );\n\n                    expect(existingTags).to.not.equal(undefined);\n                    expect(existingTags.length).to.equal(1);\n                    expect(\n                        existingTags[0].innerHTML === noscriptInnerHTML &&\n                            existingTags[0].id === \"bar\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"clears all noscripts tags if none are specified\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <noscript id=\"bar\" />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(<Helmet />, container);\n\n                    requestAnimationFrame(() => {\n                        const existingTags = headElement.querySelectorAll(\n                            `script[${HELMET_ATTRIBUTE}]`\n                        );\n\n                        expect(existingTags).to.not.equal(undefined);\n                        expect(existingTags.length).to.equal(0);\n\n                        done();\n                    });\n                });\n            });\n\n            it(\"tags without 'innerHTML' are not accepted\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <noscript property=\"won't work\" />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const existingTags = headElement.querySelectorAll(\n                        `noscript[${HELMET_ATTRIBUTE}]`\n                    );\n\n                    expect(existingTags).to.not.equal(undefined);\n                    expect(existingTags.length).to.equal(0);\n\n                    done();\n                });\n            });\n\n            it(\"does not render tag when primary attribute is null\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <noscript>{undefined}</noscript>\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `noscript[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    expect(existingTags).to.be.empty;\n\n                    done();\n                });\n            });\n        });\n\n        describe(\"style tags\", () => {\n            it(\"updates style tags\", done => {\n                const cssText1 = `\n                    body {\n                        background-color: green;\n                    }\n                `;\n                const cssText2 = `\n                    p {\n                        font-size: 12px;\n                    }\n                `;\n\n                ReactDOM.render(\n                    <Helmet>\n                        <style type=\"text/css\">{cssText1}</style>\n                        <style>{cssText2}</style>\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `style[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n\n                    const [firstTag, secondTag] = existingTags;\n                    expect(existingTags).to.not.equal(undefined);\n                    expect(existingTags.length).to.be.equal(2);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"type\")).to.equal(\"text/css\");\n                    expect(firstTag.innerHTML).to.equal(cssText1);\n                    expect(firstTag.outerHTML).to.equal(\n                        `<style type=\"text/css\" ${HELMET_ATTRIBUTE}=\"true\">${cssText1}</style>`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[1]\")\n                        .that.is.an.instanceof(Element);\n                    expect(secondTag.innerHTML).to.equal(cssText2);\n                    expect(secondTag.outerHTML).to.equal(\n                        `<style ${HELMET_ATTRIBUTE}=\"true\">${cssText2}</style>`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"clears all style tags if none are specified\", done => {\n                const cssText = `\n                    body {\n                        background-color: green;\n                    }\n                `;\n                ReactDOM.render(\n                    <Helmet>\n                        <style type=\"text/css\">{cssText}</style>\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(<Helmet />, container);\n\n                    requestAnimationFrame(() => {\n                        const existingTags = headElement.querySelectorAll(\n                            `style[${HELMET_ATTRIBUTE}]`\n                        );\n\n                        expect(existingTags).to.not.equal(undefined);\n                        expect(existingTags.length).to.equal(0);\n\n                        done();\n                    });\n                });\n            });\n\n            it(\"tags without 'cssText' are not accepted\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <style property=\"won't work\" />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const existingTags = headElement.querySelectorAll(\n                        `style[${HELMET_ATTRIBUTE}]`\n                    );\n\n                    expect(existingTags).to.not.equal(undefined);\n                    expect(existingTags.length).to.equal(0);\n\n                    done();\n                });\n            });\n\n            it(\"does not render tag when primary attribute is null\", done => {\n                ReactDOM.render(\n                    <Helmet>\n                        <style>{undefined}</style>\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `style[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    expect(existingTags).to.be.empty;\n\n                    done();\n                });\n            });\n        });\n    });\n\n    describe(\"deferred tags\", () => {\n        beforeEach(() => {\n            window.__spy__ = sinon.spy();\n        });\n\n        afterEach(() => {\n            delete window.__spy__;\n        });\n\n        it(\"executes synchronously when defer={true} and async otherwise\", done => {\n            ReactDOM.render(\n                <div>\n                    <Helmet defer={false}>\n                        <script>window.__spy__(1)</script>\n                    </Helmet>\n                    <Helmet>\n                        <script>window.__spy__(2)</script>\n                    </Helmet>\n                </div>,\n                container\n            );\n\n            expect(window.__spy__.callCount).to.equal(1);\n\n            requestAnimationFrame(() => {\n                expect(window.__spy__.callCount).to.equal(2);\n                expect(window.__spy__.args).to.deep.equal([[1], [2]]);\n                done();\n            });\n        });\n    });\n\n    describe(\"server\", () => {\n        const stringifiedHtmlAttributes = `lang=\"ga\" class=\"myClassName\"`;\n        const stringifiedBodyAttributes = `lang=\"ga\" class=\"myClassName\"`;\n        const stringifiedTitle = `<title ${HELMET_ATTRIBUTE}=\"true\">Dangerous &lt;script&gt; include</title>`;\n        const unEncodedStringifiedTitle = `<title ${HELMET_ATTRIBUTE}=\"true\">This is text and & and '.</title>`;\n        const stringifiedTitleWithItemprop = `<title ${HELMET_ATTRIBUTE}=\"true\" itemprop=\"name\">Title with Itemprop</title>`;\n        // Separate itemprop string for the server - Per https://github.com/facebook/react/issues/12403 the server renders HTML Microdata as camel case\n        const stringifiedTitleWithItempropFromServer = `<title ${HELMET_ATTRIBUTE}=\"true\" itemProp=\"name\">Title with Itemprop</title>`;\n        const stringifiedTitleWithTitleExpression = `<title ${HELMET_ATTRIBUTE}=\"true\">Title: Some Great Title</title>`;\n        const stringifiedBaseTag = `<base ${HELMET_ATTRIBUTE}=\"true\" target=\"_blank\" href=\"http://localhost/\"/>`;\n\n        const stringifiedMetaTags = [\n            `<meta ${HELMET_ATTRIBUTE}=\"true\" charset=\"utf-8\"/>`,\n            `<meta ${HELMET_ATTRIBUTE}=\"true\" name=\"description\" content=\"Test description &amp; encoding of special characters like &#x27; &quot; &gt; &lt; \\`\"/>`,\n            `<meta ${HELMET_ATTRIBUTE}=\"true\" http-equiv=\"content-type\" content=\"text/html\"/>`,\n            `<meta ${HELMET_ATTRIBUTE}=\"true\" property=\"og:type\" content=\"article\"/>`,\n            `<meta ${HELMET_ATTRIBUTE}=\"true\" itemprop=\"name\" content=\"Test name itemprop\"/>`\n        ].join(\"\");\n        // Separate itemprop string for the server - Per https://github.com/facebook/react/issues/12403 the server renders HTML Microdata as camel case\n        const stringifiedMetaTagsFromServer = [\n            `<meta ${HELMET_ATTRIBUTE}=\"true\" charSet=\"utf-8\"/>`,\n            `<meta ${HELMET_ATTRIBUTE}=\"true\" name=\"description\" content=\"Test description &amp; encoding of special characters like &#x27; &quot; &gt; &lt; \\`\"/>`,\n            `<meta ${HELMET_ATTRIBUTE}=\"true\" http-equiv=\"content-type\" content=\"text/html\"/>`,\n            `<meta ${HELMET_ATTRIBUTE}=\"true\" property=\"og:type\" content=\"article\"/>`,\n            `<meta ${HELMET_ATTRIBUTE}=\"true\" itemProp=\"name\" content=\"Test name itemprop\"/>`\n        ].join(\"\");\n\n        const stringifiedLinkTags = [\n            `<link ${HELMET_ATTRIBUTE}=\"true\" href=\"http://localhost/helmet\" rel=\"canonical\"/>`,\n            `<link ${HELMET_ATTRIBUTE}=\"true\" href=\"http://localhost/style.css\" rel=\"stylesheet\" type=\"text/css\"/>`\n        ].join(\"\");\n\n        const stringifiedScriptTags = [\n            `<script ${HELMET_ATTRIBUTE}=\"true\" src=\"http://localhost/test.js\" type=\"text/javascript\"></script>`,\n            `<script ${HELMET_ATTRIBUTE}=\"true\" src=\"http://localhost/test2.js\" type=\"text/javascript\"></script>`\n        ].join(\"\");\n\n        const stringifiedNoscriptTags = [\n            `<noscript ${HELMET_ATTRIBUTE}=\"true\" id=\"foo\"><link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\" /></noscript>`,\n            `<noscript ${HELMET_ATTRIBUTE}=\"true\" id=\"bar\"><link rel=\"stylesheet\" type=\"text/css\" href=\"/style2.css\" /></noscript>`\n        ].join(\"\");\n\n        const stringifiedStyleTags = [\n            `<style ${HELMET_ATTRIBUTE}=\"true\" type=\"text/css\">body {background-color: green;}</style>`,\n            `<style ${HELMET_ATTRIBUTE}=\"true\" type=\"text/css\">p {font-size: 12px;}</style>`\n        ].join(\"\");\n\n        before(() => {\n            Helmet.canUseDOM = false;\n        });\n\n        it(\"provides initial values if no state is found\", () => {\n            let head = Helmet.rewind();\n            head = Helmet.rewind();\n\n            expect(head.meta).to.exist;\n            expect(head.meta).to.respondTo(\"toString\");\n\n            expect(head.meta.toString()).to.equal(\"\");\n        });\n\n        it(\"encodes special characters in title\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <title>{`Dangerous <script> include`}</title>\n                </Helmet>,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.title).to.exist;\n            expect(head.title).to.respondTo(\"toString\");\n\n            expect(head.title.toString()).to.equal(stringifiedTitle);\n        });\n\n        it(\"opts out of string encoding\", () => {\n            ReactDOM.render(\n                <Helmet encodeSpecialCharacters={false}>\n                    <title>{\"This is text and & and '.\"}</title>\n                </Helmet>,\n                container\n            );\n\n            const head = Helmet.rewind();\n            expect(head.title).to.exist;\n            expect(head.title).to.respondTo(\"toString\");\n\n            expect(head.title.toString()).to.equal(unEncodedStringifiedTitle);\n        });\n\n        it(\"renders title as React component\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <title>{`Dangerous <script> include`}</title>\n                </Helmet>,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.title).to.exist;\n            expect(head.title).to.respondTo(\"toComponent\");\n\n            const titleComponent = head.title.toComponent();\n\n            expect(titleComponent)\n                .to.be.an(\"array\")\n                .that.has.length.of(1);\n\n            titleComponent.forEach(title => {\n                expect(title)\n                    .to.be.an(\"object\")\n                    .that.contains.property(\"type\", \"title\");\n            });\n\n            const markup = ReactServer.renderToStaticMarkup(\n                <div>{titleComponent}</div>\n            );\n\n            expect(markup)\n                .to.be.a(\"string\")\n                .that.equals(`<div>${stringifiedTitle}</div>`);\n        });\n\n        it(\"renders title with itemprop name as React component\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <title itemProp=\"name\">Title with Itemprop</title>\n                </Helmet>,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.title).to.exist;\n            expect(head.title).to.respondTo(\"toComponent\");\n\n            const titleComponent = head.title.toComponent();\n\n            expect(titleComponent)\n                .to.be.an(\"array\")\n                .that.has.length.of(1);\n\n            titleComponent.forEach(title => {\n                expect(title)\n                    .to.be.an(\"object\")\n                    .that.contains.property(\"type\", \"title\");\n            });\n\n            const markup = ReactServer.renderToStaticMarkup(\n                <div>{titleComponent}</div>\n            );\n\n            expect(markup)\n                .to.be.a(\"string\")\n                .that.equals(\n                    `<div>${stringifiedTitleWithItempropFromServer}</div>`\n                );\n        });\n\n        it(\"renders base tag as React component\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <base target=\"_blank\" href=\"http://localhost/\" />\n                </Helmet>,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.base).to.exist;\n            expect(head.base).to.respondTo(\"toComponent\");\n\n            const baseComponent = head.base.toComponent();\n\n            expect(baseComponent)\n                .to.be.an(\"array\")\n                .that.has.length.of(1);\n\n            baseComponent.forEach(base => {\n                expect(base)\n                    .to.be.an(\"object\")\n                    .that.contains.property(\"type\", \"base\");\n            });\n\n            const markup = ReactServer.renderToStaticMarkup(\n                <div>{baseComponent}</div>\n            );\n\n            expect(markup)\n                .to.be.a(\"string\")\n                .that.equals(`<div>${stringifiedBaseTag}</div>`);\n        });\n\n        it(\"renders meta tags as React components\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <meta charSet=\"utf-8\" />\n                    <meta\n                        name=\"description\"\n                        content={\n                            \"Test description & encoding of special characters like ' \\\" > < `\"\n                        }\n                    />\n                    <meta httpEquiv=\"content-type\" content=\"text/html\" />\n                    <meta property=\"og:type\" content=\"article\" />\n                    <meta itemProp=\"name\" content=\"Test name itemprop\" />\n                </Helmet>,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.meta).to.exist;\n            expect(head.meta).to.respondTo(\"toComponent\");\n\n            const metaComponent = head.meta.toComponent();\n\n            expect(metaComponent)\n                .to.be.an(\"array\")\n                .that.has.length.of(5);\n\n            metaComponent.forEach(meta => {\n                expect(meta)\n                    .to.be.an(\"object\")\n                    .that.contains.property(\"type\", \"meta\");\n            });\n\n            const markup = ReactServer.renderToStaticMarkup(\n                <div>{metaComponent}</div>\n            );\n\n            expect(markup)\n                .to.be.a(\"string\")\n                .that.equals(`<div>${stringifiedMetaTagsFromServer}</div>`);\n        });\n\n        it(\"renders link tags as React components\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <link href=\"http://localhost/helmet\" rel=\"canonical\" />\n                    <link\n                        href=\"http://localhost/style.css\"\n                        rel=\"stylesheet\"\n                        type=\"text/css\"\n                    />\n                </Helmet>,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.link).to.exist;\n            expect(head.link).to.respondTo(\"toComponent\");\n\n            const linkComponent = head.link.toComponent();\n\n            expect(linkComponent)\n                .to.be.an(\"array\")\n                .that.has.length.of(2);\n\n            linkComponent.forEach(link => {\n                expect(link)\n                    .to.be.an(\"object\")\n                    .that.contains.property(\"type\", \"link\");\n            });\n\n            const markup = ReactServer.renderToStaticMarkup(\n                <div>{linkComponent}</div>\n            );\n\n            expect(markup)\n                .to.be.a(\"string\")\n                .that.equals(`<div>${stringifiedLinkTags}</div>`);\n        });\n\n        it(\"renders script tags as React components\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <script\n                        src=\"http://localhost/test.js\"\n                        type=\"text/javascript\"\n                    />\n                    <script\n                        src=\"http://localhost/test2.js\"\n                        type=\"text/javascript\"\n                    />\n                </Helmet>,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.script).to.exist;\n            expect(head.script).to.respondTo(\"toComponent\");\n\n            const scriptComponent = head.script.toComponent();\n\n            expect(scriptComponent)\n                .to.be.an(\"array\")\n                .that.has.length.of(2);\n\n            scriptComponent.forEach(script => {\n                expect(script)\n                    .to.be.an(\"object\")\n                    .that.contains.property(\"type\", \"script\");\n            });\n\n            const markup = ReactServer.renderToStaticMarkup(\n                <div>{scriptComponent}</div>\n            );\n\n            expect(markup)\n                .to.be.a(\"string\")\n                .that.equals(`<div>${stringifiedScriptTags}</div>`);\n        });\n\n        it(\"renders noscript tags as React components\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <noscript id=\"foo\">{`<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\" />`}</noscript>\n                    <noscript id=\"bar\">{`<link rel=\"stylesheet\" type=\"text/css\" href=\"/style2.css\" />`}</noscript>\n                </Helmet>,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.noscript).to.exist;\n            expect(head.noscript).to.respondTo(\"toComponent\");\n\n            const noscriptComponent = head.noscript.toComponent();\n\n            expect(noscriptComponent)\n                .to.be.an(\"array\")\n                .that.has.length.of(2);\n\n            noscriptComponent.forEach(noscript => {\n                expect(noscript)\n                    .to.be.an(\"object\")\n                    .that.contains.property(\"type\", \"noscript\");\n            });\n\n            const markup = ReactServer.renderToStaticMarkup(\n                <div>{noscriptComponent}</div>\n            );\n\n            expect(markup)\n                .to.be.a(\"string\")\n                .that.equals(`<div>${stringifiedNoscriptTags}</div>`);\n        });\n\n        it(\"renders style tags as React components\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <style type=\"text/css\">{`body {background-color: green;}`}</style>\n                    <style type=\"text/css\">{`p {font-size: 12px;}`}</style>\n                </Helmet>,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.style).to.exist;\n            expect(head.style).to.respondTo(\"toComponent\");\n\n            const styleComponent = head.style.toComponent();\n\n            expect(styleComponent)\n                .to.be.an(\"array\")\n                .that.has.length.of(2);\n\n            const markup = ReactServer.renderToStaticMarkup(\n                <div>{styleComponent}</div>\n            );\n\n            expect(markup)\n                .to.be.a(\"string\")\n                .that.equals(`<div>${stringifiedStyleTags}</div>`);\n        });\n\n        it(\"renders title tag as string\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <title>{\"Dangerous <script> include\"}</title>\n                </Helmet>,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.title).to.exist;\n            expect(head.title).to.respondTo(\"toString\");\n\n            expect(head.title.toString())\n                .to.be.a(\"string\")\n                .that.equals(stringifiedTitle);\n        });\n\n        it(\"renders title and allows children containing expressions\", done => {\n            const someValue = \"Some Great Title\";\n\n            ReactDOM.render(\n                <Helmet>\n                    <title>Title: {someValue}</title>\n                </Helmet>,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.title).to.exist;\n            expect(head.title).to.respondTo(\"toString\");\n\n            requestAnimationFrame(() => {\n                expect(head.title.toString())\n                    .to.be.a(\"string\")\n                    .that.equals(stringifiedTitleWithTitleExpression);\n\n                done();\n            });\n        });\n\n        it(\"renders title with itemprop name as string\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <title itemProp=\"name\">Title with Itemprop</title>\n                </Helmet>,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.title).to.exist;\n            expect(head.title).to.respondTo(\"toString\");\n\n            const titleString = head.title.toString();\n            expect(titleString)\n                .to.be.a(\"string\")\n                .that.equals(stringifiedTitleWithItemprop);\n        });\n\n        it(\"renders base tags as string\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <base target=\"_blank\" href=\"http://localhost/\" />\n                </Helmet>,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.base).to.exist;\n            expect(head.base).to.respondTo(\"toString\");\n\n            expect(head.base.toString())\n                .to.be.a(\"string\")\n                .that.equals(stringifiedBaseTag);\n        });\n\n        it(\"renders meta tags as string\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <meta charSet=\"utf-8\" />\n                    <meta\n                        name=\"description\"\n                        content=\"Test description &amp; encoding of special characters like &#x27; &quot; &gt; &lt; `\"\n                    />\n                    <meta httpEquiv=\"content-type\" content=\"text/html\" />\n                    <meta property=\"og:type\" content=\"article\" />\n                    <meta itemProp=\"name\" content=\"Test name itemprop\" />\n                </Helmet>,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.meta).to.exist;\n            expect(head.meta).to.respondTo(\"toString\");\n\n            expect(head.meta.toString())\n                .to.be.a(\"string\")\n                .that.equals(stringifiedMetaTags);\n        });\n\n        it(\"renders link tags as string\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <link href=\"http://localhost/helmet\" rel=\"canonical\" />\n                    <link\n                        href=\"http://localhost/style.css\"\n                        rel=\"stylesheet\"\n                        type=\"text/css\"\n                    />\n                </Helmet>,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.link).to.exist;\n            expect(head.link).to.respondTo(\"toString\");\n\n            expect(head.link.toString())\n                .to.be.a(\"string\")\n                .that.equals(stringifiedLinkTags);\n        });\n\n        it(\"renders script tags as string\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <script\n                        src=\"http://localhost/test.js\"\n                        type=\"text/javascript\"\n                    />\n                    <script\n                        src=\"http://localhost/test2.js\"\n                        type=\"text/javascript\"\n                    />\n                </Helmet>,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.script).to.exist;\n            expect(head.script).to.respondTo(\"toString\");\n\n            expect(head.script.toString())\n                .to.be.a(\"string\")\n                .that.equals(stringifiedScriptTags);\n        });\n\n        it(\"renders style tags as string\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <style type=\"text/css\">{`body {background-color: green;}`}</style>\n                    <style type=\"text/css\">{`p {font-size: 12px;}`}</style>\n                </Helmet>,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.style).to.exist;\n            expect(head.style).to.respondTo(\"toString\");\n\n            expect(head.style.toString())\n                .to.be.a(\"string\")\n                .that.equals(stringifiedStyleTags);\n        });\n\n        it(\"renders html attributes as component\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <html lang=\"ga\" className=\"myClassName\" />\n                </Helmet>,\n                container\n            );\n\n            const {htmlAttributes} = Helmet.rewind();\n            const attrs = htmlAttributes.toComponent();\n\n            expect(attrs).to.exist;\n\n            const markup = ReactServer.renderToStaticMarkup(\n                <html lang=\"en\" {...attrs} />\n            );\n\n            expect(markup)\n                .to.be.a(\"string\")\n                .that.equals(`<html ${stringifiedHtmlAttributes}></html>`);\n        });\n\n        it(\"renders html attributes as string\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <html lang=\"ga\" className=\"myClassName\" />\n                </Helmet>,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.htmlAttributes).to.exist;\n            expect(head.htmlAttributes).to.respondTo(\"toString\");\n\n            expect(head.htmlAttributes.toString())\n                .to.be.a(\"string\")\n                .that.equals(stringifiedHtmlAttributes);\n        });\n\n        it(\"renders body attributes as component\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <body lang=\"ga\" className=\"myClassName\" />\n                </Helmet>,\n                container\n            );\n\n            const {bodyAttributes} = Helmet.rewind();\n            const attrs = bodyAttributes.toComponent();\n\n            expect(attrs).to.exist;\n\n            const markup = ReactServer.renderToStaticMarkup(\n                <body lang=\"en\" {...attrs} />\n            );\n\n            expect(markup)\n                .to.be.a(\"string\")\n                .that.equals(`<body ${stringifiedBodyAttributes}></body>`);\n        });\n\n        it(\"renders body attributes as string\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <body lang=\"ga\" className=\"myClassName\" />\n                </Helmet>,\n                container\n            );\n\n            const body = Helmet.rewind();\n\n            expect(body.bodyAttributes).to.exist;\n            expect(body.bodyAttributes).to.respondTo(\"toString\");\n\n            expect(body.bodyAttributes.toString())\n                .to.be.a(\"string\")\n                .that.equals(stringifiedBodyAttributes);\n        });\n\n        it(\"does not encode all characters with HTML character entity equivalents\", () => {\n            const chineseTitle = \"膣膗 鍆錌雔\";\n            const stringifiedChineseTitle = `<title ${HELMET_ATTRIBUTE}=\"true\">${chineseTitle}</title>`;\n\n            ReactDOM.render(\n                <div>\n                    <Helmet>\n                        <title>{chineseTitle}</title>\n                    </Helmet>\n                </div>,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.title).to.exist;\n            expect(head.title).to.respondTo(\"toString\");\n\n            expect(head.title.toString())\n                .to.be.a(\"string\")\n                .that.equals(stringifiedChineseTitle);\n        });\n\n        it(\"rewind() provides a fallback object for empty Helmet state\", () => {\n            ReactDOM.render(<div />, container);\n\n            const head = Helmet.rewind();\n\n            expect(head.htmlAttributes).to.exist;\n            expect(head.htmlAttributes).to.respondTo(\"toString\");\n            expect(head.htmlAttributes.toString()).to.equal(\"\");\n            expect(head.htmlAttributes).to.respondTo(\"toComponent\");\n            expect(head.htmlAttributes.toComponent()).to.be.an(\"object\").that.is\n                .empty;\n\n            expect(head.title).to.exist;\n            expect(head.title).to.respondTo(\"toString\");\n            expect(head.title.toString()).to.equal(\n                `<title ${HELMET_ATTRIBUTE}=\"true\"></title>`\n            );\n            expect(head.title).to.respondTo(\"toComponent\");\n\n            const markup = ReactServer.renderToStaticMarkup(\n                <div>{head.title.toComponent()}</div>\n            );\n\n            expect(markup)\n                .to.be.a(\"string\")\n                .that.equals(\n                    `<div><title ${HELMET_ATTRIBUTE}=\"true\"></title></div>`\n                );\n\n            expect(head.base).to.exist;\n            expect(head.base).to.respondTo(\"toString\");\n            expect(head.base.toString()).to.equal(\"\");\n            expect(head.base).to.respondTo(\"toComponent\");\n            expect(head.base.toComponent()).to.be.an(\"array\").that.is.empty;\n\n            expect(head.meta).to.exist;\n            expect(head.meta).to.respondTo(\"toString\");\n            expect(head.meta.toString()).to.equal(\"\");\n            expect(head.meta).to.respondTo(\"toComponent\");\n            expect(head.meta.toComponent()).to.be.an(\"array\").that.is.empty;\n\n            expect(head.link).to.exist;\n            expect(head.link).to.respondTo(\"toString\");\n            expect(head.link.toString()).to.equal(\"\");\n            expect(head.link).to.respondTo(\"toComponent\");\n            expect(head.link.toComponent()).to.be.an(\"array\").that.is.empty;\n\n            expect(head.script).to.exist;\n            expect(head.script).to.respondTo(\"toString\");\n            expect(head.script.toString()).to.equal(\"\");\n            expect(head.script).to.respondTo(\"toComponent\");\n            expect(head.script.toComponent()).to.be.an(\"array\").that.is.empty;\n\n            expect(head.noscript).to.exist;\n            expect(head.noscript).to.respondTo(\"toString\");\n            expect(head.noscript.toString()).to.equal(\"\");\n            expect(head.noscript).to.respondTo(\"toComponent\");\n            expect(head.noscript.toComponent()).to.be.an(\"array\").that.is.empty;\n\n            expect(head.style).to.exist;\n            expect(head.style).to.respondTo(\"toString\");\n            expect(head.style.toString()).to.equal(\"\");\n            expect(head.style).to.respondTo(\"toComponent\");\n            expect(head.style.toComponent()).to.be.an(\"array\").that.is.empty;\n        });\n\n        it(\"does not render undefined attribute values\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <script src=\"foo.js\" async={undefined} />\n                </Helmet>,\n                container\n            );\n\n            const {script} = Helmet.rewind();\n            const stringifiedScriptTag = script.toString();\n\n            expect(stringifiedScriptTag)\n                .to.be.a(\"string\")\n                .that.equals(\n                    `<script ${HELMET_ATTRIBUTE}=\"true\" src=\"foo.js\" async></script>`\n                );\n        });\n\n        context(\"renderStatic\", () => {\n            it(\"does html encode title\", () => {\n                ReactDOM.render(\n                    <Helmet>\n                        <title>{`Dangerous <script> include`}</title>\n                    </Helmet>,\n                    container\n                );\n\n                const head = Helmet.renderStatic();\n\n                expect(head.title).to.exist;\n                expect(head.title).to.respondTo(\"toString\");\n\n                expect(head.title.toString()).to.equal(stringifiedTitle);\n            });\n\n            it(\"renders title as React component\", () => {\n                ReactDOM.render(\n                    <Helmet>\n                        <title>{`Dangerous <script> include`}</title>\n                    </Helmet>,\n                    container\n                );\n\n                const head = Helmet.renderStatic();\n\n                expect(head.title).to.exist;\n                expect(head.title).to.respondTo(\"toComponent\");\n\n                const titleComponent = head.title.toComponent();\n\n                expect(titleComponent)\n                    .to.be.an(\"array\")\n                    .that.has.length.of(1);\n\n                titleComponent.forEach(title => {\n                    expect(title)\n                        .to.be.an(\"object\")\n                        .that.contains.property(\"type\", \"title\");\n                });\n\n                const markup = ReactServer.renderToStaticMarkup(\n                    <div>{titleComponent}</div>\n                );\n\n                expect(markup)\n                    .to.be.a(\"string\")\n                    .that.equals(`<div>${stringifiedTitle}</div>`);\n            });\n        });\n\n        after(() => {\n            Helmet.canUseDOM = true;\n        });\n    });\n\n    describe(\"misc\", () => {\n        it(\"throws in rewind() when a DOM is present\", () => {\n            ReactDOM.render(\n                <Helmet>\n                    <title>Fancy title</title>\n                </Helmet>,\n                container\n            );\n\n            expect(Helmet.rewind).to.throw(\n                \"You may only call rewind() on the server. Call peek() to read the current state.\"\n            );\n        });\n\n        it(\"lets you read current state in peek() whether or not a DOM is present\", done => {\n            ReactDOM.render(\n                <Helmet>\n                    <title>Fancy title</title>\n                </Helmet>,\n                container\n            );\n\n            requestAnimationFrame(() => {\n                expect(Helmet.peek().title).to.be.equal(\"Fancy title\");\n                Helmet.canUseDOM = false;\n                expect(Helmet.peek().title).to.be.equal(\"Fancy title\");\n                Helmet.canUseDOM = true;\n\n                done();\n            });\n        });\n\n        it(\"encodes special characters\", done => {\n            ReactDOM.render(\n                <Helmet>\n                    <meta\n                        name=\"description\"\n                        content={'This is \"quoted\" text and & and \\'.'}\n                    />\n                </Helmet>,\n                container\n            );\n\n            requestAnimationFrame(() => {\n                const existingTags = headElement.querySelectorAll(\n                    `meta[${HELMET_ATTRIBUTE}]`\n                );\n                const existingTag = existingTags[0];\n\n                expect(existingTags).to.not.equal(undefined);\n\n                expect(existingTags.length).to.be.equal(1);\n\n                expect(existingTags)\n                    .to.have.deep.property(\"[0]\")\n                    .that.is.an.instanceof(Element);\n                expect(existingTag).to.have.property(\"getAttribute\");\n                expect(existingTag.getAttribute(\"name\")).to.equal(\n                    \"description\"\n                );\n                expect(existingTag.getAttribute(\"content\")).to.equal(\n                    'This is \"quoted\" text and & and \\'.'\n                );\n                expect(existingTag.outerHTML).to.equal(\n                    `<meta name=\"description\" content=\"This is &quot;quoted&quot; text and &amp; and '.\" ${HELMET_ATTRIBUTE}=\"true\">`\n                );\n\n                done();\n            });\n        });\n\n        it(\"does not change the DOM if it recevies identical props\", done => {\n            const spy = sinon.spy();\n            ReactDOM.render(\n                <Helmet onChangeClientState={spy}>\n                    <meta name=\"description\" content=\"Test description\" />\n                    <title>Test Title</title>\n                </Helmet>,\n                container\n            );\n\n            requestAnimationFrame(() => {\n                // Re-rendering will pass new props to an already mounted Helmet\n                ReactDOM.render(\n                    <Helmet onChangeClientState={spy}>\n                        <meta name=\"description\" content=\"Test description\" />\n                        <title>Test Title</title>\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(spy.callCount).to.equal(1);\n\n                    done();\n                });\n            });\n        });\n\n        it(\"does not write the DOM if the client and server are identical\", done => {\n            headElement.innerHTML = `<script ${HELMET_ATTRIBUTE}=\"true\" src=\"http://localhost/test.js\" type=\"text/javascript\" />`;\n\n            const spy = sinon.spy();\n            ReactDOM.render(\n                <Helmet onChangeClientState={spy}>\n                    <script\n                        src=\"http://localhost/test.js\"\n                        type=\"text/javascript\"\n                    />\n                </Helmet>,\n                container\n            );\n\n            requestAnimationFrame(() => {\n                expect(spy.called).to.equal(true);\n\n                const [, addedTags, removedTags] = spy.getCall(0).args;\n\n                expect(addedTags).to.be.empty;\n                expect(removedTags).to.be.empty;\n\n                done();\n            });\n        });\n\n        it(\"only adds new tags and preserves tags when rendering additional Helmet instances\", done => {\n            const spy = sinon.spy();\n            let addedTags;\n            let removedTags;\n            ReactDOM.render(\n                <Helmet onChangeClientState={spy}>\n                    <link\n                        href=\"http://localhost/style.css\"\n                        rel=\"stylesheet\"\n                        type=\"text/css\"\n                    />\n                    <meta name=\"description\" content=\"Test description\" />\n                </Helmet>,\n                container\n            );\n\n            requestAnimationFrame(() => {\n                expect(spy.called).to.equal(true);\n                addedTags = spy.getCall(0).args[1];\n                removedTags = spy.getCall(0).args[2];\n\n                expect(addedTags).to.have.property(\"metaTags\");\n                expect(addedTags.metaTags).to.have.deep.property(\"[0]\");\n                expect(addedTags.metaTags[0].outerHTML).to.equal(\n                    `<meta name=\"description\" content=\"Test description\" data-react-helmet=\"true\">`\n                );\n                expect(addedTags).to.have.property(\"linkTags\");\n                expect(addedTags.linkTags).to.have.deep.property(\"[0]\");\n                expect(addedTags.linkTags[0].outerHTML).to.equal(\n                    `<link href=\"http://localhost/style.css\" rel=\"stylesheet\" type=\"text/css\" data-react-helmet=\"true\">`\n                );\n                expect(removedTags).to.be.empty;\n\n                // Re-rendering will pass new props to an already mounted Helmet\n                ReactDOM.render(\n                    <Helmet onChangeClientState={spy}>\n                        <link\n                            href=\"http://localhost/style.css\"\n                            rel=\"stylesheet\"\n                            type=\"text/css\"\n                        />\n                        <link\n                            href=\"http://localhost/style2.css\"\n                            rel=\"stylesheet\"\n                            type=\"text/css\"\n                        />\n                        <meta name=\"description\" content=\"New description\" />\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(spy.callCount).to.equal(2);\n                    addedTags = spy.getCall(1).args[1];\n                    removedTags = spy.getCall(1).args[2];\n\n                    expect(addedTags).to.have.property(\"metaTags\");\n                    expect(addedTags.metaTags).to.have.deep.property(\"[0]\");\n                    expect(addedTags.metaTags[0].outerHTML).to.equal(\n                        `<meta name=\"description\" content=\"New description\" data-react-helmet=\"true\">`\n                    );\n                    expect(addedTags).to.have.property(\"linkTags\");\n                    expect(addedTags.linkTags).to.have.deep.property(\"[0]\");\n                    expect(addedTags.linkTags[0].outerHTML).to.equal(\n                        `<link href=\"http://localhost/style2.css\" rel=\"stylesheet\" type=\"text/css\" data-react-helmet=\"true\">`\n                    );\n                    expect(removedTags).to.have.property(\"metaTags\");\n                    expect(removedTags.metaTags).to.have.deep.property(\"[0]\");\n                    expect(removedTags.metaTags[0].outerHTML).to.equal(\n                        `<meta name=\"description\" content=\"Test description\" data-react-helmet=\"true\">`\n                    );\n                    expect(removedTags).to.not.have.property(\"linkTags\");\n\n                    done();\n                });\n            });\n        });\n\n        it(\"does not accept nested Helmets\", done => {\n            const warn = sinon.stub(console, \"warn\");\n\n            ReactDOM.render(\n                <Helmet>\n                    <title>Test Title</title>\n                    <Helmet>\n                        <title>Title you will never see</title>\n                    </Helmet>\n                </Helmet>,\n                container\n            );\n\n            requestAnimationFrame(() => {\n                expect(document.title).to.equal(\"Test Title\");\n                expect(warn.called).to.be.true;\n\n                const [warning] = warn.getCall(0).args;\n                expect(warning).to.equal(\n                    \"You may be attempting to nest <Helmet> components within each other, which is not allowed. Refer to our API for more information.\"\n                );\n\n                warn.restore();\n\n                done();\n            });\n        });\n\n        it(\"warns on invalid elements\", done => {\n            const warn = sinon.stub(console, \"warn\");\n\n            ReactDOM.render(\n                <Helmet>\n                    <title>Test Title</title>\n                    <div>\n                        <title>Title you will never see</title>\n                    </div>\n                </Helmet>,\n                container\n            );\n\n            requestAnimationFrame(() => {\n                expect(document.title).to.equal(\"Test Title\");\n                expect(warn.called).to.be.true;\n\n                const [warning] = warn.getCall(0).args;\n                expect(warning).to.equal(\n                    \"Only elements types base, body, head, html, link, meta, noscript, script, style, title are allowed. Helmet does not support rendering <div> elements. Refer to our API for more information.\"\n                );\n\n                warn.restore();\n                done();\n            });\n        });\n\n        it(\"warns on invalid self-closing elements\", done => {\n            const warn = sinon.stub(console, \"warn\");\n\n            ReactDOM.render(\n                <Helmet>\n                    <title>Test Title</title>\n                    <div customAttribute={true} />\n                </Helmet>,\n                container\n            );\n\n            requestAnimationFrame(() => {\n                expect(document.title).to.equal(\"Test Title\");\n                expect(warn.called).to.be.true;\n\n                const [warning] = warn.getCall(0).args;\n                expect(warning).to.equal(\n                    \"Only elements types base, body, head, html, link, meta, noscript, script, style, title are allowed. Helmet does not support rendering <div> elements. Refer to our API for more information.\"\n                );\n\n                warn.restore();\n                done();\n            });\n        });\n\n        // TODO: Successfully test error cases with React 16.x\n        it.skip(\"throws on invalid strings as children\", () => {\n            const renderInvalid = () =>\n                ReactDOM.render(\n                    <Helmet>\n                        <title>Test Title</title>\n                        <link\n                            href=\"http://localhost/helmet\"\n                            rel=\"canonical\"\n                        >{`test`}</link>\n                    </Helmet>,\n                    container\n                );\n\n            expect(renderInvalid).to.throw(\n                Error,\n                \"<link /> elements are self-closing and can not contain children. Refer to our API for more information.\"\n            );\n        });\n\n        // TODO: Successfully test error cases with React 16.x\n        it.skip(\"throws on invalid children\", () => {\n            const renderInvalid = () =>\n                ReactDOM.render(\n                    <Helmet>\n                        <title>Test Title</title>\n                        <script>\n                            <title>Title you will never see</title>\n                        </script>\n                    </Helmet>,\n                    container\n                );\n\n            expect(renderInvalid).to.throw(\n                Error,\n                \"Helmet expects a string as a child of <script>. Did you forget to wrap your children in braces? ( <script>{``}</script> ) Refer to our API for more information.\"\n            );\n        });\n\n        it(\"handles undefined children\", done => {\n            const charSet = undefined;\n\n            ReactDOM.render(\n                <Helmet>\n                    {charSet && <meta charSet={charSet} />}\n                    <title>Test Title</title>\n                </Helmet>,\n                container\n            );\n\n            requestAnimationFrame(() => {\n                expect(document.title).to.equal(\"Test Title\");\n\n                done();\n            });\n        });\n\n        it(\"recognizes valid tags regardless of attribute ordering\", done => {\n            ReactDOM.render(\n                <Helmet>\n                    <meta content=\"Test Description\" name=\"description\" />\n                </Helmet>,\n                container\n            );\n\n            requestAnimationFrame(() => {\n                const existingTags = headElement.querySelectorAll(\n                    `meta[${HELMET_ATTRIBUTE}]`\n                );\n                const existingTag = existingTags[0];\n\n                expect(existingTags).to.not.equal(undefined);\n\n                expect(existingTags.length).to.be.equal(1);\n\n                expect(existingTags)\n                    .to.have.deep.property(\"[0]\")\n                    .that.is.an.instanceof(Element);\n                expect(existingTag).to.have.property(\"getAttribute\");\n                expect(existingTag.getAttribute(\"name\")).to.equal(\n                    \"description\"\n                );\n                expect(existingTag.getAttribute(\"content\")).to.equal(\n                    \"Test Description\"\n                );\n                expect(existingTag.outerHTML).to.equal(\n                    `<meta content=\"Test Description\" name=\"description\" ${HELMET_ATTRIBUTE}=\"true\">`\n                );\n\n                done();\n            });\n        });\n\n        it(\"requestAnimationFrame works as expected\", done => {\n            requestAnimationFrame(cb => {\n                expect(cb).to.exist;\n                expect(cb).to.be.a(\"number\");\n\n                done();\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "test/HelmetTest.js",
    "content": "/* eslint max-nested-callbacks: [1, 7] */\n/* eslint-disable import/no-named-as-default */\n\nimport React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport ReactServer from \"react-dom/server\";\nimport {Helmet} from \"../src/Helmet\";\nimport {requestAnimationFrame} from \"../src/HelmetUtils.js\";\n\nconst HELMET_ATTRIBUTE = \"data-react-helmet\";\n\ndescribe(\"Helmet\", () => {\n    let headElement;\n\n    const container = document.createElement(\"div\");\n\n    beforeEach(() => {\n        headElement =\n            headElement || document.head || document.querySelector(\"head\");\n\n        // resets DOM after each run\n        headElement.innerHTML = \"\";\n    });\n\n    afterEach(() => {\n        ReactDOM.unmountComponentAtNode(container);\n    });\n\n    describe(\"api\", () => {\n        describe(\"title\", () => {\n            it(\"updates page title\", done => {\n                ReactDOM.render(\n                    <Helmet defaultTitle={\"Fallback\"} title={\"Test Title\"} />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\"Test Title\");\n\n                    done();\n                });\n            });\n\n            it(\"updates page title with multiple children\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet title={\"Test Title\"} />\n                        <Helmet title={\"Child One Title\"} />\n                        <Helmet title={\"Child Two Title\"} />\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\"Child Two Title\");\n\n                    done();\n                });\n            });\n\n            it(\"sets title based on deepest nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet title={\"Main Title\"} />\n                        <div>\n                            <Helmet title={\"Nested Title\"} />\n                        </div>\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\"Nested Title\");\n\n                    done();\n                });\n            });\n\n            it(\"sets title using deepest nested component with a defined title\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet title={\"Main Title\"} />\n                        <Helmet />\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\"Main Title\");\n\n                    done();\n                });\n            });\n\n            it(\"uses defaultTitle if no title is defined\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        defaultTitle={\"Fallback\"}\n                        title={\"\"}\n                        titleTemplate={\n                            \"This is a %s of the titleTemplate feature\"\n                        }\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\"Fallback\");\n\n                    done();\n                });\n            });\n\n            it(\"uses a titleTemplate and a child <title>\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        defaultTitle={\"Fallback\"}\n                        titleTemplate={\n                            \"This is a %s of the titleTemplate feature\"\n                        }\n                    >\n                        <title>Test</title>\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\n                        \"This is a Test of the titleTemplate feature\"\n                    );\n                    done();\n                });\n            });\n\n            it(\"uses a titleTemplate and a child <title> via a template?\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        defaultTitle={\"Fallback\"}\n                        titleTemplate={\n                            \"This is a %s of the titleTemplate feature\"\n                        }\n                    >\n                        <title>{`${\"Test\"}`}</title>\n                    </Helmet>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\n                        \"This is a Test of the titleTemplate feature\"\n                    );\n                    done();\n                });\n            });\n\n            it(\"uses a titleTemplate if defined\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        defaultTitle={\"Fallback\"}\n                        title={\"Test\"}\n                        titleTemplate={\n                            \"This is a %s of the titleTemplate feature\"\n                        }\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\n                        \"This is a Test of the titleTemplate feature\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"replaces multiple title strings in titleTemplate\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        title={\"Test\"}\n                        titleTemplate={\n                            \"This is a %s of the titleTemplate feature. Another %s.\"\n                        }\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\n                        \"This is a Test of the titleTemplate feature. Another Test.\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"uses a titleTemplate based on deepest nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet\n                            title={\"Test\"}\n                            titleTemplate={\n                                \"This is a %s of the titleTemplate feature\"\n                            }\n                        />\n                        <Helmet\n                            title={\"Second Test\"}\n                            titleTemplate={\n                                \"A %s using nested titleTemplate attributes\"\n                            }\n                        />\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\n                        \"A Second Test using nested titleTemplate attributes\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"merges deepest component title with nearest upstream titleTemplate\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet\n                            title={\"Test\"}\n                            titleTemplate={\n                                \"This is a %s of the titleTemplate feature\"\n                            }\n                        />\n                        <Helmet title={\"Second Test\"} />\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\n                        \"This is a Second Test of the titleTemplate feature\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"renders dollar characters in a title correctly when titleTemplate present\", done => {\n                const dollarTitle = \"te$t te$$t te$$$t te$$$$t\";\n\n                ReactDOM.render(\n                    <Helmet\n                        title={dollarTitle}\n                        titleTemplate={\"This is a %s\"}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(\n                        \"This is a te$t te$$t te$$$t te$$$$t\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"does not encode all characters with HTML character entity equivalents\", done => {\n                const chineseTitle = \"膣膗 鍆錌雔\";\n\n                ReactDOM.render(\n                    <div>\n                        <Helmet title={chineseTitle} />\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(document.title).to.equal(chineseTitle);\n\n                    done();\n                });\n            });\n\n            it(\"page title with prop itemprop\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        defaultTitle={\"Fallback\"}\n                        title={\"Test Title with itemProp\"}\n                        titleAttributes={{itemprop: \"name\"}}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const titleTag = document.getElementsByTagName(\"title\")[0];\n                    expect(document.title).to.equal(\"Test Title with itemProp\");\n                    expect(titleTag.getAttribute(\"itemprop\")).to.equal(\"name\");\n\n                    done();\n                });\n            });\n        });\n\n        describe(\"title attributes\", () => {\n            beforeEach(() => {\n                headElement.innerHTML = `<title>Test Title</title>`;\n            });\n\n            it(\"update title attributes\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        titleAttributes={{\n                            itemprop: \"name\"\n                        }}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const titleTag = document.getElementsByTagName(\"title\")[0];\n                    expect(titleTag.getAttribute(\"itemprop\")).to.equal(\"name\");\n                    expect(titleTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                        \"itemprop\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"sets attributes based on the deepest nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet\n                            titleAttributes={{\n                                lang: \"en\",\n                                hidden: undefined\n                            }}\n                        />\n                        <Helmet\n                            titleAttributes={{\n                                lang: \"ja\"\n                            }}\n                        />\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const titleTag = document.getElementsByTagName(\"title\")[0];\n                    expect(titleTag.getAttribute(\"lang\")).to.equal(\"ja\");\n                    expect(titleTag.getAttribute(\"hidden\")).to.equal(\"\");\n                    expect(titleTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                        \"lang,hidden\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"handles valueless attributes\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        titleAttributes={{\n                            hidden: undefined\n                        }}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const titleTag = document.getElementsByTagName(\"title\")[0];\n                    expect(titleTag.getAttribute(\"hidden\")).to.equal(\"\");\n                    expect(titleTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                        \"hidden\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"clears title attributes that are handled within helmet\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        titleAttributes={{\n                            lang: \"en\",\n                            hidden: undefined\n                        }}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(<Helmet />, container);\n\n                    requestAnimationFrame(() => {\n                        const titleTag = document.getElementsByTagName(\n                            \"title\"\n                        )[0];\n                        expect(titleTag.getAttribute(\"lang\")).to.be.null;\n                        expect(titleTag.getAttribute(\"hidden\")).to.be.null;\n                        expect(\n                            titleTag.getAttribute(HELMET_ATTRIBUTE)\n                        ).to.equal(null);\n\n                        done();\n                    });\n                });\n            });\n        });\n\n        describe(\"html attributes\", () => {\n            it(\"updates html attributes\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        htmlAttributes={{\n                            class: \"myClassName\",\n                            lang: \"en\"\n                        }}\n                        lang=\"en\"\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const htmlTag = document.getElementsByTagName(\"html\")[0];\n                    expect(htmlTag.getAttribute(\"class\")).to.equal(\n                        \"myClassName\"\n                    );\n                    expect(htmlTag.getAttribute(\"lang\")).to.equal(\"en\");\n                    expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                        \"class,lang\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"sets attributes based on the deepest nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet\n                            htmlAttributes={{\n                                lang: \"en\"\n                            }}\n                        />\n                        <Helmet\n                            htmlAttributes={{\n                                lang: \"ja\"\n                            }}\n                        />\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const htmlTag = document.getElementsByTagName(\"html\")[0];\n                    expect(htmlTag.getAttribute(\"lang\")).to.equal(\"ja\");\n                    expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                        \"lang\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"handles valueless attributes\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        htmlAttributes={{\n                            amp: undefined\n                        }}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const htmlTag = document.getElementsByTagName(\"html\")[0];\n                    expect(htmlTag.getAttribute(\"amp\")).to.equal(\"\");\n                    expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                        \"amp\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"clears html attributes that are handled within helmet\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        htmlAttributes={{\n                            lang: \"en\",\n                            amp: undefined\n                        }}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(<Helmet />, container);\n\n                    requestAnimationFrame(() => {\n                        const htmlTag = document.getElementsByTagName(\n                            \"html\"\n                        )[0];\n                        expect(htmlTag.getAttribute(\"lang\")).to.be.null;\n                        expect(htmlTag.getAttribute(\"amp\")).to.be.null;\n                        expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                            null\n                        );\n\n                        done();\n                    });\n                });\n            });\n\n            it(\"updates with multiple additions and removals - overwrite and new\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        htmlAttributes={{\n                            lang: \"en\",\n                            amp: undefined\n                        }}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(\n                        <Helmet\n                            htmlAttributes={{\n                                lang: \"ja\",\n                                id: \"html-tag\",\n                                title: \"html tag\"\n                            }}\n                        />,\n                        container\n                    );\n\n                    requestAnimationFrame(() => {\n                        const htmlTag = document.getElementsByTagName(\n                            \"html\"\n                        )[0];\n                        expect(htmlTag.getAttribute(\"amp\")).to.equal(null);\n                        expect(htmlTag.getAttribute(\"lang\")).to.equal(\"ja\");\n                        expect(htmlTag.getAttribute(\"id\")).to.equal(\"html-tag\");\n                        expect(htmlTag.getAttribute(\"title\")).to.equal(\n                            \"html tag\"\n                        );\n                        expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                            \"lang,id,title\"\n                        );\n\n                        done();\n                    });\n                });\n            });\n\n            it(\"updates with multiple additions and removals - all new\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        htmlAttributes={{\n                            lang: \"en\",\n                            amp: undefined\n                        }}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(\n                        <Helmet\n                            htmlAttributes={{\n                                id: \"html-tag\",\n                                title: \"html tag\"\n                            }}\n                        />,\n                        container\n                    );\n\n                    requestAnimationFrame(() => {\n                        const htmlTag = document.getElementsByTagName(\n                            \"html\"\n                        )[0];\n                        expect(htmlTag.getAttribute(\"amp\")).to.equal(null);\n                        expect(htmlTag.getAttribute(\"lang\")).to.equal(null);\n                        expect(htmlTag.getAttribute(\"id\")).to.equal(\"html-tag\");\n                        expect(htmlTag.getAttribute(\"title\")).to.equal(\n                            \"html tag\"\n                        );\n                        expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                            \"id,title\"\n                        );\n\n                        done();\n                    });\n                });\n            });\n\n            context(\"initialized outside of helmet\", () => {\n                before(() => {\n                    const htmlTag = document.getElementsByTagName(\"html\")[0];\n                    htmlTag.setAttribute(\"test\", \"test\");\n                });\n\n                it(\"attributes are not cleared\", done => {\n                    ReactDOM.render(<Helmet />, container);\n\n                    requestAnimationFrame(() => {\n                        const htmlTag = document.getElementsByTagName(\n                            \"html\"\n                        )[0];\n                        expect(htmlTag.getAttribute(\"test\")).to.equal(\"test\");\n                        expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                            null\n                        );\n\n                        done();\n                    });\n                });\n\n                it(\"attributes are overwritten if specified in helmet\", done => {\n                    ReactDOM.render(\n                        <Helmet\n                            htmlAttributes={{\n                                test: \"helmet-attr\"\n                            }}\n                        />,\n                        container\n                    );\n\n                    requestAnimationFrame(() => {\n                        const htmlTag = document.getElementsByTagName(\n                            \"html\"\n                        )[0];\n                        expect(htmlTag.getAttribute(\"test\")).to.equal(\n                            \"helmet-attr\"\n                        );\n                        expect(htmlTag.getAttribute(HELMET_ATTRIBUTE)).to.equal(\n                            \"test\"\n                        );\n\n                        done();\n                    });\n                });\n\n                it(\"attributes are cleared once managed in helmet\", done => {\n                    ReactDOM.render(\n                        <Helmet\n                            htmlAttributes={{\n                                test: \"helmet-attr\"\n                            }}\n                        />,\n                        container\n                    );\n\n                    requestAnimationFrame(() => {\n                        ReactDOM.render(<Helmet />, container);\n\n                        requestAnimationFrame(() => {\n                            const htmlTag = document.getElementsByTagName(\n                                \"html\"\n                            )[0];\n                            expect(htmlTag.getAttribute(\"test\")).to.equal(null);\n                            expect(\n                                htmlTag.getAttribute(HELMET_ATTRIBUTE)\n                            ).to.equal(null);\n\n                            done();\n                        });\n                    });\n                });\n            });\n        });\n\n        describe(\"onChangeClientState\", () => {\n            it(\"when handling client state change, calls the function with new state, addedTags and removedTags \", done => {\n                const spy = sinon.spy();\n                ReactDOM.render(\n                    <div>\n                        <Helmet\n                            base={{href: \"http://mysite.com/\"}}\n                            link={[\n                                {\n                                    href: \"http://localhost/helmet\",\n                                    rel: \"canonical\"\n                                }\n                            ]}\n                            meta={[{charset: \"utf-8\"}]}\n                            script={[\n                                {\n                                    src: \"http://localhost/test.js\",\n                                    type: \"text/javascript\"\n                                }\n                            ]}\n                            title={\"Main Title\"}\n                            onChangeClientState={spy}\n                        />\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(spy.called).to.equal(true);\n                    const newState = spy.getCall(0).args[0];\n                    const addedTags = spy.getCall(0).args[1];\n                    const removedTags = spy.getCall(0).args[2];\n\n                    expect(newState).to.contain({title: \"Main Title\"});\n                    expect(newState.baseTag).to.contain({\n                        href: \"http://mysite.com/\"\n                    });\n                    expect(newState.metaTags).to.contain({charset: \"utf-8\"});\n                    expect(newState.linkTags).to.contain({\n                        href: \"http://localhost/helmet\",\n                        rel: \"canonical\"\n                    });\n                    expect(newState.scriptTags).to.contain({\n                        src: \"http://localhost/test.js\",\n                        type: \"text/javascript\"\n                    });\n\n                    expect(addedTags).to.have.property(\"baseTag\");\n                    expect(addedTags.baseTag).to.have.deep.property(\"[0]\");\n                    expect(addedTags.baseTag[0].outerHTML).to.equal(\n                        `<base href=\"http://mysite.com/\" data-react-helmet=\"true\">`\n                    );\n\n                    expect(addedTags).to.have.property(\"metaTags\");\n                    expect(addedTags.metaTags).to.have.deep.property(\"[0]\");\n                    expect(addedTags.metaTags[0].outerHTML).to.equal(\n                        `<meta charset=\"utf-8\" data-react-helmet=\"true\">`\n                    );\n\n                    expect(addedTags).to.have.property(\"linkTags\");\n                    expect(addedTags.linkTags).to.have.deep.property(\"[0]\");\n                    expect(addedTags.linkTags[0].outerHTML).to.equal(\n                        `<link href=\"http://localhost/helmet\" rel=\"canonical\" data-react-helmet=\"true\">`\n                    );\n\n                    expect(addedTags).to.have.property(\"scriptTags\");\n                    expect(addedTags.scriptTags).to.have.deep.property(\"[0]\");\n                    expect(addedTags.scriptTags[0].outerHTML).to.equal(\n                        `<script src=\"http://localhost/test.js\" type=\"text/javascript\" data-react-helmet=\"true\"></script>`\n                    );\n\n                    expect(removedTags).to.be.empty;\n\n                    done();\n                });\n            });\n\n            it(\"calls the deepest defined callback with the deepest state\", done => {\n                const spy = sinon.spy();\n                ReactDOM.render(\n                    <div>\n                        <Helmet\n                            title={\"Main Title\"}\n                            onChangeClientState={spy}\n                        />\n                        <Helmet title={\"Deeper Title\"} />\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(spy.callCount).to.equal(1);\n                    expect(spy.getCall(0).args[0]).to.contain({\n                        title: \"Deeper Title\"\n                    });\n\n                    done();\n                });\n            });\n        });\n\n        describe(\"base tag\", () => {\n            it(\"updates base tag with href property\", done => {\n                ReactDOM.render(\n                    <Helmet base={{href: \"http://mysite.com/\"}} />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const existingTags = headElement.querySelectorAll(\n                        `base[${HELMET_ATTRIBUTE}]`\n                    );\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    const filteredTags = [].slice\n                        .call(existingTags)\n                        .filter(tag => {\n                            return (\n                                tag.getAttribute(\"href\") ===\n                                \"http://mysite.com/\"\n                            );\n                        });\n\n                    expect(filteredTags.length).to.equal(1);\n\n                    done();\n                });\n            });\n\n            it(\"updates base tag with target property\", done => {\n                ReactDOM.render(\n                    <Helmet base={{target: \"_blank\"}} />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const existingTags = headElement.querySelectorAll(\n                        `base[${HELMET_ATTRIBUTE}]`\n                    );\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    const filteredTags = [].slice\n                        .call(existingTags)\n                        .filter(tag => {\n                            return tag.getAttribute(\"target\") === \"_blank\";\n                        });\n\n                    expect(filteredTags.length).to.equal(1);\n\n                    done();\n                });\n            });\n\n            it(\"clears the base tag if one is not specified\", done => {\n                ReactDOM.render(\n                    <Helmet base={{href: \"http://mysite.com/\"}} />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(<Helmet />, container);\n\n                    requestAnimationFrame(() => {\n                        const existingTags = headElement.querySelectorAll(\n                            `base[${HELMET_ATTRIBUTE}]`\n                        );\n\n                        expect(existingTags).to.not.equal(undefined);\n                        expect(existingTags.length).to.equal(0);\n\n                        done();\n                    });\n                });\n            });\n\n            it(\"tags without 'href' or 'target' are not accepted\", done => {\n                ReactDOM.render(\n                    <Helmet base={{property: \"won't work\"}} />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const existingTags = headElement.querySelectorAll(\n                        `base[${HELMET_ATTRIBUTE}]`\n                    );\n\n                    expect(existingTags).to.not.equal(undefined);\n                    expect(existingTags.length).to.equal(0);\n\n                    done();\n                });\n            });\n\n            it(\"sets base tag based on deepest nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet base={{href: \"http://mysite.com/\"}} />\n                        <Helmet\n                            base={{\n                                href: \"http://mysite.com/public\",\n                                target: \"_parent\"\n                            }}\n                        />\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const existingTags = headElement.querySelectorAll(\n                        `base[${HELMET_ATTRIBUTE}]`\n                    );\n                    const firstTag = Array.prototype.slice.call(\n                        existingTags\n                    )[0];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.be.equal(1);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"href\")).to.equal(\n                        \"http://mysite.com/public\"\n                    );\n                    expect(firstTag.getAttribute(\"target\")).to.equal(\"_parent\");\n                    expect(firstTag.outerHTML).to.equal(\n                        `<base href=\"http://mysite.com/public\" target=\"_parent\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"does not render tag when primary attribute is null\", done => {\n                ReactDOM.render(<Helmet base={{href: undefined}} />, container);\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `base[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    expect(existingTags).to.be.empty;\n\n                    done();\n                });\n            });\n        });\n\n        describe(\"meta tags\", () => {\n            it(\"updates meta tags\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        meta={[\n                            {charset: \"utf-8\"},\n                            {\n                                name: \"description\",\n                                content: \"Test description\"\n                            },\n                            {\n                                \"http-equiv\": \"content-type\",\n                                content: \"text/html\"\n                            },\n                            {property: \"og:type\", content: \"article\"},\n                            {itemprop: \"name\", content: \"Test name itemprop\"}\n                        ]}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `meta[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    const filteredTags = [].slice\n                        .call(existingTags)\n                        .filter(tag => {\n                            return (\n                                tag.getAttribute(\"charset\") === \"utf-8\" ||\n                                (tag.getAttribute(\"name\") === \"description\" &&\n                                    tag.getAttribute(\"content\") ===\n                                        \"Test description\") ||\n                                (tag.getAttribute(\"http-equiv\") ===\n                                    \"content-type\" &&\n                                    tag.getAttribute(\"content\") ===\n                                        \"text/html\") ||\n                                (tag.getAttribute(\"itemprop\") === \"name\" &&\n                                    tag.getAttribute(\"content\") ===\n                                        \"Test name itemprop\")\n                            );\n                        });\n\n                    expect(filteredTags.length).to.be.at.least(4);\n\n                    done();\n                });\n            });\n\n            it(\"clears all meta tags if none are specified\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        meta={[\n                            {name: \"description\", content: \"Test description\"}\n                        ]}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(<Helmet />, container);\n\n                    requestAnimationFrame(() => {\n                        const existingTags = headElement.querySelectorAll(\n                            `meta[${HELMET_ATTRIBUTE}]`\n                        );\n\n                        expect(existingTags).to.not.equal(undefined);\n                        expect(existingTags.length).to.equal(0);\n\n                        done();\n                    });\n                });\n            });\n\n            it(\"tags without 'name', 'http-equiv', 'property', 'charset', or 'itemprop' are not accepted\", done => {\n                ReactDOM.render(\n                    <Helmet meta={[{href: \"won't work\"}]} />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const existingTags = headElement.querySelectorAll(\n                        `meta[${HELMET_ATTRIBUTE}]`\n                    );\n\n                    expect(existingTags).to.not.equal(undefined);\n                    expect(existingTags.length).to.equal(0);\n\n                    done();\n                });\n            });\n\n            it(\"sets meta tags based on deepest nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet\n                            meta={[\n                                {charset: \"utf-8\"},\n                                {\n                                    name: \"description\",\n                                    content: \"Test description\"\n                                }\n                            ]}\n                        />\n                        <Helmet\n                            meta={[\n                                {\n                                    name: \"description\",\n                                    content: \"Inner description\"\n                                },\n                                {name: \"keywords\", content: \"test,meta,tags\"}\n                            ]}\n                        />\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `meta[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n\n                    const firstTag = existingTags[0];\n                    const secondTag = existingTags[1];\n                    const thirdTag = existingTags[2];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.be.equal(3);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"charset\")).to.equal(\"utf-8\");\n                    expect(firstTag.outerHTML).to.equal(\n                        `<meta charset=\"utf-8\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[1]\")\n                        .that.is.an.instanceof(Element);\n                    expect(secondTag).to.have.property(\"getAttribute\");\n                    expect(secondTag.getAttribute(\"name\")).to.equal(\n                        \"description\"\n                    );\n                    expect(secondTag.getAttribute(\"content\")).to.equal(\n                        \"Inner description\"\n                    );\n                    expect(secondTag.outerHTML).to.equal(\n                        `<meta name=\"description\" content=\"Inner description\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[2]\")\n                        .that.is.an.instanceof(Element);\n                    expect(thirdTag).to.have.property(\"getAttribute\");\n                    expect(thirdTag.getAttribute(\"name\")).to.equal(\"keywords\");\n                    expect(thirdTag.getAttribute(\"content\")).to.equal(\n                        \"test,meta,tags\"\n                    );\n                    expect(thirdTag.outerHTML).to.equal(\n                        `<meta name=\"keywords\" content=\"test,meta,tags\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"allows duplicate meta tags if specified in the same component\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        meta={[\n                            {\n                                name: \"description\",\n                                content: \"Test description\"\n                            },\n                            {\n                                name: \"description\",\n                                content: \"Duplicate description\"\n                            }\n                        ]}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `meta[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n                    const secondTag = existingTags[1];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.equal(2);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"name\")).to.equal(\n                        \"description\"\n                    );\n                    expect(firstTag.getAttribute(\"content\")).to.equal(\n                        \"Test description\"\n                    );\n                    expect(firstTag.outerHTML).to.equal(\n                        `<meta name=\"description\" content=\"Test description\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[1]\")\n                        .that.is.an.instanceof(Element);\n                    expect(secondTag).to.have.property(\"getAttribute\");\n                    expect(secondTag.getAttribute(\"name\")).to.equal(\n                        \"description\"\n                    );\n                    expect(secondTag.getAttribute(\"content\")).to.equal(\n                        \"Duplicate description\"\n                    );\n                    expect(secondTag.outerHTML).to.equal(\n                        `<meta name=\"description\" content=\"Duplicate description\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"overrides duplicate meta tags with single meta tag in a nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet\n                            meta={[\n                                {\n                                    name: \"description\",\n                                    content: \"Test description\"\n                                },\n                                {\n                                    name: \"description\",\n                                    content: \"Duplicate description\"\n                                }\n                            ]}\n                        />\n                        <Helmet\n                            meta={[\n                                {\n                                    name: \"description\",\n                                    content: \"Inner description\"\n                                }\n                            ]}\n                        />\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `meta[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.equal(1);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"name\")).to.equal(\n                        \"description\"\n                    );\n                    expect(firstTag.getAttribute(\"content\")).to.equal(\n                        \"Inner description\"\n                    );\n                    expect(firstTag.outerHTML).to.equal(\n                        `<meta name=\"description\" content=\"Inner description\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"overrides single meta tag with duplicate meta tags in a nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet\n                            meta={[\n                                {\n                                    name: \"description\",\n                                    content: \"Test description\"\n                                }\n                            ]}\n                        />\n                        <Helmet\n                            meta={[\n                                {\n                                    name: \"description\",\n                                    content: \"Inner description\"\n                                },\n                                {\n                                    name: \"description\",\n                                    content: \"Inner duplicate description\"\n                                }\n                            ]}\n                        />\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `meta[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n                    const secondTag = existingTags[1];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.equal(2);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"name\")).to.equal(\n                        \"description\"\n                    );\n                    expect(firstTag.getAttribute(\"content\")).to.equal(\n                        \"Inner description\"\n                    );\n                    expect(firstTag.outerHTML).to.equal(\n                        `<meta name=\"description\" content=\"Inner description\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[1]\")\n                        .that.is.an.instanceof(Element);\n                    expect(secondTag).to.have.property(\"getAttribute\");\n                    expect(secondTag.getAttribute(\"name\")).to.equal(\n                        \"description\"\n                    );\n                    expect(secondTag.getAttribute(\"content\")).to.equal(\n                        \"Inner duplicate description\"\n                    );\n                    expect(secondTag.outerHTML).to.equal(\n                        `<meta name=\"description\" content=\"Inner duplicate description\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"does not render tag when primary attribute is null\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        meta={[\n                            {\n                                name: undefined,\n                                content: \"Inner duplicate description\"\n                            }\n                        ]}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `meta[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    expect(existingTags).to.be.empty;\n\n                    done();\n                });\n            });\n\n            it(\"fails gracefully when meta is wrong shape\", done => {\n                const error = sinon.stub(console, \"error\");\n                const warn = sinon.stub(console, \"warn\");\n\n                ReactDOM.render(\n                    <Helmet meta={{name: \"title\", content: \"some title\"}} />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `meta[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    expect(existingTags).to.be.empty;\n\n                    expect(error.called).to.be.true;\n                    expect(warn.called).to.be.true;\n\n                    const [warning] = warn.getCall(0).args;\n                    expect(warning).to.equal(\n                        `Helmet: meta should be of type \"Array\". Instead found type \"object\"`\n                    );\n\n                    error.restore();\n                    warn.restore();\n\n                    done();\n                });\n            });\n        });\n\n        describe(\"link tags\", () => {\n            it(\"updates link tags\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        link={[\n                            {\n                                href: \"http://localhost/helmet\",\n                                rel: \"canonical\"\n                            },\n                            {\n                                href: \"http://localhost/style.css\",\n                                rel: \"stylesheet\",\n                                type: \"text/css\"\n                            }\n                        ]}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `link[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    const filteredTags = [].slice\n                        .call(existingTags)\n                        .filter(tag => {\n                            return (\n                                (tag.getAttribute(\"href\") ===\n                                    \"http://localhost/style.css\" &&\n                                    tag.getAttribute(\"rel\") === \"stylesheet\" &&\n                                    tag.getAttribute(\"type\") === \"text/css\") ||\n                                (tag.getAttribute(\"href\") ===\n                                    \"http://localhost/helmet\" &&\n                                    tag.getAttribute(\"rel\") === \"canonical\")\n                            );\n                        });\n\n                    expect(filteredTags.length).to.be.at.least(2);\n\n                    done();\n                });\n            });\n\n            it(\"clears all link tags if none are specified\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        link={[\n                            {\n                                href: \"http://localhost/helmet\",\n                                rel: \"canonical\"\n                            }\n                        ]}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(<Helmet />, container);\n\n                    requestAnimationFrame(() => {\n                        const tagNodes = headElement.querySelectorAll(\n                            `link[${HELMET_ATTRIBUTE}]`\n                        );\n                        const existingTags = Array.prototype.slice.call(\n                            tagNodes\n                        );\n\n                        expect(existingTags).to.not.equal(undefined);\n                        expect(existingTags.length).to.equal(0);\n\n                        done();\n                    });\n                });\n            });\n\n            it(\"tags without 'href' or 'rel' are not accepted, even if they are valid for other tags\", done => {\n                ReactDOM.render(\n                    <Helmet link={[{\"http-equiv\": \"won't work\"}]} />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `link[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n\n                    expect(existingTags).to.not.equal(undefined);\n                    expect(existingTags.length).to.equal(0);\n\n                    done();\n                });\n            });\n\n            it(\"tags 'rel' and 'href' properly use 'rel' as the primary identification for this tag, regardless of ordering\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet\n                            link={[\n                                {\n                                    href: \"http://localhost/helmet\",\n                                    rel: \"canonical\"\n                                }\n                            ]}\n                        />\n                        <Helmet\n                            link={[\n                                {\n                                    rel: \"canonical\",\n                                    href: \"http://localhost/helmet/new\"\n                                }\n                            ]}\n                        />\n                        <Helmet\n                            link={[\n                                {\n                                    href: \"http://localhost/helmet/newest\",\n                                    rel: \"canonical\"\n                                }\n                            ]}\n                        />\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `link[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.equal(1);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"rel\")).to.equal(\"canonical\");\n                    expect(firstTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/helmet/newest\"\n                    );\n                    expect(firstTag.outerHTML).to.equal(\n                        `<link href=\"http://localhost/helmet/newest\" rel=\"canonical\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"tags with rel='stylesheet' uses the href as the primary identification of the tag, regardless of ordering\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet\n                            link={[\n                                {\n                                    href: \"http://localhost/style.css\",\n                                    rel: \"stylesheet\",\n                                    type: \"text/css\",\n                                    media: \"all\"\n                                }\n                            ]}\n                        />\n                        <Helmet\n                            link={[\n                                {\n                                    rel: \"stylesheet\",\n                                    href: \"http://localhost/inner.css\",\n                                    type: \"text/css\",\n                                    media: \"all\"\n                                }\n                            ]}\n                        />\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `link[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n                    const secondTag = existingTags[1];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.equal(2);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/style.css\"\n                    );\n                    expect(firstTag.getAttribute(\"rel\")).to.equal(\"stylesheet\");\n                    expect(firstTag.getAttribute(\"type\")).to.equal(\"text/css\");\n                    expect(firstTag.getAttribute(\"media\")).to.equal(\"all\");\n                    expect(firstTag.outerHTML).to.equal(\n                        `<link href=\"http://localhost/style.css\" rel=\"stylesheet\" type=\"text/css\" media=\"all\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[1]\")\n                        .that.is.an.instanceof(Element);\n                    expect(secondTag).to.have.property(\"getAttribute\");\n                    expect(secondTag.getAttribute(\"rel\")).to.equal(\n                        \"stylesheet\"\n                    );\n                    expect(secondTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/inner.css\"\n                    );\n                    expect(secondTag.getAttribute(\"type\")).to.equal(\"text/css\");\n                    expect(secondTag.getAttribute(\"media\")).to.equal(\"all\");\n                    expect(secondTag.outerHTML).to.equal(\n                        `<link rel=\"stylesheet\" href=\"http://localhost/inner.css\" type=\"text/css\" media=\"all\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"sets link tags based on deepest nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet\n                            link={[\n                                {\n                                    rel: \"canonical\",\n                                    href: \"http://localhost/helmet\"\n                                },\n                                {\n                                    href: \"http://localhost/style.css\",\n                                    rel: \"stylesheet\",\n                                    type: \"text/css\",\n                                    media: \"all\"\n                                }\n                            ]}\n                        />\n                        <Helmet\n                            link={[\n                                {\n                                    rel: \"canonical\",\n                                    href:\n                                        \"http://localhost/helmet/innercomponent\"\n                                },\n                                {\n                                    href: \"http://localhost/inner.css\",\n                                    rel: \"stylesheet\",\n                                    type: \"text/css\",\n                                    media: \"all\"\n                                }\n                            ]}\n                        />\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `link[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n                    const secondTag = existingTags[1];\n                    const thirdTag = existingTags[2];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.be.at.least(2);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/style.css\"\n                    );\n                    expect(firstTag.getAttribute(\"rel\")).to.equal(\"stylesheet\");\n                    expect(firstTag.getAttribute(\"type\")).to.equal(\"text/css\");\n                    expect(firstTag.getAttribute(\"media\")).to.equal(\"all\");\n                    expect(firstTag.outerHTML).to.equal(\n                        `<link href=\"http://localhost/style.css\" rel=\"stylesheet\" type=\"text/css\" media=\"all\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[1]\")\n                        .that.is.an.instanceof(Element);\n                    expect(secondTag).to.have.property(\"getAttribute\");\n                    expect(secondTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/helmet/innercomponent\"\n                    );\n                    expect(secondTag.getAttribute(\"rel\")).to.equal(\"canonical\");\n                    expect(secondTag.outerHTML).to.equal(\n                        `<link rel=\"canonical\" href=\"http://localhost/helmet/innercomponent\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[2]\")\n                        .that.is.an.instanceof(Element);\n                    expect(thirdTag).to.have.property(\"getAttribute\");\n                    expect(thirdTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/inner.css\"\n                    );\n                    expect(thirdTag.getAttribute(\"rel\")).to.equal(\"stylesheet\");\n                    expect(thirdTag.getAttribute(\"type\")).to.equal(\"text/css\");\n                    expect(thirdTag.getAttribute(\"media\")).to.equal(\"all\");\n                    expect(thirdTag.outerHTML).to.equal(\n                        `<link href=\"http://localhost/inner.css\" rel=\"stylesheet\" type=\"text/css\" media=\"all\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"allows duplicate link tags if specified in the same component\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        link={[\n                            {\n                                rel: \"canonical\",\n                                href: \"http://localhost/helmet\"\n                            },\n                            {\n                                rel: \"canonical\",\n                                href: \"http://localhost/helmet/component\"\n                            }\n                        ]}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `link[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n                    const secondTag = existingTags[1];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.be.at.least(2);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"rel\")).to.equal(\"canonical\");\n                    expect(firstTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/helmet\"\n                    );\n                    expect(firstTag.outerHTML).to.equal(\n                        `<link rel=\"canonical\" href=\"http://localhost/helmet\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[1]\")\n                        .that.is.an.instanceof(Element);\n                    expect(secondTag).to.have.property(\"getAttribute\");\n                    expect(secondTag.getAttribute(\"rel\")).to.equal(\"canonical\");\n                    expect(secondTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/helmet/component\"\n                    );\n                    expect(secondTag.outerHTML).to.equal(\n                        `<link rel=\"canonical\" href=\"http://localhost/helmet/component\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"overrides duplicate link tags with a single link tag in a nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet\n                            link={[\n                                {\n                                    rel: \"canonical\",\n                                    href: \"http://localhost/helmet\"\n                                },\n                                {\n                                    rel: \"canonical\",\n                                    href: \"http://localhost/helmet/component\"\n                                }\n                            ]}\n                        />\n                        <Helmet\n                            link={[\n                                {\n                                    rel: \"canonical\",\n                                    href:\n                                        \"http://localhost/helmet/innercomponent\"\n                                }\n                            ]}\n                        />\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `link[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.be.equal(1);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"rel\")).to.equal(\"canonical\");\n                    expect(firstTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/helmet/innercomponent\"\n                    );\n                    expect(firstTag.outerHTML).to.equal(\n                        `<link rel=\"canonical\" href=\"http://localhost/helmet/innercomponent\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"overrides single link tag with duplicate link tags in a nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet\n                            link={[\n                                {\n                                    rel: \"canonical\",\n                                    href: \"http://localhost/helmet\"\n                                }\n                            ]}\n                        />\n                        <Helmet\n                            link={[\n                                {\n                                    rel: \"canonical\",\n                                    href: \"http://localhost/helmet/component\"\n                                },\n                                {\n                                    rel: \"canonical\",\n                                    href:\n                                        \"http://localhost/helmet/innercomponent\"\n                                }\n                            ]}\n                        />\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `link[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n                    const secondTag = existingTags[1];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.be.equal(2);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"rel\")).to.equal(\"canonical\");\n                    expect(firstTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/helmet/component\"\n                    );\n                    expect(firstTag.outerHTML).to.equal(\n                        `<link rel=\"canonical\" href=\"http://localhost/helmet/component\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[1]\")\n                        .that.is.an.instanceof(Element);\n                    expect(secondTag).to.have.property(\"getAttribute\");\n                    expect(secondTag.getAttribute(\"rel\")).to.equal(\"canonical\");\n                    expect(secondTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/helmet/innercomponent\"\n                    );\n                    expect(secondTag.outerHTML).to.equal(\n                        `<link rel=\"canonical\" href=\"http://localhost/helmet/innercomponent\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"does not render tag when primary attribute is null\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        link={[\n                            {rel: \"icon\", sizes: \"192x192\", href: null},\n                            {\n                                rel: \"canonical\",\n                                href: \"http://localhost/helmet/component\"\n                            }\n                        ]}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `link[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n\n                    expect(existingTags).to.not.equal(undefined);\n                    expect(existingTags.length).to.be.equal(1);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"rel\")).to.equal(\"canonical\");\n                    expect(firstTag.getAttribute(\"href\")).to.equal(\n                        \"http://localhost/helmet/component\"\n                    );\n                    expect(firstTag.outerHTML).to.equal(\n                        `<link rel=\"canonical\" href=\"http://localhost/helmet/component\" ${HELMET_ATTRIBUTE}=\"true\">`\n                    );\n\n                    done();\n                });\n            });\n        });\n\n        describe(\"script tags\", () => {\n            it(\"updates script tags\", done => {\n                const scriptInnerHTML = `\n                  {\n                    \"@context\": \"http://schema.org\",\n                    \"@type\": \"NewsArticle\",\n                    \"url\": \"http://localhost/helmet\"\n                  }\n                `;\n                ReactDOM.render(\n                    <Helmet\n                        script={[\n                            {\n                                src: \"http://localhost/test.js\",\n                                type: \"text/javascript\"\n                            },\n                            {\n                                src: \"http://localhost/test2.js\",\n                                type: \"text/javascript\"\n                            },\n                            {\n                                type: \"application/ld+json\",\n                                innerHTML: scriptInnerHTML\n                            }\n                        ]}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const existingTags = headElement.getElementsByTagName(\n                        \"script\"\n                    );\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    const filteredTags = [].slice\n                        .call(existingTags)\n                        .filter(tag => {\n                            return (\n                                (tag.getAttribute(\"src\") ===\n                                    \"http://localhost/test.js\" &&\n                                    tag.getAttribute(\"type\") ===\n                                        \"text/javascript\") ||\n                                (tag.getAttribute(\"src\") ===\n                                    \"http://localhost/test2.js\" &&\n                                    tag.getAttribute(\"type\") ===\n                                        \"text/javascript\") ||\n                                (tag.getAttribute(\"type\") ===\n                                    \"application/ld+json\" &&\n                                    tag.innerHTML === scriptInnerHTML)\n                            );\n                        });\n\n                    expect(filteredTags.length).to.be.at.least(3);\n\n                    done();\n                });\n            });\n\n            it(\"clears all scripts tags if none are specified\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        script={[\n                            {\n                                src: \"http://localhost/test.js\",\n                                type: \"text/javascript\"\n                            }\n                        ]}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(<Helmet />, container);\n\n                    requestAnimationFrame(() => {\n                        const existingTags = headElement.querySelectorAll(\n                            `script[${HELMET_ATTRIBUTE}]`\n                        );\n\n                        expect(existingTags).to.not.equal(undefined);\n                        expect(existingTags.length).to.equal(0);\n\n                        done();\n                    });\n                });\n            });\n\n            it(\"tags without 'src' are not accepted\", done => {\n                ReactDOM.render(\n                    <Helmet script={[{property: \"won't work\"}]} />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const existingTags = headElement.querySelectorAll(\n                        `script[${HELMET_ATTRIBUTE}]`\n                    );\n\n                    expect(existingTags).to.not.equal(undefined);\n                    expect(existingTags.length).to.equal(0);\n\n                    done();\n                });\n            });\n\n            it(\"sets script tags based on deepest nested component\", done => {\n                ReactDOM.render(\n                    <div>\n                        <Helmet\n                            script={[\n                                {\n                                    src: \"http://localhost/test.js\",\n                                    type: \"text/javascript\"\n                                }\n                            ]}\n                        />\n                        <Helmet\n                            script={[\n                                {\n                                    src: \"http://localhost/test2.js\",\n                                    type: \"text/javascript\"\n                                }\n                            ]}\n                        />\n                    </div>,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `script[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    const firstTag = existingTags[0];\n                    const secondTag = existingTags[1];\n\n                    expect(existingTags).to.not.equal(undefined);\n\n                    expect(existingTags.length).to.be.at.least(2);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"src\")).to.equal(\n                        \"http://localhost/test.js\"\n                    );\n                    expect(firstTag.getAttribute(\"type\")).to.equal(\n                        \"text/javascript\"\n                    );\n                    expect(firstTag.outerHTML).to.equal(\n                        `<script src=\"http://localhost/test.js\" type=\"text/javascript\" ${HELMET_ATTRIBUTE}=\"true\"></script>`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[1]\")\n                        .that.is.an.instanceof(Element);\n                    expect(secondTag).to.have.property(\"getAttribute\");\n                    expect(secondTag.getAttribute(\"src\")).to.equal(\n                        \"http://localhost/test2.js\"\n                    );\n                    expect(secondTag.getAttribute(\"type\")).to.equal(\n                        \"text/javascript\"\n                    );\n                    expect(secondTag.outerHTML).to.equal(\n                        `<script src=\"http://localhost/test2.js\" type=\"text/javascript\" ${HELMET_ATTRIBUTE}=\"true\"></script>`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"sets undefined attribute values to empty strings\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        script={[\n                            {\n                                src: \"foo.js\",\n                                async: undefined\n                            }\n                        ]}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const existingTag = headElement.querySelector(\n                        `script[${HELMET_ATTRIBUTE}]`\n                    );\n\n                    expect(existingTag).to.not.equal(undefined);\n                    expect(existingTag.outerHTML)\n                        .to.be.a(\"string\")\n                        .that.equals(\n                            `<script src=\"foo.js\" async=\"\" ${HELMET_ATTRIBUTE}=\"true\"></script>`\n                        );\n\n                    done();\n                });\n            });\n\n            it(\"does not render tag when primary attribute (src) is null\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        script={[\n                            {\n                                src: undefined,\n                                type: \"text/javascript\"\n                            }\n                        ]}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `script[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    expect(existingTags).to.be.empty;\n\n                    done();\n                });\n            });\n\n            it(\"does not render tag when primary attribute (innerHTML) is null\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        script={[\n                            {\n                                innerHTML: undefined\n                            }\n                        ]}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `script[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    expect(existingTags).to.be.empty;\n\n                    done();\n                });\n            });\n        });\n\n        describe(\"noscript tags\", () => {\n            it(\"updates noscript tags\", done => {\n                const noscriptInnerHTML = `<link rel=\"stylesheet\" type=\"text/css\" href=\"foo.css\" />`;\n                ReactDOM.render(\n                    <Helmet\n                        noscript={[{id: \"bar\", innerHTML: noscriptInnerHTML}]}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const existingTags = headElement.getElementsByTagName(\n                        \"noscript\"\n                    );\n\n                    expect(existingTags).to.not.equal(undefined);\n                    expect(existingTags.length).to.equal(1);\n                    expect(\n                        existingTags[0].innerHTML === noscriptInnerHTML &&\n                            existingTags[0].id === \"bar\"\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"clears all noscripts tags if none are specified\", done => {\n                ReactDOM.render(<Helmet noscript={[{id: \"bar\"}]} />, container);\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(<Helmet />, container);\n\n                    requestAnimationFrame(() => {\n                        const existingTags = headElement.querySelectorAll(\n                            `script[${HELMET_ATTRIBUTE}]`\n                        );\n\n                        expect(existingTags).to.not.equal(undefined);\n                        expect(existingTags.length).to.equal(0);\n\n                        done();\n                    });\n                });\n            });\n\n            it(\"tags without 'innerHTML' are not accepted\", done => {\n                ReactDOM.render(\n                    <Helmet noscript={[{property: \"won't work\"}]} />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const existingTags = headElement.querySelectorAll(\n                        `noscript[${HELMET_ATTRIBUTE}]`\n                    );\n\n                    expect(existingTags).to.not.equal(undefined);\n                    expect(existingTags.length).to.equal(0);\n\n                    done();\n                });\n            });\n\n            it(\"does not render tag when primary attribute is null\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        noscript={[\n                            {\n                                innerHTML: undefined\n                            }\n                        ]}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `noscript[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    expect(existingTags).to.be.empty;\n\n                    done();\n                });\n            });\n        });\n\n        describe(\"style tags\", () => {\n            it(\"updates style tags\", done => {\n                const cssText1 = `\n                    body {\n                        background-color: green;\n                    }\n                `;\n                const cssText2 = `\n                    p {\n                        font-size: 12px;\n                    }\n                `;\n                ReactDOM.render(\n                    <Helmet\n                        style={[\n                            {\n                                type: \"text/css\",\n                                cssText: cssText1\n                            },\n                            {\n                                cssText: cssText2\n                            }\n                        ]}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `style[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n\n                    const [firstTag, secondTag] = existingTags;\n                    expect(existingTags).to.not.equal(undefined);\n                    expect(existingTags.length).to.be.equal(2);\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[0]\")\n                        .that.is.an.instanceof(Element);\n                    expect(firstTag).to.have.property(\"getAttribute\");\n                    expect(firstTag.getAttribute(\"type\")).to.equal(\"text/css\");\n                    expect(firstTag.innerHTML).to.equal(cssText1);\n                    expect(firstTag.outerHTML).to.equal(\n                        `<style type=\"text/css\" ${HELMET_ATTRIBUTE}=\"true\">${cssText1}</style>`\n                    );\n\n                    expect(existingTags)\n                        .to.have.deep.property(\"[1]\")\n                        .that.is.an.instanceof(Element);\n                    expect(secondTag.innerHTML).to.equal(cssText2);\n                    expect(secondTag.outerHTML).to.equal(\n                        `<style ${HELMET_ATTRIBUTE}=\"true\">${cssText2}</style>`\n                    );\n\n                    done();\n                });\n            });\n\n            it(\"clears all style tags if none are specified\", done => {\n                const cssText = `\n                    body {\n                        background-color: green;\n                    }\n                `;\n                ReactDOM.render(\n                    <Helmet\n                        style={[\n                            {\n                                type: \"text/css\",\n                                cssText\n                            }\n                        ]}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    ReactDOM.render(<Helmet />, container);\n\n                    requestAnimationFrame(() => {\n                        const existingTags = headElement.querySelectorAll(\n                            `style[${HELMET_ATTRIBUTE}]`\n                        );\n\n                        expect(existingTags).to.not.equal(undefined);\n                        expect(existingTags.length).to.equal(0);\n\n                        done();\n                    });\n                });\n            });\n\n            it(\"tags without 'cssText' are not accepted\", done => {\n                ReactDOM.render(\n                    <Helmet style={[{property: \"won't work\"}]} />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const existingTags = headElement.querySelectorAll(\n                        `style[${HELMET_ATTRIBUTE}]`\n                    );\n\n                    expect(existingTags).to.not.equal(undefined);\n                    expect(existingTags.length).to.equal(0);\n\n                    done();\n                });\n            });\n\n            it(\"does not render tag when primary attribute is null\", done => {\n                ReactDOM.render(\n                    <Helmet\n                        style={[\n                            {\n                                cssText: undefined\n                            }\n                        ]}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    const tagNodes = headElement.querySelectorAll(\n                        `style[${HELMET_ATTRIBUTE}]`\n                    );\n                    const existingTags = Array.prototype.slice.call(tagNodes);\n                    expect(existingTags).to.be.empty;\n\n                    done();\n                });\n            });\n        });\n    });\n\n    describe(\"deferred tags\", () => {\n        beforeEach(() => {\n            window.__spy__ = sinon.spy();\n        });\n\n        afterEach(() => {\n            delete window.__spy__;\n        });\n\n        it(\"executes synchronously when defer={true} and async otherwise\", done => {\n            ReactDOM.render(\n                <div>\n                    <Helmet\n                        defer={false}\n                        script={[\n                            {\n                                innerHTML: `window.__spy__(1)`\n                            }\n                        ]}\n                    />\n                    <Helmet\n                        script={[\n                            {\n                                innerHTML: `window.__spy__(2)`\n                            }\n                        ]}\n                    />\n                </div>,\n                container\n            );\n\n            expect(window.__spy__.callCount).to.equal(1);\n\n            requestAnimationFrame(() => {\n                expect(window.__spy__.callCount).to.equal(2);\n                expect(window.__spy__.args).to.deep.equal([[1], [2]]);\n                done();\n            });\n        });\n    });\n\n    describe(\"server\", () => {\n        const stringifiedHtmlAttributes = `lang=\"ga\" class=\"myClassName\"`;\n        const stringifiedTitle = `<title ${HELMET_ATTRIBUTE}=\"true\">Dangerous &lt;script&gt; include</title>`;\n        const unEncodedStringifiedTitle = `<title ${HELMET_ATTRIBUTE}=\"true\">This is text and & and '.</title>`;\n        const stringifiedTitleWithItemprop = `<title ${HELMET_ATTRIBUTE}=\"true\" itemprop=\"name\">Title with Itemprop</title>`;\n        // Separate itemprop string for the server - Per https://github.com/facebook/react/issues/12403 the server renders HTML Microdata as camel case\n        const stringifiedTitleWithItempropFromServer = `<title ${HELMET_ATTRIBUTE}=\"true\" itemProp=\"name\">Title with Itemprop</title>`;\n        const stringifiedBaseTag = `<base ${HELMET_ATTRIBUTE}=\"true\" target=\"_blank\" href=\"http://localhost/\"/>`;\n\n        const stringifiedMetaTags = [\n            `<meta ${HELMET_ATTRIBUTE}=\"true\" charset=\"utf-8\"/>`,\n            `<meta ${HELMET_ATTRIBUTE}=\"true\" name=\"description\" content=\"Test description &amp; encoding of special characters like &#x27; &quot; &gt; &lt; \\`\"/>`,\n            `<meta ${HELMET_ATTRIBUTE}=\"true\" http-equiv=\"content-type\" content=\"text/html\"/>`,\n            `<meta ${HELMET_ATTRIBUTE}=\"true\" property=\"og:type\" content=\"article\"/>`,\n            `<meta ${HELMET_ATTRIBUTE}=\"true\" itemprop=\"name\" content=\"Test name itemprop\"/>`\n        ].join(\"\");\n        // Separate string for charset and itemprop for the server - Per https://github.com/facebook/react/issues/12403 the server renders HTML Microdata as camel case\n        const stringifiedMetaTagsFromServer = [\n            `<meta ${HELMET_ATTRIBUTE}=\"true\" charSet=\"utf-8\"/>`,\n            `<meta ${HELMET_ATTRIBUTE}=\"true\" name=\"description\" content=\"Test description &amp; encoding of special characters like &#x27; &quot; &gt; &lt; \\`\"/>`,\n            `<meta ${HELMET_ATTRIBUTE}=\"true\" http-equiv=\"content-type\" content=\"text/html\"/>`,\n            `<meta ${HELMET_ATTRIBUTE}=\"true\" property=\"og:type\" content=\"article\"/>`,\n            `<meta ${HELMET_ATTRIBUTE}=\"true\" itemProp=\"name\" content=\"Test name itemprop\"/>`\n        ].join(\"\");\n\n        const stringifiedLinkTags = [\n            `<link ${HELMET_ATTRIBUTE}=\"true\" href=\"http://localhost/helmet\" rel=\"canonical\"/>`,\n            `<link ${HELMET_ATTRIBUTE}=\"true\" href=\"http://localhost/style.css\" rel=\"stylesheet\" type=\"text/css\"/>`\n        ].join(\"\");\n\n        const stringifiedScriptTags = [\n            `<script ${HELMET_ATTRIBUTE}=\"true\" src=\"http://localhost/test.js\" type=\"text/javascript\"></script>`,\n            `<script ${HELMET_ATTRIBUTE}=\"true\" src=\"http://localhost/test2.js\" type=\"text/javascript\"></script>`\n        ].join(\"\");\n\n        const stringifiedNoscriptTags = [\n            `<noscript ${HELMET_ATTRIBUTE}=\"true\" id=\"foo\"><link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\" /></noscript>`,\n            `<noscript ${HELMET_ATTRIBUTE}=\"true\" id=\"bar\"><link rel=\"stylesheet\" type=\"text/css\" href=\"/style2.css\" /></noscript>`\n        ].join(\"\");\n\n        const stringifiedStyleTags = [\n            `<style ${HELMET_ATTRIBUTE}=\"true\" type=\"text/css\">body {background-color: green;}</style>`,\n            `<style ${HELMET_ATTRIBUTE}=\"true\" type=\"text/css\">p {font-size: 12px;}</style>`\n        ].join(\"\");\n\n        before(() => {\n            Helmet.canUseDOM = false;\n        });\n\n        it(\"provides initial values if no state is found\", () => {\n            let head = Helmet.rewind();\n            head = Helmet.rewind();\n\n            expect(head.meta).to.exist;\n            expect(head.meta).to.respondTo(\"toString\");\n\n            expect(head.meta.toString()).to.equal(\"\");\n        });\n\n        it(\"encodes special characters in title\", () => {\n            ReactDOM.render(\n                <Helmet title=\"Dangerous <script> include\" />,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.title).to.exist;\n            expect(head.title).to.respondTo(\"toString\");\n\n            expect(head.title.toString()).to.equal(stringifiedTitle);\n        });\n\n        it(\"opts out of string encoding\", () => {\n            ReactDOM.render(\n                <Helmet\n                    encodeSpecialCharacters={false}\n                    title={\"This is text and & and '.\"}\n                />,\n                container\n            );\n\n            const head = Helmet.rewind();\n            expect(head.title).to.exist;\n            expect(head.title).to.respondTo(\"toString\");\n\n            expect(head.title.toString()).to.equal(unEncodedStringifiedTitle);\n        });\n\n        it(\"renders title as React component\", () => {\n            ReactDOM.render(\n                <Helmet title={\"Dangerous <script> include\"} />,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.title).to.exist;\n            expect(head.title).to.respondTo(\"toComponent\");\n\n            const titleComponent = head.title.toComponent();\n\n            expect(titleComponent)\n                .to.be.an(\"array\")\n                .that.has.length.of(1);\n\n            titleComponent.forEach(title => {\n                expect(title)\n                    .to.be.an(\"object\")\n                    .that.contains.property(\"type\", \"title\");\n            });\n\n            const markup = ReactServer.renderToStaticMarkup(\n                <div>{titleComponent}</div>\n            );\n\n            expect(markup)\n                .to.be.a(\"string\")\n                .that.equals(`<div>${stringifiedTitle}</div>`);\n        });\n\n        it(\"renders title with itemprop name as React component\", () => {\n            ReactDOM.render(\n                <Helmet\n                    title={\"Title with Itemprop\"}\n                    titleAttributes={{itemprop: \"name\"}}\n                />,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.title).to.exist;\n            expect(head.title).to.respondTo(\"toComponent\");\n\n            const titleComponent = head.title.toComponent();\n\n            expect(titleComponent)\n                .to.be.an(\"array\")\n                .that.has.length.of(1);\n\n            titleComponent.forEach(title => {\n                expect(title)\n                    .to.be.an(\"object\")\n                    .that.contains.property(\"type\", \"title\");\n            });\n\n            const markup = ReactServer.renderToStaticMarkup(\n                <div>{titleComponent}</div>\n            );\n\n            expect(markup)\n                .to.be.a(\"string\")\n                .that.equals(\n                    `<div>${stringifiedTitleWithItempropFromServer}</div>`\n                );\n        });\n\n        it(\"renders base tag as React component\", () => {\n            ReactDOM.render(\n                <Helmet base={{target: \"_blank\", href: \"http://localhost/\"}} />,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.base).to.exist;\n            expect(head.base).to.respondTo(\"toComponent\");\n\n            const baseComponent = head.base.toComponent();\n\n            expect(baseComponent)\n                .to.be.an(\"array\")\n                .that.has.length.of(1);\n\n            baseComponent.forEach(base => {\n                expect(base)\n                    .to.be.an(\"object\")\n                    .that.contains.property(\"type\", \"base\");\n            });\n\n            const markup = ReactServer.renderToStaticMarkup(\n                <div>{baseComponent}</div>\n            );\n\n            expect(markup)\n                .to.be.a(\"string\")\n                .that.equals(`<div>${stringifiedBaseTag}</div>`);\n        });\n\n        it(\"renders meta tags as React components\", () => {\n            ReactDOM.render(\n                <Helmet\n                    meta={[\n                        {charset: \"utf-8\"},\n                        {\n                            name: \"description\",\n                            content:\n                                \"Test description & encoding of special characters like ' \\\" > < `\"\n                        },\n                        {\"http-equiv\": \"content-type\", content: \"text/html\"},\n                        {property: \"og:type\", content: \"article\"},\n                        {itemprop: \"name\", content: \"Test name itemprop\"}\n                    ]}\n                />,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.meta).to.exist;\n            expect(head.meta).to.respondTo(\"toComponent\");\n\n            const metaComponent = head.meta.toComponent();\n\n            expect(metaComponent)\n                .to.be.an(\"array\")\n                .that.has.length.of(5);\n\n            metaComponent.forEach(meta => {\n                expect(meta)\n                    .to.be.an(\"object\")\n                    .that.contains.property(\"type\", \"meta\");\n            });\n\n            const markup = ReactServer.renderToStaticMarkup(\n                <div>{metaComponent}</div>\n            );\n\n            expect(markup)\n                .to.be.a(\"string\")\n                .that.equals(`<div>${stringifiedMetaTagsFromServer}</div>`);\n        });\n\n        it(\"renders link tags as React components\", () => {\n            ReactDOM.render(\n                <Helmet\n                    link={[\n                        {href: \"http://localhost/helmet\", rel: \"canonical\"},\n                        {\n                            href: \"http://localhost/style.css\",\n                            rel: \"stylesheet\",\n                            type: \"text/css\"\n                        }\n                    ]}\n                />,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.link).to.exist;\n            expect(head.link).to.respondTo(\"toComponent\");\n\n            const linkComponent = head.link.toComponent();\n\n            expect(linkComponent)\n                .to.be.an(\"array\")\n                .that.has.length.of(2);\n\n            linkComponent.forEach(link => {\n                expect(link)\n                    .to.be.an(\"object\")\n                    .that.contains.property(\"type\", \"link\");\n            });\n\n            const markup = ReactServer.renderToStaticMarkup(\n                <div>{linkComponent}</div>\n            );\n\n            expect(markup)\n                .to.be.a(\"string\")\n                .that.equals(`<div>${stringifiedLinkTags}</div>`);\n        });\n\n        it(\"renders script tags as React components\", () => {\n            ReactDOM.render(\n                <Helmet\n                    script={[\n                        {\n                            src: \"http://localhost/test.js\",\n                            type: \"text/javascript\"\n                        },\n                        {\n                            src: \"http://localhost/test2.js\",\n                            type: \"text/javascript\"\n                        }\n                    ]}\n                />,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.script).to.exist;\n            expect(head.script).to.respondTo(\"toComponent\");\n\n            const scriptComponent = head.script.toComponent();\n\n            expect(scriptComponent)\n                .to.be.an(\"array\")\n                .that.has.length.of(2);\n\n            scriptComponent.forEach(script => {\n                expect(script)\n                    .to.be.an(\"object\")\n                    .that.contains.property(\"type\", \"script\");\n            });\n\n            const markup = ReactServer.renderToStaticMarkup(\n                <div>{scriptComponent}</div>\n            );\n\n            expect(markup)\n                .to.be.a(\"string\")\n                .that.equals(`<div>${stringifiedScriptTags}</div>`);\n        });\n\n        it(\"renders noscript tags as React components\", () => {\n            ReactDOM.render(\n                <Helmet\n                    noscript={[\n                        {\n                            id: \"foo\",\n                            innerHTML:\n                                '<link rel=\"stylesheet\" type=\"text/css\" href=\"/style.css\" />'\n                        },\n                        {\n                            id: \"bar\",\n                            innerHTML:\n                                '<link rel=\"stylesheet\" type=\"text/css\" href=\"/style2.css\" />'\n                        }\n                    ]}\n                />,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.noscript).to.exist;\n            expect(head.noscript).to.respondTo(\"toComponent\");\n\n            const noscriptComponent = head.noscript.toComponent();\n\n            expect(noscriptComponent)\n                .to.be.an(\"array\")\n                .that.has.length.of(2);\n\n            noscriptComponent.forEach(noscript => {\n                expect(noscript)\n                    .to.be.an(\"object\")\n                    .that.contains.property(\"type\", \"noscript\");\n            });\n\n            const markup = ReactServer.renderToStaticMarkup(\n                <div>{noscriptComponent}</div>\n            );\n\n            expect(markup)\n                .to.be.a(\"string\")\n                .that.equals(`<div>${stringifiedNoscriptTags}</div>`);\n        });\n\n        it(\"renders style tags as React components\", () => {\n            ReactDOM.render(\n                <Helmet\n                    style={[\n                        {\n                            type: \"text/css\",\n                            cssText: `body {background-color: green;}`\n                        },\n                        {\n                            type: \"text/css\",\n                            cssText: `p {font-size: 12px;}`\n                        }\n                    ]}\n                />,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.style).to.exist;\n            expect(head.style).to.respondTo(\"toComponent\");\n\n            const styleComponent = head.style.toComponent();\n\n            expect(styleComponent)\n                .to.be.an(\"array\")\n                .that.has.length.of(2);\n\n            const markup = ReactServer.renderToStaticMarkup(\n                <div>{styleComponent}</div>\n            );\n\n            expect(markup)\n                .to.be.a(\"string\")\n                .that.equals(`<div>${stringifiedStyleTags}</div>`);\n        });\n\n        it(\"renders title tag as string\", () => {\n            ReactDOM.render(\n                <Helmet title={\"Dangerous <script> include\"} />,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.title).to.exist;\n            expect(head.title).to.respondTo(\"toString\");\n\n            expect(head.title.toString())\n                .to.be.a(\"string\")\n                .that.equals(stringifiedTitle);\n        });\n\n        it(\"renders title with itemprop name as string\", () => {\n            ReactDOM.render(\n                <Helmet\n                    title={\"Title with Itemprop\"}\n                    titleAttributes={{itemprop: \"name\"}}\n                />,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.title).to.exist;\n            expect(head.title).to.respondTo(\"toString\");\n\n            const titleString = head.title.toString();\n            expect(titleString)\n                .to.be.a(\"string\")\n                .that.equals(stringifiedTitleWithItemprop);\n        });\n\n        it(\"renders base tags as string\", () => {\n            ReactDOM.render(\n                <Helmet base={{target: \"_blank\", href: \"http://localhost/\"}} />,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.base).to.exist;\n            expect(head.base).to.respondTo(\"toString\");\n\n            expect(head.base.toString())\n                .to.be.a(\"string\")\n                .that.equals(stringifiedBaseTag);\n        });\n\n        it(\"renders meta tags as string\", () => {\n            ReactDOM.render(\n                <Helmet\n                    meta={[\n                        {charset: \"utf-8\"},\n                        {\n                            name: \"description\",\n                            content:\n                                \"Test description & encoding of special characters like ' \\\" > < `\"\n                        },\n                        {\"http-equiv\": \"content-type\", content: \"text/html\"},\n                        {property: \"og:type\", content: \"article\"},\n                        {itemprop: \"name\", content: \"Test name itemprop\"}\n                    ]}\n                />,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.meta).to.exist;\n            expect(head.meta).to.respondTo(\"toString\");\n\n            expect(head.meta.toString())\n                .to.be.a(\"string\")\n                .that.equals(stringifiedMetaTags);\n        });\n\n        it(\"renders link tags as string\", () => {\n            ReactDOM.render(\n                <Helmet\n                    link={[\n                        {href: \"http://localhost/helmet\", rel: \"canonical\"},\n                        {\n                            href: \"http://localhost/style.css\",\n                            rel: \"stylesheet\",\n                            type: \"text/css\"\n                        }\n                    ]}\n                />,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.link).to.exist;\n            expect(head.link).to.respondTo(\"toString\");\n\n            expect(head.link.toString())\n                .to.be.a(\"string\")\n                .that.equals(stringifiedLinkTags);\n        });\n\n        it(\"renders script tags as string\", () => {\n            ReactDOM.render(\n                <Helmet\n                    script={[\n                        {\n                            src: \"http://localhost/test.js\",\n                            type: \"text/javascript\"\n                        },\n                        {\n                            src: \"http://localhost/test2.js\",\n                            type: \"text/javascript\"\n                        }\n                    ]}\n                />,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.script).to.exist;\n            expect(head.script).to.respondTo(\"toString\");\n\n            expect(head.script.toString())\n                .to.be.a(\"string\")\n                .that.equals(stringifiedScriptTags);\n        });\n\n        it(\"renders style tags as string\", () => {\n            ReactDOM.render(\n                <Helmet\n                    style={[\n                        {\n                            type: \"text/css\",\n                            cssText: `body {background-color: green;}`\n                        },\n                        {\n                            type: \"text/css\",\n                            cssText: `p {font-size: 12px;}`\n                        }\n                    ]}\n                />,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.style).to.exist;\n            expect(head.style).to.respondTo(\"toString\");\n\n            expect(head.style.toString())\n                .to.be.a(\"string\")\n                .that.equals(stringifiedStyleTags);\n        });\n\n        it(\"renders html attributes as component\", () => {\n            ReactDOM.render(\n                <Helmet\n                    htmlAttributes={{\n                        lang: \"ga\",\n                        className: \"myClassName\"\n                    }}\n                />,\n                container\n            );\n\n            const {htmlAttributes} = Helmet.rewind();\n            const attrs = htmlAttributes.toComponent();\n\n            expect(attrs).to.exist;\n\n            const markup = ReactServer.renderToStaticMarkup(\n                <html lang=\"en\" {...attrs} />\n            );\n\n            expect(markup)\n                .to.be.a(\"string\")\n                .that.equals(`<html ${stringifiedHtmlAttributes}></html>`);\n        });\n\n        it(\"renders html attributes as string\", () => {\n            ReactDOM.render(\n                <Helmet\n                    htmlAttributes={{\n                        lang: \"ga\",\n                        class: \"myClassName\"\n                    }}\n                />,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.htmlAttributes).to.exist;\n            expect(head.htmlAttributes).to.respondTo(\"toString\");\n\n            expect(head.htmlAttributes.toString())\n                .to.be.a(\"string\")\n                .that.equals(stringifiedHtmlAttributes);\n        });\n\n        it(\"does not encode all characters with HTML character entity equivalents\", () => {\n            const chineseTitle = \"膣膗 鍆錌雔\";\n            const stringifiedChineseTitle = `<title ${HELMET_ATTRIBUTE}=\"true\">${chineseTitle}</title>`;\n\n            ReactDOM.render(\n                <div>\n                    <Helmet title={chineseTitle} />\n                </div>,\n                container\n            );\n\n            const head = Helmet.rewind();\n\n            expect(head.title).to.exist;\n            expect(head.title).to.respondTo(\"toString\");\n\n            expect(head.title.toString())\n                .to.be.a(\"string\")\n                .that.equals(stringifiedChineseTitle);\n        });\n\n        it(\"rewind() provides a fallback object for empty Helmet state\", () => {\n            ReactDOM.render(<div />, container);\n\n            const head = Helmet.rewind();\n\n            expect(head.htmlAttributes).to.exist;\n            expect(head.htmlAttributes).to.respondTo(\"toString\");\n            expect(head.htmlAttributes.toString()).to.equal(\"\");\n            expect(head.htmlAttributes).to.respondTo(\"toComponent\");\n            expect(head.htmlAttributes.toComponent()).to.be.an(\"object\").that.is\n                .empty;\n\n            expect(head.title).to.exist;\n            expect(head.title).to.respondTo(\"toString\");\n            expect(head.title.toString()).to.equal(\n                `<title ${HELMET_ATTRIBUTE}=\"true\"></title>`\n            );\n            expect(head.title).to.respondTo(\"toComponent\");\n\n            const markup = ReactServer.renderToStaticMarkup(\n                <div>{head.title.toComponent()}</div>\n            );\n\n            expect(markup)\n                .to.be.a(\"string\")\n                .that.equals(\n                    `<div><title ${HELMET_ATTRIBUTE}=\"true\"></title></div>`\n                );\n\n            expect(head.base).to.exist;\n            expect(head.base).to.respondTo(\"toString\");\n            expect(head.base.toString()).to.equal(\"\");\n            expect(head.base).to.respondTo(\"toComponent\");\n            expect(head.base.toComponent()).to.be.an(\"array\").that.is.empty;\n\n            expect(head.meta).to.exist;\n            expect(head.meta).to.respondTo(\"toString\");\n            expect(head.meta.toString()).to.equal(\"\");\n            expect(head.meta).to.respondTo(\"toComponent\");\n            expect(head.meta.toComponent()).to.be.an(\"array\").that.is.empty;\n\n            expect(head.link).to.exist;\n            expect(head.link).to.respondTo(\"toString\");\n            expect(head.link.toString()).to.equal(\"\");\n            expect(head.link).to.respondTo(\"toComponent\");\n            expect(head.link.toComponent()).to.be.an(\"array\").that.is.empty;\n\n            expect(head.script).to.exist;\n            expect(head.script).to.respondTo(\"toString\");\n            expect(head.script.toString()).to.equal(\"\");\n            expect(head.script).to.respondTo(\"toComponent\");\n            expect(head.script.toComponent()).to.be.an(\"array\").that.is.empty;\n\n            expect(head.noscript).to.exist;\n            expect(head.noscript).to.respondTo(\"toString\");\n            expect(head.noscript.toString()).to.equal(\"\");\n            expect(head.noscript).to.respondTo(\"toComponent\");\n            expect(head.noscript.toComponent()).to.be.an(\"array\").that.is.empty;\n\n            expect(head.style).to.exist;\n            expect(head.style).to.respondTo(\"toString\");\n            expect(head.style.toString()).to.equal(\"\");\n            expect(head.style).to.respondTo(\"toComponent\");\n            expect(head.style.toComponent()).to.be.an(\"array\").that.is.empty;\n        });\n\n        it(\"does not render undefined attribute values\", () => {\n            ReactDOM.render(\n                <Helmet\n                    script={[\n                        {\n                            src: \"foo.js\",\n                            async: undefined\n                        }\n                    ]}\n                />,\n                container\n            );\n\n            const {script} = Helmet.rewind();\n            const stringifiedScriptTag = script.toString();\n\n            expect(stringifiedScriptTag)\n                .to.be.a(\"string\")\n                .that.equals(\n                    `<script ${HELMET_ATTRIBUTE}=\"true\" src=\"foo.js\" async></script>`\n                );\n        });\n        after(() => {\n            Helmet.canUseDOM = true;\n        });\n    });\n\n    describe(\"misc\", () => {\n        it(\"throws in rewind() when a DOM is present\", () => {\n            ReactDOM.render(<Helmet title={\"Fancy title\"} />, container);\n\n            expect(Helmet.rewind).to.throw(\n                \"You may only call rewind() on the server. Call peek() to read the current state.\"\n            );\n        });\n\n        it(\"lets you read current state in peek() whether or not a DOM is present\", done => {\n            ReactDOM.render(<Helmet title={\"Fancy title\"} />, container);\n\n            requestAnimationFrame(() => {\n                expect(Helmet.peek().title).to.be.equal(\"Fancy title\");\n                Helmet.canUseDOM = false;\n                expect(Helmet.peek().title).to.be.equal(\"Fancy title\");\n                Helmet.canUseDOM = true;\n\n                done();\n            });\n        });\n\n        it(\"encodes special characters\", done => {\n            ReactDOM.render(\n                <Helmet\n                    meta={[\n                        {\n                            name: \"description\",\n                            content: 'This is \"quoted\" text and & and \\'.'\n                        }\n                    ]}\n                />,\n                container\n            );\n\n            requestAnimationFrame(() => {\n                const existingTags = headElement.querySelectorAll(\n                    `meta[${HELMET_ATTRIBUTE}]`\n                );\n                const existingTag = existingTags[0];\n\n                expect(existingTags).to.not.equal(undefined);\n\n                expect(existingTags.length).to.be.equal(1);\n\n                expect(existingTags)\n                    .to.have.deep.property(\"[0]\")\n                    .that.is.an.instanceof(Element);\n                expect(existingTag).to.have.property(\"getAttribute\");\n                expect(existingTag.getAttribute(\"name\")).to.equal(\n                    \"description\"\n                );\n                expect(existingTag.getAttribute(\"content\")).to.equal(\n                    'This is \"quoted\" text and & and \\'.'\n                );\n                expect(existingTag.outerHTML).to.equal(\n                    `<meta name=\"description\" content=\"This is &quot;quoted&quot; text and &amp; and '.\" ${HELMET_ATTRIBUTE}=\"true\">`\n                );\n\n                done();\n            });\n        });\n\n        it(\"does not change the DOM if it receives identical props\", done => {\n            const spy = sinon.spy();\n            ReactDOM.render(\n                <Helmet\n                    meta={[{name: \"description\", content: \"Test description\"}]}\n                    title={\"Test Title\"}\n                    onChangeClientState={spy}\n                />,\n                container\n            );\n\n            requestAnimationFrame(() => {\n                // Re-rendering will pass new props to an already mounted Helmet\n                ReactDOM.render(\n                    <Helmet\n                        meta={[\n                            {name: \"description\", content: \"Test description\"}\n                        ]}\n                        title={\"Test Title\"}\n                        onChangeClientState={spy}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(spy.callCount).to.equal(1);\n\n                    done();\n                });\n            });\n        });\n\n        it(\"does not write the DOM if the client and server are identical\", done => {\n            headElement.innerHTML = `<script ${HELMET_ATTRIBUTE}=\"true\" src=\"http://localhost/test.js\" type=\"text/javascript\" />`;\n\n            const spy = sinon.spy();\n            ReactDOM.render(\n                <Helmet\n                    script={[\n                        {\n                            src: \"http://localhost/test.js\",\n                            type: \"text/javascript\"\n                        }\n                    ]}\n                    onChangeClientState={spy}\n                />,\n                container\n            );\n\n            requestAnimationFrame(() => {\n                expect(spy.called).to.equal(true);\n\n                const [, addedTags, removedTags] = spy.getCall(0).args;\n\n                expect(addedTags).to.be.empty;\n                expect(removedTags).to.be.empty;\n\n                done();\n            });\n        });\n\n        it(\"only adds new tags and preserves tags when rendering additional Helmet instances\", done => {\n            const spy = sinon.spy();\n            let addedTags;\n            let removedTags;\n            ReactDOM.render(\n                <Helmet\n                    link={[\n                        {\n                            href: \"http://localhost/style.css\",\n                            rel: \"stylesheet\",\n                            type: \"text/css\"\n                        }\n                    ]}\n                    meta={[{name: \"description\", content: \"Test description\"}]}\n                    onChangeClientState={spy}\n                />,\n                container\n            );\n\n            requestAnimationFrame(() => {\n                expect(spy.called).to.equal(true);\n                addedTags = spy.getCall(0).args[1];\n                removedTags = spy.getCall(0).args[2];\n\n                expect(addedTags).to.have.property(\"metaTags\");\n                expect(addedTags.metaTags).to.have.deep.property(\"[0]\");\n                expect(addedTags.metaTags[0].outerHTML).to.equal(\n                    `<meta name=\"description\" content=\"Test description\" data-react-helmet=\"true\">`\n                );\n                expect(addedTags).to.have.property(\"linkTags\");\n                expect(addedTags.linkTags).to.have.deep.property(\"[0]\");\n                expect(addedTags.linkTags[0].outerHTML).to.equal(\n                    `<link href=\"http://localhost/style.css\" rel=\"stylesheet\" type=\"text/css\" data-react-helmet=\"true\">`\n                );\n                expect(removedTags).to.be.empty;\n\n                // Re-rendering will pass new props to an already mounted Helmet\n                ReactDOM.render(\n                    <Helmet\n                        link={[\n                            {\n                                href: \"http://localhost/style.css\",\n                                rel: \"stylesheet\",\n                                type: \"text/css\"\n                            },\n                            {\n                                href: \"http://localhost/style2.css\",\n                                rel: \"stylesheet\",\n                                type: \"text/css\"\n                            }\n                        ]}\n                        meta={[\n                            {name: \"description\", content: \"New description\"}\n                        ]}\n                        onChangeClientState={spy}\n                    />,\n                    container\n                );\n\n                requestAnimationFrame(() => {\n                    expect(spy.callCount).to.equal(2);\n                    addedTags = spy.getCall(1).args[1];\n                    removedTags = spy.getCall(1).args[2];\n\n                    expect(addedTags).to.have.property(\"metaTags\");\n                    expect(addedTags.metaTags).to.have.deep.property(\"[0]\");\n                    expect(addedTags.metaTags[0].outerHTML).to.equal(\n                        `<meta name=\"description\" content=\"New description\" data-react-helmet=\"true\">`\n                    );\n                    expect(addedTags).to.have.property(\"linkTags\");\n                    expect(addedTags.linkTags).to.have.deep.property(\"[0]\");\n                    expect(addedTags.linkTags[0].outerHTML).to.equal(\n                        `<link href=\"http://localhost/style2.css\" rel=\"stylesheet\" type=\"text/css\" data-react-helmet=\"true\">`\n                    );\n                    expect(removedTags).to.have.property(\"metaTags\");\n                    expect(removedTags.metaTags).to.have.deep.property(\"[0]\");\n                    expect(removedTags.metaTags[0].outerHTML).to.equal(\n                        `<meta name=\"description\" content=\"Test description\" data-react-helmet=\"true\">`\n                    );\n                    expect(removedTags).to.not.have.property(\"linkTags\");\n\n                    done();\n                });\n            });\n        });\n\n        it(\"does not accept nested Helmets\", done => {\n            const warn = sinon.stub(console, \"warn\");\n\n            ReactDOM.render(\n                <Helmet title={\"Test Title\"}>\n                    <Helmet title={\"Title you'll never see\"} />\n                </Helmet>,\n                container\n            );\n\n            requestAnimationFrame(() => {\n                expect(document.title).to.equal(\"Test Title\");\n                expect(warn.called).to.be.true;\n\n                const [warning] = warn.getCall(0).args;\n                expect(warning).to.equal(\n                    \"You may be attempting to nest <Helmet> components within each other, which is not allowed. Refer to our API for more information.\"\n                );\n\n                warn.restore();\n                done();\n            });\n        });\n\n        it(\"recognizes valid tags regardless of attribute ordering\", done => {\n            ReactDOM.render(\n                <Helmet\n                    meta={[{content: \"Test Description\", name: \"description\"}]}\n                />,\n                container\n            );\n\n            requestAnimationFrame(() => {\n                const existingTags = headElement.querySelectorAll(\n                    `meta[${HELMET_ATTRIBUTE}]`\n                );\n                const existingTag = existingTags[0];\n\n                expect(existingTags).to.not.equal(undefined);\n\n                expect(existingTags.length).to.be.equal(1);\n\n                expect(existingTags)\n                    .to.have.deep.property(\"[0]\")\n                    .that.is.an.instanceof(Element);\n                expect(existingTag).to.have.property(\"getAttribute\");\n                expect(existingTag.getAttribute(\"name\")).to.equal(\n                    \"description\"\n                );\n                expect(existingTag.getAttribute(\"content\")).to.equal(\n                    \"Test Description\"\n                );\n                expect(existingTag.outerHTML).to.equal(\n                    `<meta content=\"Test Description\" name=\"description\" ${HELMET_ATTRIBUTE}=\"true\">`\n                );\n\n                done();\n            });\n        });\n\n        it(\"requestAnimationFrame works as expected\", done => {\n            requestAnimationFrame(cb => {\n                expect(cb).to.exist;\n                expect(cb).to.be.a(\"number\");\n\n                done();\n            });\n        });\n    });\n});\n"
  }
]