Skip to content

Commit

Permalink
Field inferring changes and cleanup (#3688)
Browse files Browse the repository at this point in the history
* remove not needed edge case for infering array of objects to improve code readability

* don't lose field args and resolve function when infering array (fixes date format options not available in arrays of dates)

* move infering date field to seperate file to improve code readability

* don't recreate date field definition for every date field - we can reuse same object

* create dedicated Date graphql scalar (based on string scalar) for date fields

* pass fieldName to resolver when filtering on types with custom resolvers (date type fields now rely on fieldname info being passed)

* use already constructed nextselector instead of rebuilding it again

* move infering file field to separate file to improve code readability

* create file type field object just once and reuse it

* move trying to infer Files from string paths to inferGraphQLType function where rest of value based inferring is done

* add tests for inferring File from string paths

* add tests for inferring date type from string, array of strings and filtering date fields, move date related test to seperate date test suite
  • Loading branch information
pieh authored and KyleAMathews committed Feb 9, 2018
1 parent 68fe2ef commit 820d737
Show file tree
Hide file tree
Showing 8 changed files with 566 additions and 345 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`GraphQL type inferance Handles dates Date type inference 1`] = `
Object {
"data": Object {
"listNode": Array [
Object {
"dateObject": "2012-11-05T00:00:00.000Z",
},
Object {
"dateObject": "2012-11-05T00:00:00.000Z",
},
],
},
}
`;

exports[`GraphQL type inferance Infers graphql type from array of nodes 1`] = `
Object {
"data": Object {
Expand Down Expand Up @@ -115,18 +130,3 @@ Object {
},
}
`;

