Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing Gatsby component with MDX and graphql data

I am trying to write a unit test in Jest for the component 'Step.js', which is used as a template for creating pages dynamically with the GraphQL data. I have provided the fake data in the test, hoping that it would resolve by the GraphQL query. But I got the error message that saying 'Syntax Error: Cannot use import statement outside a module'.

Since then, I tried:

  1. Adding a 'Static Query' mock in the file, hoping that would generate the fake data in the testing environment. But I got the same error message.
  2. Adding 'mdx' in the 'moduleNameMapper' config option. I still got the same error message.
  3. My next attempt might be installing 'Jest-transformer-mdx' to see if I can add it to the 'jest.config.js'.

I just wondering if there is any suggestion for this problem? Or has anyone encounter this before? If you do have some suggestion, please do share! Thanks in advance 👍🏻

Here is code,

Step.js

import React from "react"
import { graphql } from "gatsby"
import { MDXRenderer } from "gatsby-plugin-mdx"
import Layout from "./layout"
import style from "./step.module.css"

export default function Step({ data }) {
  const mdx = data.mdx
  return (
    <div>
      <h1 className={style.title}>{mdx.frontmatter.title}</h1>
      <Layout>
        <MDXRenderer>{mdx.body}</MDXRenderer>
      </Layout>
    </div>
 )
}

export const query = graphql`
  query($slug: String!) {
    mdx(fields: { slug: { eq: $slug } }) {
      body
      frontmatter {
        title
      }
    }
  }
`

Step.test.js

import React from "react"
import renderer from "react-test-renderer"
import { StaticQuery } from "gatsby"
import Step from "../src/components/step"

beforeEach(() => {
  StaticQuery.mockImplementationOnce(({ render }) => {
    render({
        mdx: {
          body: "function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"Homebrew\"\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"It's important to keep your programs up to date, to check to see if anything is outdated, you can use this command:\"), mdx(CommandBox, {\n    mdxType: \"CommandBox\"\n  }, \"brew outdated\"), mdx(\"p\", null, \"And to update:\"), mdx(CommandBox, {\n    mdxType: \"CommandBox\"\n  }, \"brew update\"), mdx(\"p\", null, \"If anything has gone wrong with your installation or update, you can uninstall Homebrew and start again:\"), mdx(CommandBox, {\n    mdxType: \"CommandBox\"\n  }, \"/bin/bash -c \\\"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall.sh)\\\"\"), mdx(StepButton, {\n    to: \"/step-4\",\n    mdxType: \"StepButton\"\n  }));\n}\n;\nMDXContent.isMDXComponent = true;",
          frontmatter: {
            title: "Homebrew"
          },
        },
    })
  })
})


describe("Step component", () => {
  it("render step content on the page", () => {
    const data = {
        mdx: {
          body: "function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"Homebrew\"\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"It's important to keep your programs up to date, to check to see if anything is outdated, you can use this command:\"), mdx(CommandBox, {\n    mdxType: \"CommandBox\"\n  }, \"brew outdated\"), mdx(\"p\", null, \"And to update:\"), mdx(CommandBox, {\n    mdxType: \"CommandBox\"\n  }, \"brew update\"), mdx(\"p\", null, \"If anything has gone wrong with your installation or update, you can uninstall Homebrew and start again:\"), mdx(CommandBox, {\n    mdxType: \"CommandBox\"\n  }, \"/bin/bash -c \\\"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall.sh)\\\"\"), mdx(StepButton, {\n    to: \"/step-4\",\n    mdxType: \"StepButton\"\n  }));\n}\n;\nMDXContent.isMDXComponent = true;",
          frontmatter: {
            title: "Homebrew"
          },
        },
    }

    const tree = renderer.create(<Step data={data}/>).toJSON()
    expect(tree).toMatchSnapshot()
  });
});

jest.config.js

