@operato/utils 10.16.2 → 10.29.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +26 -0
- package/coverage/lcov-report/index.html +18 -18
- package/coverage/lcov.info +250 -0
- package/dist/src/when.d.ts +84 -0
- package/dist/src/when.js +158 -0
- package/dist/src/when.js.map +1 -0
- package/dist/test/when.test.d.ts +1 -0
- package/dist/test/when.test.js +101 -0
- package/dist/test/when.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -3
- package/test/when.test.ts +127 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { expect } from '@open-wc/testing'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
availableZones,
|
|
5
|
+
dayHeadings,
|
|
6
|
+
formatWhen,
|
|
7
|
+
msOf,
|
|
8
|
+
nextZone,
|
|
9
|
+
resolveZone,
|
|
10
|
+
zoneAbbr,
|
|
11
|
+
ZONE_ORDER
|
|
12
|
+
} from '../src/when.js'
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* The moment rule, carried over from operato-twin (test/when-core.test.ts) with its cases: follow the
|
|
16
|
+
* screen's language, read the zone given, and never make up a zone that is not there.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/** 2026-08-22 08:23 UTC - 17:23 the same day in Seoul, 01:23 the same day in Los Angeles. */
|
|
20
|
+
const AT = Date.UTC(2026, 7, 22, 8, 23, 0)
|
|
21
|
+
|
|
22
|
+
describe('formatWhen', () => {
|
|
23
|
+
it('draws in the language it is given, not the browser setting', () => {
|
|
24
|
+
const ko = formatWhen(AT, { lang: 'ko', zone: 'Asia/Seoul' })!
|
|
25
|
+
const en = formatWhen(AT, { lang: 'en-US', zone: 'Asia/Seoul' })!
|
|
26
|
+
expect(ko).to.include('2026년')
|
|
27
|
+
expect(ko).to.not.equal(en)
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('writes a 24-hour clock in all five languages', () => {
|
|
31
|
+
for (const lang of ['ko', 'en-US', 'ja', 'zh', 'es']) {
|
|
32
|
+
const out = formatWhen(AT, { lang, zone: 'Asia/Seoul' })!
|
|
33
|
+
expect(out, lang).to.include('17:23')
|
|
34
|
+
expect(/AM|PM|오전|오후/.test(out), `${lang}: ${out}`).to.equal(false)
|
|
35
|
+
}
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
it('reads the zone it is given', () => {
|
|
39
|
+
const seoul = formatWhen(AT, { lang: 'en-US', zone: 'Asia/Seoul' })!
|
|
40
|
+
const la = formatWhen(AT, { lang: 'en-US', zone: 'America/Los_Angeles' })!
|
|
41
|
+
expect(seoul).to.not.equal(la)
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
it('does not draw on another clock when the zone is unknown or missing', () => {
|
|
45
|
+
expect(formatWhen(AT, { lang: 'ko', zone: 'Mars/Olympus' })).to.equal(null)
|
|
46
|
+
expect(formatWhen(AT, { lang: 'ko', zone: resolveZone('domain', null) })).to.equal(null)
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('lets the caller choose how much to write', () => {
|
|
50
|
+
const opts = { lang: 'en-US', zone: 'UTC' }
|
|
51
|
+
expect(/:/.test(formatWhen(AT, { ...opts, style: 'date' })!)).to.equal(false)
|
|
52
|
+
expect(formatWhen(AT, { ...opts, style: 'time' })).to.match(/08:23/)
|
|
53
|
+
expect(formatWhen(AT, { ...opts, style: 'precise' })).to.match(/:00/)
|
|
54
|
+
})
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
describe('zones', () => {
|
|
58
|
+
it('without a domain zone, that choice cannot be made', () => {
|
|
59
|
+
expect(availableZones(null)).to.deep.equal(['local', 'utc'])
|
|
60
|
+
expect(availableZones('')).to.deep.equal(['local', 'utc'])
|
|
61
|
+
expect(availableZones('Asia/Seoul')).to.deep.equal([...ZONE_ORDER])
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
it("does not swap a missing domain zone for the viewer's own", () => {
|
|
65
|
+
expect(resolveZone('domain', null)).to.equal(null)
|
|
66
|
+
expect(resolveZone('local', null)).to.equal(undefined)
|
|
67
|
+
expect(resolveZone('utc', null)).to.equal('UTC')
|
|
68
|
+
expect(resolveZone('domain', 'Asia/Seoul')).to.equal('Asia/Seoul')
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
it('steps round and skips what cannot be chosen', () => {
|
|
72
|
+
expect(nextZone('local', 'Asia/Seoul')).to.equal('utc')
|
|
73
|
+
expect(nextZone('utc', 'Asia/Seoul')).to.equal('domain')
|
|
74
|
+
expect(nextZone('domain', 'Asia/Seoul')).to.equal('local')
|
|
75
|
+
expect(nextZone('utc', null)).to.equal('local')
|
|
76
|
+
expect(nextZone('domain', null)).to.equal('local')
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
it('names a zone as it is on that date - summer time included', () => {
|
|
80
|
+
expect(zoneAbbr('UTC', 'en-US', AT)).to.equal('UTC')
|
|
81
|
+
expect(zoneAbbr(null, 'en-US', AT)).to.equal(null)
|
|
82
|
+
expect(zoneAbbr('Mars/Olympus', 'en-US', AT)).to.equal(null)
|
|
83
|
+
const winter = zoneAbbr('America/Los_Angeles', 'en-US', Date.UTC(2026, 0, 15, 12))
|
|
84
|
+
const summer = zoneAbbr('America/Los_Angeles', 'en-US', Date.UTC(2026, 6, 15, 12))
|
|
85
|
+
expect(winter).to.not.equal(summer)
|
|
86
|
+
})
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
describe('msOf', () => {
|
|
90
|
+
it('unreadable is null, never "Invalid Date"', () => {
|
|
91
|
+
for (const value of [null, undefined, '', 'yesterday', Number.NaN, new Date('x')]) {
|
|
92
|
+
expect(msOf(value), String(value)).to.equal(null)
|
|
93
|
+
}
|
|
94
|
+
expect(formatWhen('yesterday', { lang: 'ko' })).to.equal(null)
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
it('takes a number, a string or a Date', () => {
|
|
98
|
+
expect(msOf(AT)).to.equal(AT)
|
|
99
|
+
expect(msOf(new Date(AT).toISOString())).to.equal(AT)
|
|
100
|
+
expect(msOf(new Date(AT))).to.equal(AT)
|
|
101
|
+
})
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
describe('dayHeadings', () => {
|
|
105
|
+
it('puts the date on the first row even when there is one day', () => {
|
|
106
|
+
expect(dayHeadings(['Aug 27', 'Aug 27', 'Aug 27'])).to.deep.equal(['Aug 27', '', ''])
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
it('and only where the date changes', () => {
|
|
110
|
+
expect(dayHeadings(['Aug 27', 'Aug 27', 'Aug 26', 'Aug 26', 'Aug 25'])).to.deep.equal([
|
|
111
|
+
'Aug 27',
|
|
112
|
+
'',
|
|
113
|
+
'Aug 26',
|
|
114
|
+
'',
|
|
115
|
+
'Aug 25'
|
|
116
|
+
])
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
it('a row with no date does not clear the one before it', () => {
|
|
120
|
+
expect(dayHeadings(['Aug 27', '', 'Aug 27', 'Aug 26'])).to.deep.equal(['Aug 27', '', '', 'Aug 26'])
|
|
121
|
+
})
|
|
122
|
+
|
|
123
|
+
it('a date that comes back is said again - a broken sort is not hidden', () => {
|
|
124
|
+
expect(dayHeadings(['Aug 27', 'Aug 26', 'Aug 27'])).to.deep.equal(['Aug 27', 'Aug 26', 'Aug 27'])
|
|
125
|
+
expect(dayHeadings([])).to.deep.equal([])
|
|
126
|
+
})
|
|
127
|
+
})
|