diff --git a/core/modules/language/src/Tests/LanguageBrowserDetectionUnitTest.php b/core/modules/language/src/Tests/LanguageBrowserDetectionUnitTest.php
index f724338..2719476 100644
--- a/core/modules/language/src/Tests/LanguageBrowserDetectionUnitTest.php
+++ b/core/modules/language/src/Tests/LanguageBrowserDetectionUnitTest.php
@@ -22,141 +22,6 @@ class LanguageBrowserDetectionUnitTest extends WebTestBase {
   public static $modules = array('language');
 
   /**
-   * Unit tests for the language_from_browser() function.
-   *
-   * @see language_from_browser().
-   */
-  function testLanguageFromBrowser() {
-    // The order of the languages is only important if the browser language
-    // codes are having the same qvalue, otherwise the one with the highest
-    // qvalue is preferred. The automatically generated generic tags are always
-    // having a lower qvalue.
-
-    $languages = array(
-      // In our test case, 'en' has priority over 'en-US'.
-      'en' => new Language(array(
-        'id' => 'en',
-      )),
-      'en-US' => new Language(array(
-        'id' => 'en-US',
-      )),
-      // But 'fr-CA' has priority over 'fr'.
-      'fr-CA' => new Language(array(
-        'id' => 'fr-CA',
-      )),
-      'fr' => new Language(array(
-        'id' => 'fr',
-      )),
-      // 'es-MX' is alone.
-      'es-MX' => new Language(array(
-        'id' => 'es-MX',
-      )),
-      // 'pt' is alone.
-      'pt' => new Language(array(
-        'id' => 'pt',
-      )),
-      // Language codes with more then one dash are actually valid.
-      // eh-oh-laa-laa is the official language code of the Teletubbies.
-      'eh-oh-laa-laa' => new Language(array(
-        'id' => 'eh-oh-laa-laa',
-      )),
-      // Chinese languages.
-      'zh-hans' => new Language(array(
-        'id' => 'zh-hans',
-      )),
-      'zh-hant' => new Language(array(
-        'id' => 'zh-hant',
-      )),
-      'zh-hant-tw' => new Language(array(
-        'id' => 'zh-hant',
-      )),
-    );
-
-    $test_cases = array(
-      // Equal qvalue for each language, choose the site preferred one.
-      'en,en-US,fr-CA,fr,es-MX' => 'en',
-      'en-US,en,fr-CA,fr,es-MX' => 'en',
-      'fr,en' => 'en',
-      'en,fr' => 'en',
-      'en-US,fr' => 'en-US',
-      'fr,en-US' => 'en-US',
-      'fr,fr-CA' => 'fr-CA',
-      'fr-CA,fr' => 'fr-CA',
-      'fr' => 'fr-CA',
-      'fr;q=1' => 'fr-CA',
-      'fr,es-MX' => 'fr-CA',
-      'fr,es' => 'fr-CA',
-      'es,fr' => 'fr-CA',
-      'es-MX,de' => 'es-MX',
-      'de,es-MX' => 'es-MX',
-
-      // Different cases and whitespace.
-      'en' => 'en',
-      'En' => 'en',
-      'EN' => 'en',
-      ' en' => 'en',
-      'en ' => 'en',
-      'en, fr' => 'en',
-
-      // A less specific language from the browser matches a more specific one
-      // from the website, and the other way around for compatibility with
-      // some versions of Internet Explorer.
-      'es' => 'es-MX',
-      'es-MX' => 'es-MX',
-      'pt' => 'pt',
-      'pt-PT' => 'pt',
-      'pt-PT;q=0.5,pt-BR;q=1,en;q=0.7' => 'en',
-      'pt-PT;q=1,pt-BR;q=0.5,en;q=0.7' => 'en',
-      'pt-PT;q=0.4,pt-BR;q=0.1,en;q=0.7' => 'en',
-      'pt-PT;q=0.1,pt-BR;q=0.4,en;q=0.7' => 'en',
-
-      // Language code with several dashes are valid. The less specific language
-      // from the browser matches the more specific one from the website.
-      'eh-oh-laa-laa' => 'eh-oh-laa-laa',
-      'eh-oh-laa' => 'eh-oh-laa-laa',
-      'eh-oh' => 'eh-oh-laa-laa',
-      'eh' => 'eh-oh-laa-laa',
-
-      // Different qvalues.
-      'fr,en;q=0.5' => 'fr-CA',
-      'fr,en;q=0.5,fr-CA;q=0.25' => 'fr',
-
-      // Silly wildcards are also valid.
-      '*,fr-CA;q=0.5' => 'en',
-      '*,en;q=0.25' => 'fr-CA',
-      'en,en-US;q=0.5,fr;q=0.25' => 'en',
-      'en-US,en;q=0.5,fr;q=0.25' => 'en-US',
-
-      // Unresolvable cases.
-      '' => FALSE,
-      'de,pl' => FALSE,
-      'iecRswK4eh' => FALSE,
-      $this->randomMachineName(10) => FALSE,
-
-      // Chinese langcodes.
-      'zh-cn, en-us;q=0.90, en;q=0.80, zh;q=0.70' => 'zh-hans',
-      'zh-tw, en-us;q=0.90, en;q=0.80, zh;q=0.70' => 'zh-hant',
-      'zh-hant, en-us;q=0.90, en;q=0.80, zh;q=0.70' => 'zh-hant',
-      'zh-hans, en-us;q=0.90, en;q=0.80, zh;q=0.70' => 'zh-hans',
-      'zh-cn' => 'zh-hans',
-      'zh-sg' => 'zh-hans',
-      'zh-tw' => 'zh-hant',
-      'zh-hk' => 'zh-hant',
-      'zh-mo' => 'zh-hant',
-      'zh-hans' => 'zh-hans',
-      'zh-hant' => 'zh-hant',
-      'zh-chs' => 'zh-hans',
-      'zh-cht' => 'zh-hant',
-    );
-
-    $mappings = $this->container->get('config.factory')->get('language.mappings')->get();
-    foreach ($test_cases as $accept_language => $expected_result) {
-      $result = UserAgent::getBestMatchingLangcode($accept_language, array_keys($languages), $mappings);
-      $this->assertIdentical($result, $expected_result, format_string("Language selection '@accept-language' selects '@result', result = '@actual'", array('@accept-language' => $accept_language, '@result' => $expected_result, '@actual' => isset($result) ? $result : 'none')));
-    }
-  }
-
-  /**
    * Tests for adding, editing and deleting mappings between browser language
    * codes and Drupal language codes.
    */
diff --git a/core/tests/Drupal/Tests/Component/Utility/HtmlTest.php b/core/tests/Drupal/Tests/Component/Utility/HtmlTest.php
new file mode 100644
index 0000000..6e15893
--- /dev/null
+++ b/core/tests/Drupal/Tests/Component/Utility/HtmlTest.php
@@ -0,0 +1,89 @@
+<?php
+
+/**
+ * @file
+ * Container Drupal\Tests\Component\Utility\UserAgentTest
+ */
+
+namespace Drupal\Tests\Component\Utility;
+
+use Drupal\Component\Utility\Html;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * Tests the http query methods.
+ *
+ * @group Utility
+ *
+ * @coversDefaultClass \Drupal\Component\Utility\Html
+ */
+class HtmlTest extends UnitTestCase {
+
+  /**
+   * Test HTML document loading.
+   *
+   * @dataProvider providerTestLoad
+   * @covers ::load
+   *
+   * @param string $html
+   *   Original HTML.
+   * @param array $tags
+   *   A list of tags to find. Key is tag, value is number instances.
+   */
+  public function testLoad($html, $tags) {
+    $doc = Html::load($html);
+    // If we have a document we did our job.
+    $this->assertTrue(is_a($doc, '\DOMDocument'));
+
+    foreach ($tags as $tag_name => $length) {
+      $tag = $doc->getElementsByTagName($tag_name);
+      $this->assertEquals($length, $tag->length);
+    }
+  }
+
+  /**
+   * Test HTML document serialization.
+   *
+   * @dataProvider providerTestLoad
+   * @covers ::serialize
+   *
+   * @param string $html
+   *   Original HTML.
+   * @param array $tags
+   *   A list of tags to find. Key is tag, value is number instances.
+   * @param $expected
+   *   Expected serialized value.
+   */
+  public function testSerialize($html, $tags, $expected) {
+    $doc = Html::load($html);
+    $this->assertEquals($expected, Html::serialize($doc));
+  }
+
+  public function providerTestLoad() {
+    return array(
+      array('<a>', array('a' => 1), '<a></a>'),
+      array('<a href>', array('a' => 1), '<a href=""></a>'),
+      // Bad html
+      array('<div><something></something><something></something></some>', array('div' => 1, 'something' => 2), '<div><something></something><something></something></div>'),
+      array('<astring', array('astring' => 1), '<astring></astring>'),
+    );
+  }
+
+  /**
+   * Test HTML normalization.
+   *
+   * @dataProvider providerTestLoad
+   * @covers ::normalize
+   *
+   * @param string $html
+   *   Original HTML.
+   * @param array $tags
+   *   A list of tags to find. Key is tag, value is number instances.
+   * @param $expected
+   *   Expected normalized value.
+   */
+  public function testNormalize($html, $tags, $expected) {
+    $this->assertEquals($expected, Html::normalize($html));
+  }
+
+}
diff --git a/core/tests/Drupal/Tests/Component/Utility/UserAgentTest.php b/core/tests/Drupal/Tests/Component/Utility/UserAgentTest.php
new file mode 100644
index 0000000..3256587
--- /dev/null
+++ b/core/tests/Drupal/Tests/Component/Utility/UserAgentTest.php
@@ -0,0 +1,165 @@
+<?php
+
+/**
+ * @file
+ * Container Drupal\Tests\Component\Utility\UserAgentTest
+ */
+
+namespace Drupal\Tests\Component\Utility;
+
+use Drupal\Component\Utility\UserAgent;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * Tests bytes size parsing helper methods.
+ *
+ * @group Utility
+ *
+ * @coversDefaultClass \Drupal\Component\Utility\UserAgent
+ */
+class UserAgentTest extends UnitTestCase {
+
+  /**
+   * Helper method to supply language codes to testGetBestMatchingLangcode().
+   *
+   * @return array
+   *   Language codes, ordered by priority.
+   */
+  protected function getLanguages() {
+    return array(
+      // In our test case, 'en' has priority over 'en-US'.
+      'en',
+      'en-US',
+      // But 'fr-CA' has priority over 'fr'.
+      'fr-CA',
+      'fr',
+      // 'es-MX' is alone.
+      'es-MX',
+      // 'pt' is alone.
+      'pt',
+      // Language codes with more then one dash are actually valid.
+      // eh-oh-laa-laa is the official language code of the Teletubbies.
+      'eh-oh-laa-laa',
+      // Chinese languages.
+      'zh-hans',
+      'zh-hant',
+      'zh-hant-tw',
+    );
+  }
+
+  /**
+   * Helper method to supply language mappings to testGetBestMatchingLangcode().
+   *
+   * @return array
+   *   Language mappings.
+   */
+  protected function getMappings() {
+    return array(
+      'no' => 'nb',
+      'pt' => 'pt-pt',
+      'zh' => 'zh-hans',
+      'zh-tw' => 'zh-hant',
+      'zh-hk' => 'zh-hant',
+      'zh-mo' => 'zh-hant',
+      'zh-cht' => 'zh-hant',
+      'zh-cn' => 'zh-hans',
+      'zh-sg' => 'zh-hans',
+      'zh-chs' => 'zh-hans',
+    );
+  }
+
+  /**
+   * Test matching language from user agent.
+   *
+   * @dataProvider providerTestGetBestMatchingLangcode
+   * @covers ::getBestMatchingLangcode
+   */
+  public function testGetBestMatchingLangcode($accept_language, $expected) {
+    $result = UserAgent::getBestMatchingLangcode($accept_language, $this->getLanguages(), $this->getMappings());
+    $this->assertSame($expected, $result, $accept_language);
+  }
+
+  public function providerTestGetBestMatchingLangcode() {
+    return array(
+      // Equal qvalue for each language, choose the site preferred one.
+      array('en,en-US,fr-CA,fr,es-MX', 'en'),
+      array('en-US,en,fr-CA,fr,es-MX', 'en'),
+      array('fr,en', 'en'),
+      array('en,fr', 'en'),
+      array('en-US,fr', 'en-US'),
+      array('fr,en-US', 'en-US'),
+      array('fr,fr-CA', 'fr-CA'),
+      array('fr-CA,fr', 'fr-CA'),
+      array('fr', 'fr-CA'),
+      array('fr;q=1', 'fr-CA'),
+      array('fr,es-MX', 'fr-CA'),
+      array('fr,es', 'fr-CA'),
+      array('es,fr', 'fr-CA'),
+      array('es-MX,de', 'es-MX'),
+      array('de,es-MX', 'es-MX'),
+
+      // Different cases and whitespace.
+      array('en', 'en'),
+      array('En', 'en'),
+      array('EN', 'en'),
+      array(' en', 'en'),
+      array('en ', 'en'),
+      array('en, fr', 'en'),
+
+      // A less specific language from the browser matches a more specific one
+      // from the website, and the other way around for compatibility with
+      // some versions of Internet Explorer.
+      array('es', 'es-MX'),
+      array('es-MX', 'es-MX'),
+      array('pt', 'pt'),
+      array('pt-PT', 'pt'),
+      array('pt-PT;q=0.5,pt-BR;q=1,en;q=0.7', 'en'),
+      array('pt-PT;q=1,pt-BR;q=0.5,en;q=0.7', 'en'),
+      array('pt-PT;q=0.4,pt-BR;q=0.1,en;q=0.7', 'en'),
+      array('pt-PT;q=0.1,pt-BR;q=0.4,en;q=0.7', 'en'),
+
+      // Language code with several dashes are valid. The less specific language
+      // from the browser matches the more specific one from the website.
+      array('eh-oh-laa-laa', 'eh-oh-laa-laa'),
+      array('eh-oh-laa', 'eh-oh-laa-laa'),
+      array('eh-oh', 'eh-oh-laa-laa'),
+      array('eh', 'eh-oh-laa-laa'),
+
+      // Different qvalues.
+      array('fr,en;q=0.5', 'fr-CA'),
+      array('fr,en;q=0.5,fr-CA;q=0.25', 'fr'),
+
+      // Silly wildcards are also valid.
+      array('*,fr-CA;q=0.5', 'en'),
+      array('*,en;q=0.25', 'fr-CA'),
+      array('en,en-US;q=0.5,fr;q=0.25', 'en'),
+      array('en-US,en;q=0.5,fr;q=0.25', 'en-US'),
+
+      // Unresolvable cases.
+      array('', FALSE),
+      array('de,pl', FALSE),
+      array('iecRswK4eh', FALSE),
+      array($this->randomMachineName(10), FALSE),
+
+      // Chinese langcodes.
+      array('zh-cn, en-us;q=0.90, en;q=0.80, zh;q=0.70', 'zh-hans'),
+      array('zh-tw, en-us;q=0.90, en;q=0.80, zh;q=0.70', 'zh-hant'),
+      array('zh-hant, en-us;q=0.90, en;q=0.80, zh;q=0.70', 'zh-hant'),
+      array('zh-hans, en-us;q=0.90, en;q=0.80, zh;q=0.70', 'zh-hans'),
+      // TODO This is copied from RFC4647 but our regex skips the numbers so they
+      // where removed. Our code should be updated so private1-private2 is valid.
+      // http://tools.ietf.org/html/rfc4647#section-3.4
+      array('zh-hant-CN-x-private-private, en-us;q=0.90, en;q=0.80, zh;q=0.70', 'zh-hant'),
+      array('zh-cn', 'zh-hans'),
+      array('zh-sg', 'zh-hans'),
+      array('zh-tw', 'zh-hant'),
+      array('zh-hk', 'zh-hant'),
+      array('zh-mo', 'zh-hant'),
+      array('zh-hans', 'zh-hans'),
+      array('zh-hant', 'zh-hant'),
+      array('zh-chs', 'zh-hans'),
+      array('zh-cht', 'zh-hant'),
+    );
+
+  }
+}