module.exports = {
  transform: {
    "^.+\\.jsx?$": `<rootDir>/jest-preprocess.js`,
  },
  moduleNameMapper: {
    ".+\\.(css|styl|less|sass|scss)$": `identity-obj-proxy`,
    ".+\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": `<rootDir>/__mocks__/file-mock.js`,
  },
  testPathIgnorePatterns: [`node_modules`, `\\.cache`, `<rootDir>.*/public`],
  transformIgnorePatterns: [`node_modules/(?!(gatsby)/)`],
  globals: {
    __PATH_PREFIX__: ``,
  },
  testURL: `http://localhost`,
  setupFiles: [`<rootDir>/loadershim.js`],
}
like image 705
Minsi Yang Avatar asked Oct 15 '25 12:10

Minsi Yang


1 Answers

So after some help, I finally passed the test. It seems like Jest was having trouble finding the 'gatsby-plugin-mdx' module, and its 'MDXRenderer' module. So I mocked them and return the 'children' that was passed in.

import React from "react"
import renderer from "react-test-renderer"
import { StaticQuery } from "gatsby"
import Step from "../src/components/step"


jest.mock("gatsby-plugin-mdx", () => {
  return { MDXRenderer: ({children}) => {
    return <div>{children}</div>;
  } }
});

beforeEach(() => {
  StaticQuery.mockImplementationOnce(({ render }) => {
    render({
        mdx: {
          body: "function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"Homebrew\"\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"It's important to keep your programs up to date, to check to see if anything is outdated, you can use this command:\"), mdx(CommandBox, {\n    mdxType: \"CommandBox\"\n  }, \"brew outdated\"), mdx(\"p\", null, \"And to update:\"), mdx(CommandBox, {\n    mdxType: \"CommandBox\"\n  }, \"brew update\"), mdx(\"p\", null, \"If anything has gone wrong with your installation or update, you can uninstall Homebrew and start again:\"), mdx(CommandBox, {\n    mdxType: \"CommandBox\"\n  }, \"/bin/bash -c \\\"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall.sh)\\\"\"), mdx(StepButton, {\n    to: \"/step-4\",\n    mdxType: \"StepButton\"\n  }));\n}\n;\nMDXContent.isMDXComponent = true;",
          frontmatter: {
            title: "Homebrew"
          },
        },
    })
  })
})


describe("Step component", () => {
  it("render step content on the page", () => {
    const data = {
        mdx: {
          body: "function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }\n\nfunction _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }\n\nfunction _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }\n\n/* @jsxRuntime classic */\n\n/* @jsx mdx */\nvar _frontmatter = {\n  \"title\": \"Homebrew\"\n};\nvar layoutProps = {\n  _frontmatter: _frontmatter\n};\nvar MDXLayout = \"wrapper\";\nreturn function MDXContent(_ref) {\n  var components = _ref.components,\n      props = _objectWithoutProperties(_ref, [\"components\"]);\n\n  return mdx(MDXLayout, _extends({}, layoutProps, props, {\n    components: components,\n    mdxType: \"MDXLayout\"\n  }), mdx(\"p\", null, \"It's important to keep your programs up to date, to check to see if anything is outdated, you can use this command:\"), mdx(CommandBox, {\n    mdxType: \"CommandBox\"\n  }, \"brew outdated\"), mdx(\"p\", null, \"And to update:\"), mdx(CommandBox, {\n    mdxType: \"CommandBox\"\n  }, \"brew update\"), mdx(\"p\", null, \"If anything has gone wrong with your installation or update, you can uninstall Homebrew and start again:\"), mdx(CommandBox, {\n    mdxType: \"CommandBox\"\n  }, \"/bin/bash -c \\\"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall.sh)\\\"\"), mdx(StepButton, {\n    to: \"/step-4\",\n    mdxType: \"StepButton\"\n  }));\n}\n;\nMDXContent.isMDXComponent = true;",
          frontmatter: {
            title: "Homebrew"
          },
        },
    }

    const tree = renderer.create(<Step data={data}/>).toJSON()
    expect(tree).toMatchSnapshot()
  });
});

If anyone has any feedback or spotted anything else, please let me know. Thanks!

like image 179
Minsi Yang Avatar answered Oct 18 '25 20:10

Minsi Yang



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!