exports[`GraphQL type inferance handles date objects 1`] = `
Object {
"data": Object {
"listNode": Array [
Object {
"dateObject": "2012-11-05T00:00:00.000Z",
},
Object {
"dateObject": "2012-11-05T00:00:00.000Z",
},
],
},
}
`;
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ function queryResult(nodes, query, { types = [] } = {}) {
describe(`GraphQL Input args`, () => {
const nodes = [
{
index: 0,
name: `The Mad Max`,
hair: 1,
date: `2006-07-22T22:39:53.000Z`,
Expand All @@ -103,9 +104,9 @@ describe(`GraphQL Input args`, () => {
boolean: true,
},
{
index: 1,
name: `The Mad Wax`,
hair: 2,
date: `2006-07-22T22:39:53.000Z`,
anArray: [1, 2, 5, 4],
frontmatter: {
date: `2006-07-22T22:39:53.000Z`,
Expand All @@ -116,9 +117,10 @@ describe(`GraphQL Input args`, () => {
boolean: false,
},
{
index: 2,
name: `The Mad Wax`,
hair: 0,
date: `2006-07-22T22:39:53.000Z`,
date: `2006-07-29T22:39:53.000Z`,
frontmatter: {
date: `2006-07-22T22:39:53.000Z`,
title: `The world of shave and adventure`,
Expand Down Expand Up @@ -375,6 +377,23 @@ describe(`GraphQL Input args`, () => {
expect(result.data.allNode.edges[0].node.name).toEqual(`The Mad Wax`)
})

it(`filters date fields`, async () => {
let result = await queryResult(
nodes,
`
{
allNode(filter: {date: { ne: null }}) {
edges { node { index }}
}
}
`
)
expect(result.errors).not.toBeDefined()
expect(result.data.allNode.edges.length).toEqual(2)
expect(result.data.allNode.edges[0].node.index).toEqual(0)
expect(result.data.allNode.edges[1].node.index).toEqual(2)
})

it(`sorts results`, async () => {
let result = await queryResult(
nodes,
Expand Down
173 changes: 148 additions & 25 deletions packages/gatsby/src/schema/__tests__/infer-graphql-type-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ const {
GraphQLList,
GraphQLSchema,
} = require(`graphql`)
const path = require(`path`)
const normalizePath = require(`normalize-path`)

const { inferObjectStructureFromNodes } = require(`../infer-graphql-type`)

function queryResult(nodes, fragment, { types = [] } = {}) {
Expand Down Expand Up @@ -39,7 +42,9 @@ function queryResult(nodes, fragment, { types = [] } = {}) {
${fragment}
}
}
`
`,
null,
{ path: `/` }
)
}

Expand Down Expand Up @@ -118,29 +123,6 @@ describe(`GraphQL type inferance`, () => {
expect(result.data.listNode[0].number).toEqual(1.1)
})

it(`handles integer with valid date format`, async () => {
let result = await queryResult(
[{ number: 2018 }, { number: 1987 }],
`
number
`
)
expect(result.data.listNode[0].number).toEqual(2018)
})

it(`handles date objects`, async () => {
let result = await queryResult(
[
{ dateObject: new Date(Date.UTC(2012, 10, 5)) },
{ dateObject: new Date(Date.UTC(2012, 10, 5)) },
],
`
dateObject
`
)
expect(result).toMatchSnapshot()
})

it(`filters out empty objects`, async () => {
let result = await queryResult(
[{ foo: {}, bar: `baz` }],
Expand Down Expand Up @@ -206,8 +188,149 @@ describe(`GraphQL type inferance`, () => {
expect(Object.keys(fields.foo.type.getFields())).toHaveLength(4)
})

describe(`Handles dates`, () => {
it(`Handles integer with valid date format`, async () => {
let result = await queryResult(
[{ number: 2018 }, { number: 1987 }],
`
number
`
)
expect(result.data.listNode[0].number).toEqual(2018)
})

it(`Date type inference`, async () => {
let result = await queryResult(
[
{ dateObject: new Date(Date.UTC(2012, 10, 5)) },
{ dateObject: new Date(Date.UTC(2012, 10, 5)) },
],
`
dateObject
`
)
expect(result).toMatchSnapshot()
})

it(`Infers from date strings`, async () => {
let result = await queryResult(
[{ date: `1012-11-01` }],
`
date(formatString:"DD.MM.YYYY")
`
)

expect(result.errors).not.toBeDefined()
expect(result.data.listNode[0].date).toEqual(`01.11.1012`)
})

it(`Infers from arrays of date strings`, async () => {
let result = await queryResult(
[{ date: [`1012-11-01`, `10390203`] }],
`
date(formatString:"DD.MM.YYYY")
`
)

expect(result.errors).not.toBeDefined()
expect(result.data.listNode[0].date.length).toEqual(2)
expect(result.data.listNode[0].date[0]).toEqual(`01.11.1012`)
expect(result.data.listNode[0].date[1]).toEqual(`03.02.1039`)
})
})

xdescribe(`Linked inference from config mappings`)
xdescribe(`Linked inference from file URIs`)

describe(`Linked inference from file URIs`, () => {
let store, types, dir

beforeEach(() => {
;({ store } = require(`../../redux`))

const { setFileNodeRootType } = require(`../types/type-file`)
const fileType = {
name: `File`,
nodeObjectType: new GraphQLObjectType({
name: `File`,
fields: inferObjectStructureFromNodes({
nodes: [{ id: `file_1`, absolutePath: `path`, dir: `path` }],
types: [{ name: `File` }],
}),
}),
}

types = [fileType]
setFileNodeRootType(fileType.nodeObjectType)

dir = normalizePath(path.resolve(`/path/`))

store.dispatch({
type: `CREATE_NODE`,
payload: {
id: `parent`,
internal: { type: `File` },
absolutePath: normalizePath(path.resolve(dir, `index.md`)),
dir: dir,
},
})
store.dispatch({
type: `CREATE_NODE`,
payload: {
id: `file_1`,
internal: { type: `File` },
absolutePath: normalizePath(path.resolve(dir, `file_1.jpg`)),
dir,
},
})
store.dispatch({
type: `CREATE_NODE`,
payload: {
id: `file_2`,
internal: { type: `File` },
absolutePath: normalizePath(path.resolve(dir, `file_2.txt`)),
dir,
},
})
})

it(`Links to file node`, async () => {
let result = await queryResult(
[{ file: `./file_1.jpg`, parent: `parent` }],
`
file {
absolutePath
}
`,
{ types }
)

expect(result.errors).not.toBeDefined()
expect(result.data.listNode[0].file.absolutePath).toEqual(
normalizePath(path.resolve(dir, `file_1.jpg`))
)
})

it(`Links to array of file nodes`, async () => {
let result = await queryResult(
[{ files: [`./file_1.jpg`, `./file_2.txt`], parent: `parent` }],
`
files {
absolutePath
}
`,
{ types }
)

expect(result.errors).not.toBeDefined()
expect(result.data.listNode[0].files.length).toEqual(2)
expect(result.data.listNode[0].files[0].absolutePath).toEqual(
normalizePath(path.resolve(dir, `file_1.jpg`))
)
expect(result.data.listNode[0].files[1].absolutePath).toEqual(
normalizePath(path.resolve(dir, `file_2.txt`))
)
})
})

describe(`Linked inference by __NODE convention`, () => {
let store, types
Expand Down
9 changes: 9 additions & 0 deletions packages/gatsby/src/schema/build-node-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const {
const { nodeInterface } = require(`./node-interface`)
const { getNodes, getNode, getNodeAndSavePathDependency } = require(`../redux`)
const { createPageDependency } = require(`../redux/actions/add-page-dependency`)
const { setFileNodeRootType } = require(`./types/type-file`)

import type { ProcessedNodeType } from "./infer-graphql-type"

Expand All @@ -27,6 +28,9 @@ module.exports = async () => {
const types = _.groupBy(getNodes(), node => node.internal.type)
const processedTypes: TypeMap = {}

// Reset stored File type to not point to outdated type definition
setFileNodeRootType(null)

function createNodeFields(type: ProcessedNodeType) {
const defaultNodeFields = {
id: {
Expand Down Expand Up @@ -183,6 +187,11 @@ module.exports = async () => {
}

processedTypes[_.camelCase(typeName)] = proccesedType

// Special case to construct linked file type used by type inferring
if (typeName === `File`) {
setFileNodeRootType(gqlType)
}
}

// Create node types and node fields for nodes that have a resolve function.
Expand Down
Loading

0 comments on commit 820d737

Please sign in to comment.