DateTimeFormat.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. describe("errors", () => {
  2. test("structurally invalid tag", () => {
  3. expect(() => {
  4. new Intl.DateTimeFormat("root");
  5. }).toThrowWithMessage(RangeError, "root is not a structurally valid language tag");
  6. expect(() => {
  7. new Intl.DateTimeFormat("en-");
  8. }).toThrowWithMessage(RangeError, "en- is not a structurally valid language tag");
  9. expect(() => {
  10. new Intl.DateTimeFormat("Latn");
  11. }).toThrowWithMessage(RangeError, "Latn is not a structurally valid language tag");
  12. expect(() => {
  13. new Intl.DateTimeFormat("en-u-aa-U-aa");
  14. }).toThrowWithMessage(RangeError, "en-u-aa-U-aa is not a structurally valid language tag");
  15. });
  16. test("options is an invalid type", () => {
  17. expect(() => {
  18. new Intl.DateTimeFormat("en", null);
  19. }).toThrowWithMessage(TypeError, "ToObject on null or undefined");
  20. });
  21. test("localeMatcher option is invalid", () => {
  22. expect(() => {
  23. new Intl.DateTimeFormat("en", { localeMatcher: "hello!" });
  24. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option localeMatcher");
  25. });
  26. test("calendar option is invalid", () => {
  27. expect(() => {
  28. new Intl.DateTimeFormat("en", { calendar: "hello!" });
  29. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option calendar");
  30. });
  31. test("numberingSystem option is invalid", () => {
  32. expect(() => {
  33. new Intl.DateTimeFormat("en", { numberingSystem: "hello!" });
  34. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option numberingSystem");
  35. });
  36. test("hourCycle option is invalid", () => {
  37. expect(() => {
  38. new Intl.DateTimeFormat("en", { hourCycle: "hello!" });
  39. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option hourCycle");
  40. });
  41. test("timeZone option is invalid", () => {
  42. expect(() => {
  43. new Intl.DateTimeFormat("en", { timeZone: "hello!" });
  44. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option timeZone");
  45. });
  46. test("era option is invalid", () => {
  47. expect(() => {
  48. new Intl.DateTimeFormat("en", { era: "hello!" });
  49. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option era");
  50. expect(() => {
  51. new Intl.DateTimeFormat("en", { era: "narrow", dateStyle: "long" });
  52. }).toThrowWithMessage(
  53. TypeError,
  54. "Option era cannot be set when also providing dateStyle or timeStyle"
  55. );
  56. });
  57. test("year option is invalid", () => {
  58. expect(() => {
  59. new Intl.DateTimeFormat("en", { year: "hello!" });
  60. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option year");
  61. expect(() => {
  62. new Intl.DateTimeFormat("en", { year: "numeric", dateStyle: "long" });
  63. }).toThrowWithMessage(
  64. TypeError,
  65. "Option year cannot be set when also providing dateStyle or timeStyle"
  66. );
  67. });
  68. test("month option is invalid", () => {
  69. expect(() => {
  70. new Intl.DateTimeFormat("en", { month: "hello!" });
  71. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option month");
  72. expect(() => {
  73. new Intl.DateTimeFormat("en", { month: "numeric", dateStyle: "long" });
  74. }).toThrowWithMessage(
  75. TypeError,
  76. "Option month cannot be set when also providing dateStyle or timeStyle"
  77. );
  78. });
  79. test("weekday option is invalid", () => {
  80. expect(() => {
  81. new Intl.DateTimeFormat("en", { weekday: "hello!" });
  82. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option weekday");
  83. expect(() => {
  84. new Intl.DateTimeFormat("en", { weekday: "narrow", dateStyle: "long" });
  85. }).toThrowWithMessage(
  86. TypeError,
  87. "Option weekday cannot be set when also providing dateStyle or timeStyle"
  88. );
  89. });
  90. test("day option is invalid", () => {
  91. expect(() => {
  92. new Intl.DateTimeFormat("en", { day: "hello!" });
  93. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option day");
  94. expect(() => {
  95. new Intl.DateTimeFormat("en", { day: "numeric", dateStyle: "long" });
  96. }).toThrowWithMessage(
  97. TypeError,
  98. "Option day cannot be set when also providing dateStyle or timeStyle"
  99. );
  100. });
  101. test("dayPeriod option is invalid", () => {
  102. expect(() => {
  103. new Intl.DateTimeFormat("en", { dayPeriod: "hello!" });
  104. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option dayPeriod");
  105. expect(() => {
  106. new Intl.DateTimeFormat("en", { dayPeriod: "narrow", dateStyle: "long" });
  107. }).toThrowWithMessage(
  108. TypeError,
  109. "Option dayPeriod cannot be set when also providing dateStyle or timeStyle"
  110. );
  111. });
  112. test("hour option is invalid", () => {
  113. expect(() => {
  114. new Intl.DateTimeFormat("en", { hour: "hello!" });
  115. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option hour");
  116. expect(() => {
  117. new Intl.DateTimeFormat("en", { hour: "numeric", dateStyle: "long" });
  118. }).toThrowWithMessage(
  119. TypeError,
  120. "Option hour cannot be set when also providing dateStyle or timeStyle"
  121. );
  122. });
  123. test("minute option is invalid", () => {
  124. expect(() => {
  125. new Intl.DateTimeFormat("en", { minute: "hello!" });
  126. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option minute");
  127. expect(() => {
  128. new Intl.DateTimeFormat("en", { minute: "numeric", dateStyle: "long" });
  129. }).toThrowWithMessage(
  130. TypeError,
  131. "Option minute cannot be set when also providing dateStyle or timeStyle"
  132. );
  133. });
  134. test("second option is invalid", () => {
  135. expect(() => {
  136. new Intl.DateTimeFormat("en", { second: "hello!" });
  137. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option second");
  138. expect(() => {
  139. new Intl.DateTimeFormat("en", { second: "numeric", dateStyle: "long" });
  140. }).toThrowWithMessage(
  141. TypeError,
  142. "Option second cannot be set when also providing dateStyle or timeStyle"
  143. );
  144. });
  145. test("fractionalSecondDigits option is invalid", () => {
  146. expect(() => {
  147. new Intl.DateTimeFormat("en", { fractionalSecondDigits: 1n });
  148. }).toThrowWithMessage(TypeError, "Cannot convert BigInt to number");
  149. expect(() => {
  150. new Intl.DateTimeFormat("en", { fractionalSecondDigits: "hello!" });
  151. }).toThrowWithMessage(RangeError, "Value NaN is NaN or is not between 1 and 3");
  152. expect(() => {
  153. new Intl.DateTimeFormat("en", { fractionalSecondDigits: 0 });
  154. }).toThrowWithMessage(RangeError, "Value 0 is NaN or is not between 1 and 3");
  155. expect(() => {
  156. new Intl.DateTimeFormat("en", { fractionalSecondDigits: 4 });
  157. }).toThrowWithMessage(RangeError, "Value 4 is NaN or is not between 1 and 3");
  158. expect(() => {
  159. new Intl.DateTimeFormat("en", { fractionalSecondDigits: 1, dateStyle: "long" });
  160. }).toThrowWithMessage(
  161. TypeError,
  162. "Option fractionalSecondDigits cannot be set when also providing dateStyle or timeStyle"
  163. );
  164. });
  165. test("timeZoneName option is invalid", () => {
  166. expect(() => {
  167. new Intl.DateTimeFormat("en", { timeZoneName: "hello!" });
  168. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option timeZoneName");
  169. expect(() => {
  170. new Intl.DateTimeFormat("en", { timeZoneName: "short", dateStyle: "long" });
  171. }).toThrowWithMessage(
  172. TypeError,
  173. "Option timeZoneName cannot be set when also providing dateStyle or timeStyle"
  174. );
  175. });
  176. test("formatMatcher option is invalid", () => {
  177. expect(() => {
  178. new Intl.DateTimeFormat("en", { formatMatcher: "hello!" });
  179. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option formatMatcher");
  180. });
  181. test("dateStyle option is invalid", () => {
  182. expect(() => {
  183. new Intl.DateTimeFormat("en", { dateStyle: "hello!" });
  184. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option dateStyle");
  185. });
  186. test("timeStyle option is invalid", () => {
  187. expect(() => {
  188. new Intl.DateTimeFormat("en", { timeStyle: "hello!" });
  189. }).toThrowWithMessage(RangeError, "hello! is not a valid value for option timeStyle");
  190. });
  191. });
  192. describe("normal behavior", () => {
  193. test("length is 0", () => {
  194. expect(Intl.DateTimeFormat).toHaveLength(0);
  195. });
  196. test("all valid localeMatcher options", () => {
  197. ["lookup", "best fit"].forEach(localeMatcher => {
  198. expect(() => {
  199. new Intl.DateTimeFormat("en", { localeMatcher: localeMatcher });
  200. }).not.toThrow();
  201. });
  202. });
  203. test("valid calendar options", () => {
  204. ["generic", "gregory"].forEach(calendar => {
  205. expect(() => {
  206. new Intl.DateTimeFormat("en", { calendar: calendar });
  207. }).not.toThrow();
  208. });
  209. });
  210. test("valid numberingSystem options", () => {
  211. ["latn", "arab", "abc-def-ghi"].forEach(numberingSystem => {
  212. expect(() => {
  213. new Intl.DateTimeFormat("en", { numberingSystem: numberingSystem });
  214. }).not.toThrow();
  215. });
  216. });
  217. test("valid hour12 options", () => {
  218. [true, false].forEach(hour12 => {
  219. expect(() => {
  220. new Intl.DateTimeFormat("en", { hour12: hour12 });
  221. }).not.toThrow();
  222. });
  223. });
  224. test("all valid hourCycle options", () => {
  225. ["h11", "h12", "h23", "h24"].forEach(hourCycle => {
  226. expect(() => {
  227. new Intl.DateTimeFormat("en", { hourCycle: hourCycle });
  228. }).not.toThrow();
  229. });
  230. });
  231. test("valid timeZone options", () => {
  232. expect(() => {
  233. new Intl.DateTimeFormat("en", { timeZone: "UTC" });
  234. }).not.toThrow();
  235. });
  236. test("all valid weekday options", () => {
  237. ["narrow", "short", "long"].forEach(weekday => {
  238. expect(() => {
  239. new Intl.DateTimeFormat("en", { weekday: weekday });
  240. }).not.toThrow();
  241. });
  242. });
  243. test("all valid era options", () => {
  244. ["narrow", "short", "long"].forEach(era => {
  245. expect(() => {
  246. new Intl.DateTimeFormat("en", { era: era });
  247. }).not.toThrow();
  248. });
  249. });
  250. test("all valid year options", () => {
  251. ["2-digit", "numeric"].forEach(year => {
  252. expect(() => {
  253. new Intl.DateTimeFormat("en", { year: year });
  254. }).not.toThrow();
  255. });
  256. });
  257. test("all valid month options", () => {
  258. ["2-digit", "numeric", "narrow", "short", "long"].forEach(month => {
  259. expect(() => {
  260. new Intl.DateTimeFormat("en", { month: month });
  261. }).not.toThrow();
  262. });
  263. });
  264. test("all valid day options", () => {
  265. ["2-digit", "numeric"].forEach(day => {
  266. expect(() => {
  267. new Intl.DateTimeFormat("en", { day: day });
  268. }).not.toThrow();
  269. });
  270. });
  271. test("all valid dayPeriod options", () => {
  272. ["narrow", "short", "long"].forEach(dayPeriod => {
  273. expect(() => {
  274. new Intl.DateTimeFormat("en", { dayPeriod: dayPeriod });
  275. }).not.toThrow();
  276. });
  277. });
  278. test("all valid hour options", () => {
  279. ["2-digit", "numeric"].forEach(hour => {
  280. expect(() => {
  281. new Intl.DateTimeFormat("en", { hour: hour });
  282. }).not.toThrow();
  283. });
  284. });
  285. test("all valid minute options", () => {
  286. ["2-digit", "numeric"].forEach(minute => {
  287. expect(() => {
  288. new Intl.DateTimeFormat("en", { minute: minute });
  289. }).not.toThrow();
  290. });
  291. });
  292. test("all valid second options", () => {
  293. ["2-digit", "numeric"].forEach(second => {
  294. expect(() => {
  295. new Intl.DateTimeFormat("en", { second: second });
  296. }).not.toThrow();
  297. });
  298. });
  299. test("all valid fractionalSecondDigits options", () => {
  300. [1, 2, 3].forEach(fractionalSecondDigits => {
  301. expect(() => {
  302. new Intl.DateTimeFormat("en", { fractionalSecondDigits: fractionalSecondDigits });
  303. }).not.toThrow();
  304. });
  305. });
  306. test("all valid timeZoneName options", () => {
  307. ["short", "long"].forEach(timeZoneName => {
  308. expect(() => {
  309. new Intl.DateTimeFormat("en", { timeZoneName: timeZoneName });
  310. }).not.toThrow();
  311. });
  312. });
  313. test("all valid formatMatcher options", () => {
  314. ["basic", "best fit"].forEach(formatMatcher => {
  315. expect(() => {
  316. new Intl.DateTimeFormat("en", { formatMatcher: formatMatcher });
  317. }).not.toThrow();
  318. });
  319. });
  320. test("all valid dateStyle options", () => {
  321. ["full", "long", "medium", "short"].forEach(dateStyle => {
  322. expect(() => {
  323. new Intl.DateTimeFormat("en", { dateStyle: dateStyle });
  324. }).not.toThrow();
  325. });
  326. });
  327. test("all valid timeStyle options", () => {
  328. ["full", "long", "medium", "short"].forEach(timeStyle => {
  329. expect(() => {
  330. new Intl.DateTimeFormat("en", { timeStyle: timeStyle });
  331. }).not.toThrow();
  332. });
  333. });
  334. });