Skip to content

Commit

Permalink
fix: Fix objectSupport collides with Duration plugin - issue #2027 (#…
Browse files Browse the repository at this point in the history
…2038)

* fix: make objectSupport ignore other object types (issue #2027)

while fixing, an issue wit the handling of subtract appeared and was
fixed too.

* test: add tests for issue #2027
  • Loading branch information
BePo65 committed Aug 30, 2022
1 parent 6c2a517 commit c9370ea
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 19 deletions.
46 changes: 27 additions & 19 deletions src/plugin/objectSupport/index.js
@@ -1,6 +1,7 @@
export default (o, c, dayjs) => {
const proto = c.prototype
const isObject = obj => !(obj instanceof Date) && !(obj instanceof Array) && obj instanceof Object
const isObject = obj => !(obj instanceof Date) && !(obj instanceof Array)

This comment has been minimized.

Copy link
@illjah42

illjah42 Oct 21, 2022

Contributor

now null value passes this check. is this a bug? are you planning to exclude null?

&& !proto.$utils().u(obj) && (obj.constructor.name === 'Object')

This comment has been minimized.

Copy link
@LetsGoBoulderingDude

LetsGoBoulderingDude Nov 21, 2022

Updateing from 1.11.5 to 1.11.6 leads to a null pointer in line 4 when obj == null. Which happens during angular lifecycle for a date range inpute field with custom validator. Let me know if you need any further information.

const prettyUnit = (u) => {
const unit = proto.$utils().p(u)
return unit === 'date' ? 'day' : unit
Expand Down Expand Up @@ -39,29 +40,36 @@ export default (o, c, dayjs) => {

const oldSet = proto.set
const oldAdd = proto.add
const oldSubtract = proto.subtract

const callObject = function (call, argument, string, offset = 1) {
if (argument instanceof Object) {
const keys = Object.keys(argument)
let chain = this
keys.forEach((key) => {
chain = call.bind(chain)(argument[key] * offset, key)
})
return chain
}
return call.bind(this)(argument * offset, string)
const keys = Object.keys(argument)
let chain = this
keys.forEach((key) => {
chain = call.bind(chain)(argument[key] * offset, key)
})
return chain
}

proto.set = function (string, int) {
int = int === undefined ? string : int
return callObject.bind(this)(function (i, s) {
return oldSet.bind(this)(s, i)
}, int, string)
proto.set = function (unit, value) {
value = value === undefined ? unit : value
if (unit.constructor.name === 'Object') {
return callObject.bind(this)(function (i, s) {
return oldSet.bind(this)(s, i)
}, value, unit)
}
return oldSet.bind(this)(unit, value)
}
proto.add = function (number, string) {
return callObject.bind(this)(oldAdd, number, string)
proto.add = function (value, unit) {
if (value.constructor.name === 'Object') {
return callObject.bind(this)(oldAdd, value, unit)
}
return oldAdd.bind(this)(value, unit)
}
proto.subtract = function (number, string) {
return callObject.bind(this)(oldAdd, number, string, -1)
proto.subtract = function (value, unit) {
if (value.constructor.name === 'Object') {
return callObject.bind(this)(oldAdd, value, unit, -1)
}
return oldSubtract.bind(this)(value, unit)
}
}
78 changes: 78 additions & 0 deletions test/issues/issue2027.correct-order.test.js
@@ -0,0 +1,78 @@
import MockDate from 'mockdate'
import dayjs from '../../src'
import duration from '../../src/plugin/duration'
import objectSupport from '../../src/plugin/objectSupport'

dayjs.extend(objectSupport)
dayjs.extend(duration)

beforeEach(() => {
MockDate.set(new Date())
})

afterEach(() => {
MockDate.reset()
})

// issue 2027
describe('issue 2027 - order objectSupport > Duration', () => {
it('add Duration object returns correct date', () => {
const baseDate = dayjs('2022-06-26T14:01:02.003')
const durationToAdd = dayjs.duration(6, 'hours')
const testDate = baseDate.add(durationToAdd)

expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 20:01:02.003')
})
it('subtract Duration object returns correct date', () => {
const baseDate = dayjs('2022-06-26T14:01:02.003')
const durationToAdd = dayjs.duration(6, 'hours')
const testDate = baseDate.subtract(durationToAdd)

expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 08:01:02.003')
})

it('add number with unit returns correct date', () => {
const baseDate = dayjs('2022-06-26T14:01:02.003')
const testDate = baseDate.add(6, 'hours')

expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 20:01:02.003')
})
it('subtract number with unit returns correct date', () => {
const baseDate = dayjs('2022-06-26T14:01:02.003')
const testDate = baseDate.subtract(6, 'hours')

expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 08:01:02.003')
})

it('parse string returns correct date', () => {
const testDate = dayjs('2022-06-26T14:01:02.003')

expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 14:01:02.003')
})
it('parse object returns correct date', () => {
const testDate = dayjs({
year: '2022',
month: '05',
day: '26',
hour: '14',
minute: '01',
second: '02',
millisecond: '003'
})

expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 14:01:02.003')
})

it('set hour with number returns correct date', () => {
const baseDate = dayjs('2022-06-26T14:01:02.003')
const testDate = baseDate.hour(10)

expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 10:01:02.003')
})
it('set hour with object returns correct date', () => {
const baseDate = dayjs('2022-06-26T14:01:02.003')
const testDate = baseDate.set({ hour: '10' })

expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 10:01:02.003')
})
})
79 changes: 79 additions & 0 deletions test/issues/issue2027.swapped-order.test.js
@@ -0,0 +1,79 @@
import MockDate from 'mockdate'
import dayjs from '../../src'
import duration from '../../src/plugin/duration'
import objectSupport from '../../src/plugin/objectSupport'

dayjs.extend(duration)
dayjs.extend(objectSupport)

beforeEach(() => {
MockDate.set(new Date())
})

afterEach(() => {
MockDate.reset()
})

// issue 2027
describe('issue 2027 - order objectSupport > Duration', () => {
it('add Duration object returns correct date', () => {
const baseDate = dayjs('2022-06-26T14:01:02.003')
const durationToAdd = dayjs.duration(6, 'hours')
const testDate = baseDate.add(durationToAdd)

expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 20:01:02.003')
})

it('subtract Duration object returns correct date', () => {
const baseDate = dayjs('2022-06-26T14:01:02.003')
const durationToAdd = dayjs.duration(6, 'hours')
const testDate = baseDate.subtract(durationToAdd)

expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 08:01:02.003')
})

it('add number with unit returns correct date', () => {
const baseDate = dayjs('2022-06-26T14:01:02.003')
const testDate = baseDate.add(6, 'hours')

expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 20:01:02.003')
})
it('subtract number with unit returns correct date', () => {
const baseDate = dayjs('2022-06-26T14:01:02.003')
const testDate = baseDate.subtract(6, 'hours')

expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 08:01:02.003')
})

it('parse string returns correct date', () => {
const testDate = dayjs('2022-06-26T14:01:02.003')

expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 14:01:02.003')
})
it('parse object returns correct date', () => {
const testDate = dayjs({
year: '2022',
month: '05',
day: '26',
hour: '14',
minute: '01',
second: '02',
millisecond: '003'
})

expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 14:01:02.003')
})

it('set hour with number returns correct date', () => {
const baseDate = dayjs('2022-06-26T14:01:02.003')
const testDate = baseDate.hour(10)

expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 10:01:02.003')
})
it('set hour with object returns correct date', () => {
const baseDate = dayjs('2022-06-26T14:01:02.003')
const testDate = baseDate.set({ hour: '10' })

expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 10:01:02.003')
})
})

0 comments on commit c9370ea

Please sign in to comment.