Skip to content

Commit

Permalink
refactor, more tests (#444)
Browse files Browse the repository at this point in the history
* async/await refactor, more testing

* add funding docs

* test fix

* dependency updates
  • Loading branch information
kremalicious authored Apr 8, 2024
1 parent 83e2ae1 commit a036be8
Show file tree
Hide file tree
Showing 7 changed files with 1,642 additions and 1,497 deletions.
3 changes: 3 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
github: kremalicious
patreon: kremalicious
custom: ['https://kremalicious.com/thanks']
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ By combining this plugin with [gatsby-plugin-meta-redirect](https://github.com/g
- [Documentation](#documentation)
- [Plugin Development](#plugin-development)
- [Changelog](#changelog)
- [Sponsorship](#sponsorship)
- [License](#license)

---
Expand Down Expand Up @@ -92,6 +93,12 @@ npm run release

See [CHANGELOG.md](CHANGELOG.md).

## Sponsorship

[![](https://img.shields.io/static/v1?label=Say%20Thanks%20With%20Web3&labelColor=%2343a699&message=%E2%9D%A4&logo=Ethereum&color=%23fe8e86&style=for-the-badge)](https://kremalicious.com/thanks)

[![](https://img.shields.io/static/v1?label=Say%20Thanks%20With%20GitHub&labelColor=%2343a699&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86&style=for-the-badge)](https://github.com/sponsors/kremalicious)

## License

The MIT License
Expand All @@ -107,9 +114,3 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
---

Made with ♥ by [Matthias Kretschmann](https://matthiaskretschmann.com) ([@kremalicious](https://github.com/kremalicious))

Say thanks with BTC:
`35UUssHexVK48jbiSgTxa4QihEoCqrwCTG`

Say thanks with ETH:
`0x04354F554536DA108726829207958d3E277f0210`
2,883 changes: 1,481 additions & 1,402 deletions package-lock.json

Large diffs are not rendered by default.

13 changes: 6 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,17 @@
"maintained node versions"
],
"devDependencies": {
"@babel/cli": "^7.23.0",
"@babel/core": "^7.23.0",
"@babel/preset-env": "^7.22.20",
"@babel/cli": "^7.24.1",
"@babel/core": "^7.24.4",
"@babel/preset-env": "^7.24.4",
"auto-changelog": "^2.4.0",
"chalk": "^5.3.0",
"cross-env": "^7.0.3",
"eslint": "^8.50.0",
"eslint-config-prettier": "^9.0.0",
"eslint-config-prettier": "^9.1.0",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"prettier": "^3.0.3",
"release-it": "^16.2.1"
"prettier": "^3.2.5",
"release-it": "^17.1.1"
},
"peerDependencies": {
"gatsby": "^4.0.0 || ^5.0.0",
Expand Down
136 changes: 84 additions & 52 deletions src/gatsby-node.js
Original file line number Diff line number Diff line change
@@ -1,68 +1,100 @@
import chalk from 'chalk'
exports.createSchemaCustomization = ({ actions }) => {
const { createTypes } = actions

export function createPages({ graphql, actions }, pluginOptions) {
const { createRedirect } = actions
// Define the type definitions for the `MarkdownRemark` node
const typeDefs = `
type MarkdownRemark implements Node {
fields: MarkdownRemarkFields
frontmatter: MarkdownRemarkFrontmatter
}
type MarkdownRemarkFields {
slug: String
}
type MarkdownRemarkFrontmatter {
slug: String
}
`

// Create the type definitions
createTypes(typeDefs)
}

export async function createPages({ graphql, actions }, pluginOptions) {
const { createRedirect } = actions
const markdownQuery = pluginOptions.query || 'allMarkdownRemark'

return new Promise((resolve, reject) => {
resolve(
graphql(
`
{
q: ${markdownQuery}(
filter: { frontmatter: { redirect_from: { ne: null } } }
) {
edges {
node {
fields {
slug
}
frontmatter {
redirect_from
}
}
try {
const { data } = await graphql(`
{
q: ${markdownQuery}(filter: { frontmatter: { redirect_from: { ne: null } } }) {
edges {
node {
fields {
slug
}
frontmatter {
slug
redirect_from
}
}
}
`
).then((result) => {
if (result.errors) {
console.log(result.errors) // eslint-disable-line no-console
reject(result.errors)
return
}
}
`)

const allPosts = result.data.q.edges

const redirects = []
const allPosts = data?.q?.edges

// For all posts with redirect_from frontmatter,
// extract all values and push to redirects array
allPosts.forEach((post) => {
redirects.push({
from: post.node.frontmatter.redirect_from,
to: post.node.fields.slug
})
})
if (!allPosts || allPosts.length === 0) {
console.log(
'%c %s %c %s',
'color:orange',
'warning',
'color:none',
'no posts with redirect_from found'
)
return
}

// Create redirects from the just constructed array
redirects.forEach(({ from, to }) => {
// iterate through all `from` array items
from.forEach((from) => {
createRedirect({
fromPath: from,
toPath: to,
isPermanent: true,
redirectInBrowser: true
})
})
})
const redirects = []

resolve(
console.log(`${chalk.green('success')} create redirects`) // eslint-disable-line no-console
allPosts.forEach(({ node }) => {
let _slug
const { redirect_from, slug } = node.frontmatter
if (!slug) _slug = node.fields?.slug
if (!_slug) {
console.log(
'%c %s %c %s',
'color:orange',
'warning',
'color:none',
'no slug found in frontmatter or fields'
)
return
}

redirect_from.forEach((from) => {
redirects.push({ from, to: _slug })
})
})

redirects.forEach(({ from, to }) => {
createRedirect({
fromPath: from,
toPath: to,
isPermanent: true,
redirectInBrowser: true
})
})
console.log(
'%c %s %c %s',
'color:green',
'success',
'color:none',
`created ${redirects.length} redirects`
)
})
} catch (error) {
console.error(error.message)
}
}
88 changes: 60 additions & 28 deletions test/gatsby-node.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,22 @@ describe('createPages', () => {
let actions
let consoleLogSpy

const markdownQuery = 'allMarkdownRemark'
const edges = [
{
node: {
fields: { slug: '/post-1' },
frontmatter: { redirect_from: ['/old-url-1', '/old-url-2'] }
}
},
{
node: {
fields: { slug: '/post-2' },
frontmatter: { redirect_from: ['/old-url-3'] }
}
}
]

beforeEach(() => {
actions = { createRedirect: jest.fn() }
pluginOptions = { query: 'allMarkdownRemark' }
Expand All @@ -25,39 +41,34 @@ describe('createPages', () => {
consoleLogSpy.mockRestore()
})

it('should create redirects correctly', async () => {
graphql.mockReturnValueOnce(
Promise.resolve({
data: {
q: {
edges: [
{
node: {
fields: { slug: '/post-1/' },
frontmatter: { redirect_from: ['/old-url-1', '/old-url-2'] }
}
}
]
}
}
})
)
it('should create redirects for each post with a redirect_from field', async () => {
const data = { q: { edges } }
graphql.mockReturnValueOnce(Promise.resolve({ data }))
const createRedirectSpy = jest.spyOn(actions, 'createRedirect')

await createPages({ graphql, actions }, pluginOptions)
await createPages({ graphql, actions }, { query: markdownQuery })

expect(actions.createRedirect).toHaveBeenCalledTimes(2)
expect(actions.createRedirect).toHaveBeenCalledWith({
expect(createRedirectSpy).toHaveBeenCalledTimes(3)
expect(createRedirectSpy).toHaveBeenCalledWith({
fromPath: '/old-url-1',
toPath: '/post-1/',
toPath: '/post-1',
isPermanent: true,
redirectInBrowser: true
})
expect(actions.createRedirect).toHaveBeenCalledWith({
expect(createRedirectSpy).toHaveBeenCalledWith({
fromPath: '/old-url-2',
toPath: '/post-1/',
toPath: '/post-1',
isPermanent: true,
redirectInBrowser: true
})
expect(createRedirectSpy).toHaveBeenCalledWith({
fromPath: '/old-url-3',
toPath: '/post-2',
isPermanent: true,
redirectInBrowser: true
})

createRedirectSpy.mockRestore()
})

it('should use pluginOptions.query when defined', async () => {
Expand All @@ -83,16 +94,37 @@ describe('createPages', () => {
await createPages({ graphql, actions }, pluginOptions)
})

it('should log and reject errors when the GraphQL query fails', async () => {
graphql.mockReturnValueOnce(
Promise.resolve({ errors: [{ message: 'GraphQL error' }] })
it('should log a success message when redirects are created', async () => {
const data = { q: { edges } }
graphql.mockReturnValueOnce(Promise.resolve({ data }))
const createRedirectSpy = jest.spyOn(actions, 'createRedirect')

await createPages({ graphql, actions }, { query: markdownQuery })

expect(createRedirectSpy).toHaveBeenCalledTimes(3)
expect(console.log).toHaveBeenCalledWith(
'%c %s %c %s',
'color:green',
'success',
'color:none',
'created 3 redirects'
)
})

it('should log an error message when an error occurs', async () => {
const error = new Error('GraphQL query failed')
graphql.mockImplementationOnce(() => {
throw error
})

const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {})

try {
await createPages({ graphql, actions }, pluginOptions)
} catch (error) {
expect(console.log).toHaveBeenCalledWith([{ message: 'GraphQL error' }])
expect(error).toEqual([{ message: 'GraphQL error' }])
expect(console.error).toHaveBeenCalledWith('GraphQL query failed')
}

consoleSpy.mockRestore()
})
})
3 changes: 1 addition & 2 deletions test/jest.config.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"rootDir": "../",
"coverageDirectory": "<rootDir>/coverage/",
"transformIgnorePatterns": ["node_modules/(?!chalk/.*)"]
"coverageDirectory": "<rootDir>/coverage/"
}

0 comments on commit a036be8

Please sign in to comment.