-
Notifications
You must be signed in to change notification settings - Fork 10
[#586] Fix wrong dates due to offset of time #127
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test shouldn't be here written for trials.registration_date
, as it's not only related to it. Instead, extract the pgTypes configuration to a separate file (e.g. config/pg_types.js
or similar) and write a test for that (e.g. test/config/pg_types.js
).
You can write the test by using the pgTypes.getTypeParser()
function and unit testing both functions. This would both guarantee that they're set up correctly and that they behaviour is correct.
const pgTypes = require('pg').types; | ||
|
||
function parseDate(val) { | ||
return new Date(Date.parse(val)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it possible for parseDate()
to be called with null values as well? If so, it needs to handle this case, similarly to parseDateArray
return p.parse(); | ||
} | ||
pgTypes.setTypeParser(1082, parseDate); | ||
pgTypes.setTypeParser(1182, parseDateArray); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When you move this to a separate file, please remove these magic numbers 1082
and 1182
, using a constant like DATE_OID
, so it gets more readable.
988363e
to
de9a25f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @georgiana-b, please check my comments inline. Also, instead of getting the methods on each test (i.e. pgTypes.getTypeParser(DATE_OID)
, you could get them at the beginning of the test, next to where you define the DATE_OID
constant, like const parseDate = pgTypes.getTypeParser(DATE_OID);
to make the code a bit more DRY.
|
||
it('returns null when value is null', () => { | ||
let testDate = null; | ||
should.equal(pgTypes.getTypeParser(DATE_OID)(testDate), null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use should(pgTypes.getTypeParser(DATE_OID)(testDate)).equal(null)
instead, to follow the pattern of the rest of the tests
|
||
it('raises when value is invalid', () => { | ||
let testDate = 'not a date'; | ||
pgTypes.getTypeParser(DATE_OID).bind(null, testDate).should.throw(/^Invalid Date/); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are you using .bind()
here instead of simply calling pgTypes.getTypeParser(DATE_OID)(testDate)
? Did you have issues with the latter?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used .bind()
here because if I just do pgTypes.getTypeParser(DATE_OID)(testDate).should.throw(/^Invalid Date/)
the tests fail with this error:
1) parseDate raises when value is invalid:
Error: Invalid Date
at parseDate (config/pg_types.js:9:650)
at Context.it (test/config/pg_types.js:25:36)
let testArray = `{${testDate}}`; | ||
let expectedDate = new Date(testDate).toISOString(); | ||
let resultedArray = pgTypes.getTypeParser(DATE_ARRAY_OID)(testArray); | ||
resultedArray.map((date) => date.toISOString()).should.containEql(expectedDate); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of testing that it contains the date, you can use deepEquals
, to make sure the entire array is what you expect, not that it has a single element. Like:
should(resultedArray).deepEqual([
expectedDate,
])
I don't think you need to convert toISOString()
either.
|
||
it('returns null when value is null', () => { | ||
let testArray = null; | ||
should.equal(pgTypes.getTypeParser(DATE_ARRAY_OID)(testArray), null); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use should(foo).equal(bar)
it('returns empty array when there are no values', () => { | ||
let testArray = `{}`; | ||
let resultedArray = pgTypes.getTypeParser(DATE_ARRAY_OID)(testArray); | ||
resultedArray.should.be.empty; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You need to call the function, like should(resultedArray).be.empty()
, otherwise it isn't testing anything
|
||
it('raises when one of the values is invalid', () => { | ||
let testArray = `{2016-07-08, null}`; | ||
pgTypes.getTypeParser(DATE_ARRAY_OID).bind(null, testArray).should.throw(/^Invalid Date/); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this is really throwing an exception. The should.throw()
takes a block, like:
should(() => pgTypes.getTypeParser(DATE_ARRAY_OID)(testArray)).throw(/^Invalid Date/)
Also, from the code, it doesn't look like it'll throw an error here, but simply return an array [Date(2016-07-08), null]
, which seems like the correct behaviour to me.
if (!value) { | ||
date = null; | ||
} else { | ||
throw new Error('Invalid Date'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As this is coming from Postgres, I don't think we need to validate dates here, as Postgres would already have done that for us (if I understand it correctly). Here we just need to deal with null
values (and maybe undefined, but we can do a general if (!value) { return null; }
to cover both cases)
@nightsh Please take a look at this and approve if you think it's ok. |
|
||
const p = pgTypes.arrayParser.create(value, (entry) => { | ||
let parsedEntry = entry; | ||
if (String(entry).toLowerCase() !== String(null)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To clarify why is this here: null
value only enters the function as the string 'null'
. This condition works with either version of it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left some comments, please check them out before merging (and push changes if you see fit).
}); | ||
|
||
it('returns empty array when there are no values', () => { | ||
let testArray = `{}`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would've named this testPgArray
, just to avoid any confusions with "regular" arrays delimited by square brackets.
|
||
}); | ||
|
||
describe('parseDateArray', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it('calls parseDate() on single array items')
For when you pass it an array of a single item. So we'd avoid creating an interval (unless we really want to).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An array of dates does not represent an interval in this case. It's just a normal array with date values.
return parsedEntry; | ||
}); | ||
|
||
return p.parse(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bit unclear what p
means, unless you go back up to see it's a parser. Might be worth renaming it to parser
.
opentrials/opentrials#686
After a charming journey among the horrors of JS date handling, this is the best thing I could come up with.
Imho expressed in this node-pg-types issue, the
Date
-only fields should not have any time information attached to them. However, seems that most JS developers (including the ones atnode-elasticsearch
) don't share my opinion so I had to settle with this for consistency.