UserAgentTest.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. <?php
  2. namespace Drupal\Tests\Component\Utility;
  3. use Drupal\Component\Utility\Random;
  4. use Drupal\Component\Utility\UserAgent;
  5. use PHPUnit\Framework\TestCase;
  6. /**
  7. * Tests bytes size parsing helper methods.
  8. *
  9. * @group Utility
  10. *
  11. * @coversDefaultClass \Drupal\Component\Utility\UserAgent
  12. */
  13. class UserAgentTest extends TestCase {
  14. /**
  15. * Helper method to supply language codes to testGetBestMatchingLangcode().
  16. *
  17. * @return array
  18. * Language codes, ordered by priority.
  19. */
  20. protected function getLanguages() {
  21. return [
  22. // In our test case, 'en' has priority over 'en-US'.
  23. 'en',
  24. 'en-US',
  25. // But 'fr-CA' has priority over 'fr'.
  26. 'fr-CA',
  27. 'fr',
  28. // 'es-MX' is alone.
  29. 'es-MX',
  30. // 'pt' is alone.
  31. 'pt',
  32. // Language codes with more then one dash are actually valid.
  33. // eh-oh-laa-laa is the official language code of the Teletubbies.
  34. 'eh-oh-laa-laa',
  35. // Chinese languages.
  36. 'zh-hans',
  37. 'zh-hant',
  38. 'zh-hant-tw',
  39. ];
  40. }
  41. /**
  42. * Helper method to supply language mappings to testGetBestMatchingLangcode().
  43. *
  44. * @return array
  45. * Language mappings.
  46. */
  47. protected function getMappings() {
  48. return [
  49. 'no' => 'nb',
  50. 'pt' => 'pt-pt',
  51. 'zh' => 'zh-hans',
  52. 'zh-tw' => 'zh-hant',
  53. 'zh-hk' => 'zh-hant',
  54. 'zh-mo' => 'zh-hant',
  55. 'zh-cht' => 'zh-hant',
  56. 'zh-cn' => 'zh-hans',
  57. 'zh-sg' => 'zh-hans',
  58. 'zh-chs' => 'zh-hans',
  59. ];
  60. }
  61. /**
  62. * Test matching language from user agent.
  63. *
  64. * @dataProvider providerTestGetBestMatchingLangcode
  65. * @covers ::getBestMatchingLangcode
  66. */
  67. public function testGetBestMatchingLangcode($accept_language, $expected) {
  68. $result = UserAgent::getBestMatchingLangcode($accept_language, $this->getLanguages(), $this->getMappings());
  69. $this->assertSame($expected, $result);
  70. }
  71. /**
  72. * Data provider for testGetBestMatchingLangcode().
  73. *
  74. * @return array
  75. * - An accept-language string.
  76. * - Expected best matching language code.
  77. */
  78. public function providerTestGetBestMatchingLangcode() {
  79. // Random generator.
  80. $random = new Random();
  81. return [
  82. // Equal qvalue for each language, choose the site preferred one.
  83. ['en,en-US,fr-CA,fr,es-MX', 'en'],
  84. ['en-US,en,fr-CA,fr,es-MX', 'en'],
  85. ['fr,en', 'en'],
  86. ['en,fr', 'en'],
  87. ['en-US,fr', 'en-US'],
  88. ['fr,en-US', 'en-US'],
  89. ['fr,fr-CA', 'fr-CA'],
  90. ['fr-CA,fr', 'fr-CA'],
  91. ['fr', 'fr-CA'],
  92. ['fr;q=1', 'fr-CA'],
  93. ['fr,es-MX', 'fr-CA'],
  94. ['fr,es', 'fr-CA'],
  95. ['es,fr', 'fr-CA'],
  96. ['es-MX,de', 'es-MX'],
  97. ['de,es-MX', 'es-MX'],
  98. // Different cases and whitespace.
  99. ['en', 'en'],
  100. ['En', 'en'],
  101. ['EN', 'en'],
  102. [' en', 'en'],
  103. ['en ', 'en'],
  104. ['en, fr', 'en'],
  105. // A less specific language from the browser matches a more specific one
  106. // from the website, and the other way around for compatibility with
  107. // some versions of Internet Explorer.
  108. ['es', 'es-MX'],
  109. ['es-MX', 'es-MX'],
  110. ['pt', 'pt'],
  111. ['pt-PT', 'pt'],
  112. ['pt-PT;q=0.5,pt-BR;q=1,en;q=0.7', 'en'],
  113. ['pt-PT;q=1,pt-BR;q=0.5,en;q=0.7', 'en'],
  114. ['pt-PT;q=0.4,pt-BR;q=0.1,en;q=0.7', 'en'],
  115. ['pt-PT;q=0.1,pt-BR;q=0.4,en;q=0.7', 'en'],
  116. // Language code with several dashes are valid. The less specific language
  117. // from the browser matches the more specific one from the website.
  118. ['eh-oh-laa-laa', 'eh-oh-laa-laa'],
  119. ['eh-oh-laa', 'eh-oh-laa-laa'],
  120. ['eh-oh', 'eh-oh-laa-laa'],
  121. ['eh', 'eh-oh-laa-laa'],
  122. // Different qvalues.
  123. ['fr,en;q=0.5', 'fr-CA'],
  124. ['fr,en;q=0.5,fr-CA;q=0.25', 'fr'],
  125. // Silly wildcards are also valid.
  126. ['*,fr-CA;q=0.5', 'en'],
  127. ['*,en;q=0.25', 'fr-CA'],
  128. ['en,en-US;q=0.5,fr;q=0.25', 'en'],
  129. ['en-US,en;q=0.5,fr;q=0.25', 'en-US'],
  130. // Unresolvable cases.
  131. ['', FALSE],
  132. ['de,pl', FALSE],
  133. ['iecRswK4eh', FALSE],
  134. [$random->name(10, TRUE), FALSE],
  135. // Chinese langcodes.
  136. ['zh-cn, en-us;q=0.90, en;q=0.80, zh;q=0.70', 'zh-hans'],
  137. ['zh-tw, en-us;q=0.90, en;q=0.80, zh;q=0.70', 'zh-hant'],
  138. ['zh-hant, en-us;q=0.90, en;q=0.80, zh;q=0.70', 'zh-hant'],
  139. ['zh-hans, en-us;q=0.90, en;q=0.80, zh;q=0.70', 'zh-hans'],
  140. // @todo: This is copied from RFC4647 but our regex skips the numbers so
  141. // they where removed. Our code should be updated so private1-private2 is
  142. // valid. http://tools.ietf.org/html/rfc4647#section-3.4
  143. ['zh-hant-CN-x-private-private, en-us;q=0.90, en;q=0.80, zh;q=0.70', 'zh-hant'],
  144. ['zh-cn', 'zh-hans'],
  145. ['zh-sg', 'zh-hans'],
  146. ['zh-tw', 'zh-hant'],
  147. ['zh-hk', 'zh-hant'],
  148. ['zh-mo', 'zh-hant'],
  149. ['zh-hans', 'zh-hans'],
  150. ['zh-hant', 'zh-hant'],
  151. ['zh-chs', 'zh-hans'],
  152. ['zh-cht', 'zh-hant'],
  153. ];
  154. }
  155. }