Skip to content

Commit 7feb25f

Browse files
committed
feat(chain): add support for luxon object during lookups
With the deprecation of moment, luxon is sane replacement in testing. In a similar fashion as with moment, we don't want to break the prototype chain when passing luxon objects around. Unlike moment, there are several date-ish object we need to acount for. This will allow users to reference and manimulat luxon object during chain execution with out having to cast between native date objects
1 parent f50aef9 commit 7feb25f

5 files changed

Lines changed: 62 additions & 2 deletions

File tree

lib/chain.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ const COMPLEX_LOOKUP_TYPES = new Set([
1717
, 'moment'
1818
, 'boolean'
1919
, 'number'
20+
, 'luxondatetime'
21+
, 'luxoninterval'
22+
, 'luxonduration'
2023
])
2124

2225
module.exports = class SetupChain {

lib/lang/type-of.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ module.exports = function typeOf(value) {
1111
if (value === null) return 'null'
1212
if (value === undefined) return 'undefined'
1313
if (value._isAMomentObject && typeof value.format === 'function') return 'moment'
14+
if (value.isLuxonDateTime) return 'luxondatetime'
15+
if (value.isLuxonInterval) return 'luxoninterval'
16+
if (value.isLuxonDuration) return 'luxonduration'
1417
const parts = TYPE_EXP.exec(toString.call(value))
1518
return parts[1].toLowerCase()
1619
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
"casual": "^1.6.2",
6767
"eslint": "^8.21.0",
6868
"eslint-config-logdna": "^6.1.0",
69+
"luxon": "^3.2.1",
6970
"moment": "^2.29.1",
7071
"semantic-release": "^17.4.4",
7172
"semantic-release-config-logdna": "^1.3.0",

test/integration/chain.js

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict'
22

33
const moment = require('moment')
4+
const luxon = require('luxon')
45
const {test, threw} = require('tap')
56
const Chain = require('../../lib/chain.js')
67
const actions = require('../fixtures/actions/index.js')
@@ -104,11 +105,11 @@ test('Setup chain', async (t) => {
104105

105106
t.match(state, {
106107
names: 'Hello, Mr. Wonderful'
107-
}, 'expected output')
108+
}, 'expected printNames output')
108109
}
109110
})
110111

111-
t.test('extended chain w/ lookup functions', async (t) => {
112+
t.test('extended chain w/ lookup functions (moment)', async (t) => {
112113
class MomentChain extends Chain {
113114
constructor(state) {
114115
super(state)
@@ -141,6 +142,40 @@ test('Setup chain', async (t) => {
141142
}
142143
})
143144

145+
t.test('extended chain w/ lookup functions (luxon)', async (t) => {
146+
class LuxonChain extends Chain {
147+
constructor(state) {
148+
super(state)
149+
}
150+
151+
$now() {
152+
return luxon.DateTime.now()
153+
}
154+
155+
$dateadd(date, amount, units = 'minutes', format) {
156+
const [_date, _amount, _units] = this.lookup([date, amount, units])
157+
let out = _date.isLuxonDateTime ? _date : new luxon.DateTime(_date)
158+
out = out.plus({[_units]: _amount})
159+
return format ? this.$strftime(format, out) : out
160+
}
161+
162+
$strftime(format = 'Y-MM-DD', date) {
163+
const input = this.lookup(date) || undefined
164+
return input.setZone('utc').toFormat(format)
165+
}
166+
}
167+
168+
const chain = new LuxonChain()
169+
{
170+
const value = chain.lookup('!dateadd:!now,1,day')
171+
t.ok(luxon.DateTime.isDateTime(value), 'is luxon DateTime value')
172+
}
173+
{
174+
const value = chain.lookup('!dateadd:!now,1,day,x')
175+
t.match(value, /\d+/, 'formated number value')
176+
}
177+
})
178+
144179
t.test('extended chain created with an existing state', async (t) => {
145180
class WithStateChain extends Chain {
146181
constructor(state) {

test/unit/lang/typeof.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
const {test, threw} = require('tap')
44
const Moment = require('moment')
5+
const luxon = require('luxon')
56
const typeOf = require('../../../lib/lang/type-of.js')
67

78
class FooBar {
@@ -64,8 +65,25 @@ test('typeOf', (t) => {
6465
, {
6566
value: Moment()
6667
, expected: 'moment'
68+
, message: 'typeOf(Moment()) === moment'
69+
}
70+
, {
71+
value: luxon.DateTime.now()
72+
, expected: 'luxondatetime'
73+
, message: 'typeOf(luxon.DateTime.now()) === luxondatetime'
74+
}
75+
, {
76+
value: luxon.Duration.fromMillis(Date.now())
77+
, expected: 'luxonduration'
78+
, message: 'typeOf(new luxon.Duration()) == luxonduration'
79+
}
80+
, {
81+
value: new luxon.Interval({start: luxon.DateTime.now()})
82+
, expected: 'luxoninterval'
83+
, message: 'typeOf(new luxon.Interval()) === luxoninterval'
6784
}
6885
]
86+
6987
for (const current of cases) {
7088
t.equal(
7189
typeOf(current.value)

0 commit comments

Comments
 (0)