-
Notifications
You must be signed in to change notification settings - Fork 10.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(gatsby): add support for microsecond and alternative iso datetim…
…e formats (#12533) * Add support for microsecond and alternative iso datetime formats
- Loading branch information
1 parent
8d8d39b
commit dfe93ee
Showing
2 changed files
with
428 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,383 @@ | ||
const { store } = require(`../../../redux`) | ||
const { build } = require(`../..`) | ||
const { isDate } = require(`../date`) | ||
require(`../../../db/__tests__/fixtures/ensure-loki`)() | ||
|
||
// Timestamps grabbed from https://github.com/moment/moment/blob/2e2a5b35439665d4b0200143d808a7c26d6cd30f/src/test/moment/is_valid.js | ||
|
||
describe(`isDate`, () => { | ||
it.each([ | ||
`1970`, | ||
`2019`, | ||
`1970-01`, | ||
`2019-01`, | ||
`1970-01-01`, | ||
`2010-01-01`, | ||
`2010-01-30`, | ||
`19700101`, | ||
`20100101`, | ||
`20100130`, | ||
`2010-01-30T23+00:00`, | ||
`2010-01-30T23:59+00:00`, | ||
`2010-01-30T23:59:59+00:00`, | ||
`2010-01-30T23:59:59.999+00:00`, | ||
`2010-01-30T23:59:59.999-07:00`, | ||
`2010-01-30T00:00:00.000+07:00`, | ||
`2010-01-30T23:59:59.999-07`, | ||
`2010-01-30T00:00:00.000+07`, | ||
`2010-01-30T23Z`, | ||
`2010-01-30T23:59Z`, | ||
`2010-01-30T23:59:59Z`, | ||
`2010-01-30T23:59:59.999Z`, | ||
`2010-01-30T00:00:00.000Z`, | ||
`1970-01-01T00:00:00.000001Z`, | ||
`2012-04-01T00:00:00-05:00`, | ||
`2012-11-12T00:00:00+01:00`, | ||
])(`should return true for valid ISO 8601: %s`, dateString => { | ||
expect(isDate(dateString)).toBeTruthy() | ||
}) | ||
|
||
it.each([ | ||
`2010-01-30 23+00:00`, | ||
`2010-01-30 23:59+00:00`, | ||
`2010-01-30 23:59:59+00:00`, | ||
`2010-01-30 23:59:59.999+00:00`, | ||
`2010-01-30 23:59:59.999-07:00`, | ||
`2010-01-30 00:00:00.000+07:00`, | ||
`2010-01-30 23:59:59.999-07`, | ||
`2010-01-30 00:00:00.000+07`, | ||
`1970-01-01 00:00:00.000Z`, | ||
`2012-04-01 00:00:00-05:00`, | ||
`2012-11-12 00:00:00+01:00`, | ||
`1970-01-01 00:00:00.0000001 Z`, | ||
`1970-01-01 00:00:00.000 Z`, | ||
`1970-01-01 00:00:00 Z`, | ||
`1970-01-01 000000 Z`, | ||
`1970-01-01 00:00 Z`, | ||
`1970-01-01 00 Z`, | ||
])(`should return true for ISO 8601 (no T, extra space): %s`, dateString => { | ||
expect(isDate(dateString)).toBeTruthy() | ||
}) | ||
|
||
it.each([`1970-W31`, `2006-W01`, `1970W31`, `2009-W53-7`, `2009W537`])( | ||
`should return true for ISO 8601 week dates: %s`, | ||
dateString => { | ||
expect(isDate(dateString)).toBeTruthy() | ||
} | ||
) | ||
|
||
it.each([`1970-334`, `1970334`, `2090-001`, `2090001`])( | ||
`should return true for ISO 8601 ordinal dates: %s`, | ||
dateString => { | ||
expect(isDate(dateString)).toBeTruthy() | ||
} | ||
) | ||
|
||
it.each([`2018-08-31T23:25:16.019345+02:00`, `2018-08-31T23:25:16.019345Z`])( | ||
`should return true for microsecond precision: %s`, | ||
dateString => { | ||
expect(isDate(dateString)).toBeTruthy() | ||
} | ||
) | ||
|
||
it.skip.each([ | ||
`2018-08-31T23:25:16.019345123+02:00`, | ||
`2018-08-31T23:25:16.019345123Z`, | ||
])(`should return true for nanosecond precision: %s`, dateString => { | ||
expect(isDate(dateString)).toBeTruthy() | ||
}) | ||
|
||
it.skip.each([`2018-08-31T23:25:16.012345678901+02:00`])( | ||
`should return false for precision beyond 9 digits: %s`, | ||
dateString => { | ||
expect(isDate(dateString)).toBeFalsy() | ||
} | ||
) | ||
|
||
it.each([ | ||
`2010-00-00`, | ||
`2010-01-00`, | ||
`2010-01-40`, | ||
`2010-01-01T24:01`, // 24:00:00 is actually valid | ||
`2010-01-01T23:60`, | ||
`2010-01-01T23:59:60`, | ||
`2010-01-40T23:59:59.9999`, | ||
`2010-00-00T+00:00`, | ||
`2010-01-00T+00:00`, | ||
`2010-01-40T+00:00`, | ||
`2010-01-40T24:01+00:00`, | ||
`2010-01-40T23:60+00:00`, | ||
`2010-01-40T23:59:60+00:00`, | ||
`2010-01-40T23:59:59.9999+00:00`, | ||
`2010-01-40T23:59:59,9999+00:00`, | ||
`2012-04-01T00:00:00-5:00`, // should be -05:00 | ||
`2012-04-01T00:00:00+1:00`, // should be +01:00 | ||
undefined, | ||
`undefined`, | ||
null, | ||
`null`, | ||
[], | ||
{}, | ||
``, | ||
` `, | ||
`2012-04-01T00:basketball`, | ||
])(`should return false for invalid ISO 8601: %s`, dateString => { | ||
expect(isDate(dateString)).toBeFalsy() | ||
}) | ||
|
||
it.skip.each([ | ||
1371065286, | ||
1379066897.0, | ||
1379066897.7, | ||
1379066897.0, | ||
1379066897.07, | ||
1379066897.17, | ||
1379066897.0, | ||
1379066897.007, | ||
1379066897.017, | ||
1379066897.157, | ||
`1371065286`, | ||
`1379066897.`, | ||
`1379066897.0`, | ||
`1379066897.7`, | ||
`1379066897.00`, | ||
`1379066897.07`, | ||
`1379066897.17`, | ||
`1379066897.000`, | ||
`1379066897.007`, | ||
`1379066897.017`, | ||
`1379066897.157`, | ||
])(`should return true for unix timestamps: %s`, dateString => { | ||
expect(isDate(dateString)).toBeTruthy() | ||
}) | ||
}) | ||
|
||
const nodes = [ | ||
{ | ||
id: `id1`, | ||
internal: { type: `Test` }, | ||
testDate: new Date(), | ||
explicitValidDate: `2010-01-30T23:59:59.999-07:00`, | ||
inferredValidDate: `1970-01-01T00:00:00.000Z`, | ||
validYYYY: `1970`, | ||
validYYMM: `2019-01`, | ||
validYYMMDD: `2010-01-30`, | ||
validYYMMDDNoDash: `20100101`, | ||
validISO1: `2010-01-30T23:59:59.999+00:00`, | ||
validISO2: `2010-01-30T23:59:59.999-07:00`, | ||
validISO3: `2010-01-30T00:00:00.000+07:00`, | ||
validISO4: `2010-01-30T23:59:59.999-07`, | ||
validISO5: `2010-01-30T00:00:00.000+07`, | ||
validISO6: `2010-01-30 00:00:00.000Z`, | ||
validISO7: `1970-01-01T00:00:00.000Z`, | ||
validISO8: `2012-04-01T00:00:00-05:00`, | ||
validISO9: `2012-11-12T00:00:00+01:00`, | ||
|
||
validOrdinal1: `1970-334`, | ||
validOrdinal2: `1970334`, | ||
validOrdinal3: `2090-001`, | ||
validOrdinal4: `2090001`, | ||
|
||
validWeek1: `1970-W31`, | ||
validWeek2: `2006-W01`, | ||
validWeek3: `1970W31`, | ||
validWeek4: `2009-W53-7`, | ||
validWeek5: `2009W537`, | ||
|
||
validMicrosecond1: `2018-08-31T23:25:16.019345+02:00`, | ||
validMicrosecond2: `2018-08-31T23:25:16.019345Z`, | ||
|
||
validNanosecond1: `2018-08-31T23:25:16.019345123+02:00`, | ||
validNanosecond2: `2018-08-31T23:25:16.019345123Z`, | ||
|
||
invalidHighPrecision: `2018-08-31T23:25:16.01234567899993+02:00`, | ||
|
||
invalidDate1: `2010-00-00`, | ||
invalidDate2: `2010-01-00`, | ||
invalidDate3: `2010-01-40`, | ||
invalidDate4: `2010-01-01T24:01`, // 24:00:00 is actually valid | ||
invalidDate5: `2010-01-01T23:60`, | ||
invalidDate6: `2010-01-01T23:59:60`, | ||
invalidDate7: `2010-01-40T23:59:59.9999`, | ||
|
||
invalidDate8: undefined, | ||
invalidDate9: `undefined`, | ||
invalidDate10: null, | ||
invalidDate11: `null`, | ||
invalidDate12: [], | ||
invalidDate13: {}, | ||
invalidDate14: ``, | ||
invalidDate15: ` `, | ||
invalidDate16: `2012-04-01T00:basketball`, | ||
}, | ||
] | ||
|
||
describe(`dateResolver`, () => { | ||
beforeEach(() => { | ||
store.dispatch({ type: `DELETE_CACHE` }) | ||
nodes.forEach(node => | ||
store.dispatch({ type: `CREATE_NODE`, payload: { ...node } }) | ||
) | ||
}) | ||
|
||
const buildTestSchema = async ({ | ||
infer = true, | ||
addDefaultResolvers = true, | ||
}) => { | ||
const inferDirective = infer ? `@infer` : `@dontInfer` | ||
const noDefaultResolvers = addDefaultResolvers ? `false` : `true` | ||
const typeDefs = [ | ||
` | ||
type Test implements Node ${inferDirective}(noDefaultResolvers: ${noDefaultResolvers}) { | ||
testDate: Date | ||
explicitValidDate: Date | ||
invalidHighPrecision: Date | ||
invalidDate8: Date | ||
invalidDate9: Date | ||
invalidDate10: Date | ||
invalidDate11: Date | ||
invalidDate12: Date | ||
invalidDate13: Date | ||
invalidDate14: Date | ||
invalidDate15: Date | ||
invalidDate16: Date | ||
}`, | ||
] | ||
typeDefs.forEach(def => | ||
store.dispatch({ type: `CREATE_TYPES`, payload: def }) | ||
) | ||
|
||
await build({}) | ||
return store.getState().schema | ||
} | ||
|
||
it(`can properly resolve datetimes`, async () => { | ||
const schema = await buildTestSchema({}) | ||
const fields = schema.getType(`Test`).getFields() | ||
|
||
expect(fields.testDate.resolve).toBeDefined() | ||
expect(fields.explicitValidDate.resolve).toBeDefined() | ||
expect(fields.inferredValidDate.resolve).toBeDefined() | ||
expect(fields.validYYYY.resolve).toBeDefined() | ||
expect(fields.validYYMM.resolve).toBeDefined() | ||
expect(fields.validYYMMDD.resolve).toBeDefined() | ||
expect(fields.validYYMMDDNoDash.resolve).toBeDefined() | ||
|
||
expect(fields.validISO1.resolve).toBeDefined() | ||
expect(fields.validISO2.resolve).toBeDefined() | ||
expect(fields.validISO3.resolve).toBeDefined() | ||
expect(fields.validISO4.resolve).toBeDefined() | ||
expect(fields.validISO5.resolve).toBeDefined() | ||
expect(fields.validISO6.resolve).toBeDefined() | ||
expect(fields.validISO7.resolve).toBeDefined() | ||
expect(fields.validISO8.resolve).toBeDefined() | ||
expect(fields.validISO9.resolve).toBeDefined() | ||
|
||
expect(fields.validOrdinal1.resolve).toBeDefined() | ||
expect(fields.validOrdinal2.resolve).toBeDefined() | ||
expect(fields.validOrdinal3.resolve).toBeDefined() | ||
expect(fields.validOrdinal4.resolve).toBeDefined() | ||
|
||
expect(fields.validWeek1.resolve).toBeDefined() | ||
expect(fields.validWeek2.resolve).toBeDefined() | ||
expect(fields.validWeek3.resolve).toBeDefined() | ||
expect(fields.validWeek4.resolve).toBeDefined() | ||
expect(fields.validWeek5.resolve).toBeDefined() | ||
|
||
expect(fields.validMicrosecond1.resolve).toBeDefined() | ||
expect(fields.validMicrosecond2.resolve).toBeDefined() | ||
|
||
expect(fields.validNanosecond1.resolve).toBeDefined() | ||
expect(fields.validNanosecond2.resolve).toBeDefined() | ||
// expect(fields.invalidHighPrecision.resolve).toBeDefined() | ||
expect(fields.invalidDate1.resolve).toBeUndefined() | ||
expect(fields.invalidDate2.resolve).toBeUndefined() | ||
expect(fields.invalidDate3.resolve).toBeUndefined() | ||
expect(fields.invalidDate4.resolve).toBeUndefined() | ||
expect(fields.invalidDate5.resolve).toBeUndefined() | ||
expect(fields.invalidDate6.resolve).toBeUndefined() | ||
expect(fields.invalidDate7.resolve).toBeUndefined() | ||
expect(fields.invalidDate8.resolve).toBeUndefined() | ||
expect(fields.invalidDate9.resolve).toBeUndefined() | ||
expect(fields.invalidDate10.resolve).toBeUndefined() | ||
expect(fields.invalidDate11.resolve).toBeUndefined() | ||
expect(fields.invalidDate12.resolve).toBeUndefined() | ||
expect(fields.invalidDate13.resolve).toBeUndefined() | ||
expect(fields.invalidDate14.resolve).toBeUndefined() | ||
expect(fields.invalidDate15.resolve).toBeUndefined() | ||
expect(fields.invalidDate16.resolve).toBeUndefined() | ||
}) | ||
|
||
it.each([ | ||
`2018-01-28T23:59:59.999-07:00`, | ||
`2018-01-29T00:00:00.000Z`, | ||
`2018-01-29`, | ||
`20180129`, | ||
`2018-01-29T23:59:59.999+00:00`, | ||
`2018-01-28T19:59:59.999-07:00`, | ||
`2018-01-30T06:00:00.001+07:00`, | ||
`2018-01-28 17:00:00.001-07`, | ||
`2018-01-30 04:00:00.001+07`, | ||
`2018-01-29 04:00:00.001Z`, | ||
`2018-01-29 04:00:00.001 Z`, | ||
`2018-01-29 04:00:00 Z`, | ||
`2018-01-29 04:00 Z`, | ||
`2018-01-29 04 Z`, | ||
`2018-01-28T17:00:00.001-07`, | ||
`2018-01-30T04:00:00.001+07`, | ||
`2018-01-29 00:00:00.001Z`, | ||
`2018-01-29T00:00:00.001Z`, | ||
`2018-01-28 23:00:00-05:00`, | ||
`2018-01-29 23:00:00+01:00`, | ||
`2018-01-28T23:00:00-05:00`, | ||
`2018-01-29T23:00:00+01:00`, | ||
`2018-029`, | ||
`2018029`, | ||
`2018-W05`, | ||
`2018W05`, | ||
`2018-W05-1`, | ||
`2018-01-29T23:25:16.019345+02:00`, | ||
`2018-01-29T23:25:16.019345Z`, | ||
// Seems to not require nanosecond definition to not fail | ||
`2018-01-29T23:25:16.019345123+02:00`, | ||
`2018-01-29T23:25:16.019345123Z`, | ||
])(`should return "Jan 29, 2018": %s`, async dateString => { | ||
const schema = await buildTestSchema({}) | ||
const fields = schema.getType(`Test`).getFields() | ||
expect( | ||
fields[`testDate`].resolve( | ||
{ date: dateString }, | ||
{ formatString: `MMM DD, YYYY` }, | ||
{}, | ||
{ | ||
fieldName: `date`, | ||
} | ||
) | ||
).toEqual(`Jan 29, 2018`) | ||
}) | ||
|
||
it.each([ | ||
`2010-00-00`, | ||
`2010-01-00`, | ||
`2010-01-40`, | ||
`2010-01-01T24:01`, | ||
`2010-01-01T23:60`, | ||
`2010-01-01T23:59:60`, | ||
`2010-01-40T23:59:59.9999`, | ||
// Combine with above statement once we figure out why it passes | ||
// `2018-08-31T23:25:16.01234567899993+02:00`, | ||
])(`should return "Invalid Date": %s`, async dateString => { | ||
const schema = await buildTestSchema({}) | ||
const fields = schema.getType(`Test`).getFields() | ||
expect( | ||
fields[`testDate`].resolve( | ||
{ date: dateString }, | ||
{ formatString: `MMM DD, YYYY` }, | ||
{}, | ||
{ | ||
fieldName: `date`, | ||
} | ||
) | ||
).toEqual(`Invalid date`) | ||
}) | ||
}) |
Oops, something went wrong.