From fcf82797821dd88392e33de46cb48a4703ce30e0 Mon Sep 17 00:00:00 2001 From: Haroen Viaene Date: Sun, 25 Nov 2018 20:58:57 +0100 Subject: [PATCH] fix(gatsby-plugin-filesystem): throw meaningful errors on bad inputs fixes #6643 I also fell for this error before, sinc the original errors are swallowed (and fairly unclear too, because of the indirection). Adding validation was suggested in linked issue, so I went for this, since I didn't see any already used object validation like "ow" in use here. --- .../src/__tests__/create-remote-file-node.js | 55 +++++++++++++++++++ .../src/create-remote-file-node.js | 18 ++++++ 2 files changed, 73 insertions(+) create mode 100644 packages/gatsby-source-filesystem/src/__tests__/create-remote-file-node.js diff --git a/packages/gatsby-source-filesystem/src/__tests__/create-remote-file-node.js b/packages/gatsby-source-filesystem/src/__tests__/create-remote-file-node.js new file mode 100644 index 0000000000000..92f4622844bf3 --- /dev/null +++ b/packages/gatsby-source-filesystem/src/__tests__/create-remote-file-node.js @@ -0,0 +1,55 @@ +const createRemoteFileNode = require(`../create-remote-file-node`) + +describe(`create-remote-file-node`, () => { + const defaultArgs = { + url: ``, + store: {}, + cache: {}, + createNode: jest.fn(), + createNodeId: jest.fn(), + } + + it(`throws on invalid inputs: createNode`, () => { + expect(() => { + createRemoteFileNode({ + ...defaultArgs, + createNode: undefined, + }) + }).toThrowErrorMatchingInlineSnapshot( + `"createNode must be a function, was undefined"` + ) + }) + + it(`throws on invalid inputs: createNodeId`, () => { + expect(() => { + createRemoteFileNode({ + ...defaultArgs, + createNodeId: undefined, + }) + }).toThrowErrorMatchingInlineSnapshot( + `"createNodeId must be a function, was undefined"` + ) + }) + + it(`throws on invalid inputs: cache`, () => { + expect(() => { + createRemoteFileNode({ + ...defaultArgs, + cache: undefined, + }) + }).toThrowErrorMatchingInlineSnapshot( + `"cache must be the Gatsby cache, was undefined"` + ) + }) + + it(`throws on invalid inputs: store`, () => { + expect(() => { + createRemoteFileNode({ + ...defaultArgs, + store: undefined, + }) + }).toThrowErrorMatchingInlineSnapshot( + `"store must be the redux store, was undefined"` + ) + }) +}) diff --git a/packages/gatsby-source-filesystem/src/create-remote-file-node.js b/packages/gatsby-source-filesystem/src/create-remote-file-node.js index b7eaa80b41351..ecd46827215dd 100644 --- a/packages/gatsby-source-filesystem/src/create-remote-file-node.js +++ b/packages/gatsby-source-filesystem/src/create-remote-file-node.js @@ -292,6 +292,24 @@ module.exports = ({ createNodeId, ext = null, }) => { + // validation of the input + // without this it's notoriously easy to pass in the wrong `createNodeId` + // see gatsbyjs/gatsby#6643 + if (typeof createNodeId !== `function`) { + throw new Error( + `createNodeId must be a function, was ${typeof createNodeId}` + ) + } + if (typeof createNode !== `function`) { + throw new Error(`createNode must be a function, was ${typeof createNode}`) + } + if (typeof store !== `object`) { + throw new Error(`store must be the redux store, was ${typeof store}`) + } + if (typeof cache !== `object`) { + throw new Error(`cache must be the Gatsby cache, was ${typeof cache}`) + } + // Check if we already requested node for this remote file // and return stored promise if we did. if (processingCache[url]) {