mirror of
https://github.com/kremalicious/gatsby-redirect-from.git
synced 2024-12-22 01:03:21 +01:00
refactor, more tests (#444)
* async/await refactor, more testing * add funding docs * test fix * dependency updates
This commit is contained in:
parent
83e2ae1daa
commit
a036be8087
3
.github/FUNDING.yml
vendored
Normal file
3
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
github: kremalicious
|
||||
patreon: kremalicious
|
||||
custom: ['https://kremalicious.com/thanks']
|
13
README.md
13
README.md
@ -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)
|
||||
|
||||
---
|
||||
@ -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
|
||||
@ -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`
|
||||
|
2847
package-lock.json
generated
2847
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
13
package.json
13
package.json
@ -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",
|
||||
|
@ -1,68 +1,100 @@
|
||||
import chalk from 'chalk'
|
||||
exports.createSchemaCustomization = ({ actions }) => {
|
||||
const { createTypes } = actions
|
||||
|
||||
export function createPages({ graphql, actions }, pluginOptions) {
|
||||
// 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 allPosts = data?.q?.edges
|
||||
|
||||
const redirects = []
|
||||
if (!allPosts || allPosts.length === 0) {
|
||||
console.log(
|
||||
'%c %s %c %s',
|
||||
'color:orange',
|
||||
'warning',
|
||||
'color:none',
|
||||
'no posts with redirect_from found'
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// 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
|
||||
})
|
||||
})
|
||||
const redirects = []
|
||||
|
||||
// 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
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -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' }
|
||||
@ -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 () => {
|
||||
@ -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()
|
||||
})
|
||||
})
|
||||
|
@ -1,5 +1,4 @@
|
||||
{
|
||||
"rootDir": "../",
|
||||
"coverageDirectory": "<rootDir>/coverage/",
|
||||
"transformIgnorePatterns": ["node_modules/(?!chalk/.*)"]
|
||||
"coverageDirectory": "<rootDir>/coverage/"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user