date.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /*
  2. * Copyright (C) 2024 Puter Technologies Inc.
  3. *
  4. * This file is part of Phoenix Shell.
  5. *
  6. * Phoenix Shell is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU Affero General Public License as published
  8. * by the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU Affero General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Affero General Public License
  17. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  18. */
  19. import assert from 'assert';
  20. import * as ck from 'chronokinesis';
  21. import { MakeTestContext } from './harness.js'
  22. import builtins from '../../src/puter-shell/coreutils/__exports__.js';
  23. export const runDateTests = () => {
  24. describe('date', function () {
  25. beforeEach(() => {
  26. ck.freeze();
  27. ck.timezone('UTC', '2024-03-07 13:05:07');
  28. });
  29. afterEach(() => {
  30. ck.reset();
  31. });
  32. const testCases = [
  33. {
  34. description: 'outputs the date and time in a standard format when no format parameter is given',
  35. input: [ ],
  36. options: { utc: true },
  37. expectedStdout: 'Thu Mar 7 13:05:07 UTC 2024\n',
  38. expectedStderr: '',
  39. },
  40. {
  41. description: 'outputs the format verbatim if no format sequences are included',
  42. input: [ '+hello' ],
  43. options: { utc: true },
  44. expectedStdout: 'hello\n',
  45. expectedStderr: '',
  46. },
  47. {
  48. description: '%a outputs abbreviated weekday name',
  49. input: [ '+%a' ],
  50. options: { utc: true },
  51. expectedStdout: 'Thu\n',
  52. expectedStderr: '',
  53. },
  54. {
  55. description: '%A outputs full weekday name',
  56. input: [ '+%A' ],
  57. options: { utc: true },
  58. expectedStdout: 'Thursday\n',
  59. expectedStderr: '',
  60. },
  61. {
  62. description: '%b outputs abbreviated month name',
  63. input: [ '+%b' ],
  64. options: { utc: true },
  65. expectedStdout: 'Mar\n',
  66. expectedStderr: '',
  67. },
  68. {
  69. description: '%B outputs full month name',
  70. input: [ '+%B' ],
  71. options: { utc: true },
  72. expectedStdout: 'March\n',
  73. expectedStderr: '',
  74. },
  75. {
  76. description: '%c outputs full date and time',
  77. input: [ '+%c' ],
  78. options: { utc: true },
  79. expectedStdout: '3/7/2024, 1:05:07 PM\n',
  80. expectedStderr: '',
  81. },
  82. {
  83. description: '%C outputs century as 2 digits',
  84. input: [ '+%C' ],
  85. options: { utc: true },
  86. expectedStdout: '20\n',
  87. expectedStderr: '',
  88. },
  89. {
  90. description: '%d outputs day of the month as 2 digits',
  91. input: [ '+%d' ],
  92. options: { utc: true },
  93. expectedStdout: '07\n',
  94. expectedStderr: '',
  95. },
  96. {
  97. description: '%D outputs date as mm/dd/yy',
  98. input: [ '+%D' ],
  99. options: { utc: true },
  100. expectedStdout: '03/07/24\n',
  101. expectedStderr: '',
  102. },
  103. {
  104. description: '%e outputs day of the month as 2 characters padded with a leading space',
  105. input: [ '+%e' ],
  106. options: { utc: true },
  107. expectedStdout: ' 7\n',
  108. expectedStderr: '',
  109. },
  110. {
  111. description: '%H outputs the 24-hour clock hour, as 2 digits',
  112. input: [ '+%H' ],
  113. options: { utc: true },
  114. expectedStdout: '13\n',
  115. expectedStderr: '',
  116. },
  117. {
  118. description: '%h outputs the same as %b',
  119. input: [ '+%h' ],
  120. options: { utc: true },
  121. expectedStdout: 'Mar\n',
  122. expectedStderr: '',
  123. },
  124. {
  125. description: '%I outputs the 12-hour clock hour, as 2 digits',
  126. input: [ '+%I' ],
  127. options: { utc: true },
  128. expectedStdout: '01\n',
  129. expectedStderr: '',
  130. },
  131. // TODO: %j outputs the day of the year as a 3-digit number, starting at 001.
  132. {
  133. description: '%m outputs the month, as 2 digits, with January as 01',
  134. input: [ '+%m' ],
  135. options: { utc: true },
  136. expectedStdout: '03\n',
  137. expectedStderr: '',
  138. },
  139. {
  140. description: '%M outputs the minute, as 2 digits',
  141. input: [ '+%M' ],
  142. options: { utc: true },
  143. expectedStdout: '05\n',
  144. expectedStderr: '',
  145. },
  146. {
  147. description: '%n outputs a newline character',
  148. input: [ '+%n' ],
  149. options: { utc: true },
  150. expectedStdout: '\n\n',
  151. expectedStderr: '',
  152. },
  153. {
  154. description: '%p outputs AM or PM',
  155. input: [ '+%p' ],
  156. options: { utc: true },
  157. expectedStdout: 'PM\n',
  158. expectedStderr: '',
  159. },
  160. {
  161. description: '%r outputs the 12-hour clock time',
  162. input: [ '+%r' ],
  163. options: { utc: true },
  164. expectedStdout: '01:05:07 PM\n',
  165. expectedStderr: '',
  166. },
  167. {
  168. description: '%S outputs seconds, as 2 digits',
  169. input: [ '+%S' ],
  170. options: { utc: true },
  171. expectedStdout: '07\n',
  172. expectedStderr: '',
  173. },
  174. {
  175. description: '%t outputs a tab character',
  176. input: [ '+%t' ],
  177. options: { utc: true },
  178. expectedStdout: '\t\n',
  179. expectedStderr: '',
  180. },
  181. {
  182. description: '%T outputs the 24-hour clock time',
  183. input: [ '+%T' ],
  184. options: { utc: true },
  185. expectedStdout: '13:05:07\n',
  186. expectedStderr: '',
  187. },
  188. {
  189. description: '%u outputs the week day as a number, with Monday = 1 and Sunday = 7',
  190. input: [ '+%u' ],
  191. options: { utc: true },
  192. expectedStdout: '4\n',
  193. expectedStderr: '',
  194. },
  195. // TODO: %U outputs the week of the year, as 2 digits, with weeks starting on Sunday, and the first being week 00
  196. // TODO: %V outputs the week of the year, as 2 digits, with weeks starting on Monday, and the first being week 01
  197. {
  198. description: '%w outputs the week day as a number, with Sunday = 0 and Saturday = 6',
  199. input: [ '+%w' ],
  200. options: { utc: true },
  201. expectedStdout: '4\n',
  202. expectedStderr: '',
  203. },
  204. // TODO: %W outputs the week of the year, as 2 digits,, with weeks starting on Monday, and the first being week 00
  205. {
  206. description: '%x outputs a local date representation',
  207. input: [ '+%x' ],
  208. options: { utc: true },
  209. expectedStdout: '3/7/2024\n',
  210. expectedStderr: '',
  211. },
  212. {
  213. description: '%X outputs a local time representation',
  214. input: [ '+%X' ],
  215. options: { utc: true },
  216. expectedStdout: '1:05:07 PM\n',
  217. expectedStderr: '',
  218. },
  219. {
  220. description: '%y outputs the year within a century, as 2 digits',
  221. input: [ '+%y' ],
  222. options: { utc: true },
  223. expectedStdout: '24\n',
  224. expectedStderr: '',
  225. },
  226. {
  227. description: '%Y outputs the year',
  228. input: [ '+%Y' ],
  229. options: { utc: true },
  230. expectedStdout: '2024\n',
  231. expectedStderr: '',
  232. },
  233. {
  234. description: '%Z outputs the timezone name',
  235. input: [ '+%Z' ],
  236. options: { utc: true },
  237. expectedStdout: 'UTC\n',
  238. expectedStderr: '',
  239. },
  240. {
  241. description: '%% outputs a percent sign',
  242. input: [ '+%%' ],
  243. options: { utc: true },
  244. expectedStdout: '%\n',
  245. expectedStderr: '',
  246. },
  247. {
  248. description: 'multiple format sequences can be included at once',
  249. input: [ '+%B is month %m' ],
  250. options: { utc: true },
  251. expectedStdout: 'March is month 03\n',
  252. expectedStderr: '',
  253. },
  254. {
  255. description: 'unrecognized formats are output verbatim',
  256. input: [ '+%4%L hello' ],
  257. options: { utc: true },
  258. expectedStdout: '%4%L hello\n',
  259. expectedStderr: '',
  260. },
  261. ];
  262. for (const { description, input, options, expectedStdout, expectedStderr, expectedFail } of testCases) {
  263. it(description, async () => {
  264. let ctx = MakeTestContext(builtins.date, { positionals: input, values: options });
  265. let hadError = false;
  266. try {
  267. const result = await builtins.date.execute(ctx);
  268. if (!expectedFail) {
  269. assert.equal(result, undefined, 'should exit successfully, returning nothing');
  270. }
  271. } catch (e) {
  272. hadError = true;
  273. if (!expectedFail) {
  274. assert.fail(e);
  275. }
  276. }
  277. if (expectedFail && !hadError) {
  278. assert.fail('should have returned an error code');
  279. }
  280. assert.equal(ctx.externs.out.output, expectedStdout, 'wrong output written to stdout');
  281. assert.equal(ctx.externs.err.output, expectedStderr, 'wrong output written to stderr');
  282. });
  283. }
  284. });
  285. };