mirror of
https://github.com/kremalicious/gatsby-redirect-from.git
synced 2024-12-22 09:13:20 +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)
|
- [Documentation](#documentation)
|
||||||
- [Plugin Development](#plugin-development)
|
- [Plugin Development](#plugin-development)
|
||||||
- [Changelog](#changelog)
|
- [Changelog](#changelog)
|
||||||
|
- [Sponsorship](#sponsorship)
|
||||||
- [License](#license)
|
- [License](#license)
|
||||||
|
|
||||||
---
|
---
|
||||||
@ -92,6 +93,12 @@ npm run release
|
|||||||
|
|
||||||
See [CHANGELOG.md](CHANGELOG.md).
|
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
|
## License
|
||||||
|
|
||||||
The MIT 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))
|
Made with ♥ by [Matthias Kretschmann](https://matthiaskretschmann.com) ([@kremalicious](https://github.com/kremalicious))
|
||||||
|
|
||||||
Say thanks with BTC:
|
|
||||||
`35UUssHexVK48jbiSgTxa4QihEoCqrwCTG`
|
|
||||||
|
|
||||||
Say thanks with ETH:
|
|
||||||
`0x04354F554536DA108726829207958d3E277f0210`
|
|
||||||
|
2845
package-lock.json
generated
2845
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"
|
"maintained node versions"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.23.0",
|
"@babel/cli": "^7.24.1",
|
||||||
"@babel/core": "^7.23.0",
|
"@babel/core": "^7.24.4",
|
||||||
"@babel/preset-env": "^7.22.20",
|
"@babel/preset-env": "^7.24.4",
|
||||||
"auto-changelog": "^2.4.0",
|
"auto-changelog": "^2.4.0",
|
||||||
"chalk": "^5.3.0",
|
|
||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"eslint": "^8.50.0",
|
"eslint": "^8.50.0",
|
||||||
"eslint-config-prettier": "^9.0.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
"jest-environment-jsdom": "^29.7.0",
|
"jest-environment-jsdom": "^29.7.0",
|
||||||
"prettier": "^3.0.3",
|
"prettier": "^3.2.5",
|
||||||
"release-it": "^16.2.1"
|
"release-it": "^17.1.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"gatsby": "^4.0.0 || ^5.0.0",
|
"gatsby": "^4.0.0 || ^5.0.0",
|
||||||
|
@ -1,55 +1,85 @@
|
|||||||
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 { createRedirect } = actions
|
||||||
|
|
||||||
const markdownQuery = pluginOptions.query || 'allMarkdownRemark'
|
const markdownQuery = pluginOptions.query || 'allMarkdownRemark'
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
try {
|
||||||
resolve(
|
const { data } = await graphql(`
|
||||||
graphql(
|
|
||||||
`
|
|
||||||
{
|
{
|
||||||
q: ${markdownQuery}(
|
q: ${markdownQuery}(filter: { frontmatter: { redirect_from: { ne: null } } }) {
|
||||||
filter: { frontmatter: { redirect_from: { ne: null } } }
|
|
||||||
) {
|
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
fields {
|
fields {
|
||||||
slug
|
slug
|
||||||
}
|
}
|
||||||
frontmatter {
|
frontmatter {
|
||||||
|
slug
|
||||||
redirect_from
|
redirect_from
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`)
|
||||||
).then((result) => {
|
|
||||||
if (result.errors) {
|
const allPosts = data?.q?.edges
|
||||||
console.log(result.errors) // eslint-disable-line no-console
|
|
||||||
reject(result.errors)
|
if (!allPosts || allPosts.length === 0) {
|
||||||
|
console.log(
|
||||||
|
'%c %s %c %s',
|
||||||
|
'color:orange',
|
||||||
|
'warning',
|
||||||
|
'color:none',
|
||||||
|
'no posts with redirect_from found'
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const allPosts = result.data.q.edges
|
|
||||||
|
|
||||||
const redirects = []
|
const redirects = []
|
||||||
|
|
||||||
// For all posts with redirect_from frontmatter,
|
allPosts.forEach(({ node }) => {
|
||||||
// extract all values and push to redirects array
|
let _slug
|
||||||
allPosts.forEach((post) => {
|
const { redirect_from, slug } = node.frontmatter
|
||||||
redirects.push({
|
if (!slug) _slug = node.fields?.slug
|
||||||
from: post.node.frontmatter.redirect_from,
|
if (!_slug) {
|
||||||
to: post.node.fields.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 })
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// Create redirects from the just constructed array
|
|
||||||
redirects.forEach(({ from, to }) => {
|
redirects.forEach(({ from, to }) => {
|
||||||
// iterate through all `from` array items
|
|
||||||
from.forEach((from) => {
|
|
||||||
createRedirect({
|
createRedirect({
|
||||||
fromPath: from,
|
fromPath: from,
|
||||||
toPath: to,
|
toPath: to,
|
||||||
@ -57,12 +87,14 @@ export function createPages({ graphql, actions }, pluginOptions) {
|
|||||||
redirectInBrowser: true
|
redirectInBrowser: true
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
console.log(
|
||||||
|
'%c %s %c %s',
|
||||||
resolve(
|
'color:green',
|
||||||
console.log(`${chalk.green('success')} create redirects`) // eslint-disable-line no-console
|
'success',
|
||||||
|
'color:none',
|
||||||
|
`created ${redirects.length} redirects`
|
||||||
)
|
)
|
||||||
})
|
} catch (error) {
|
||||||
)
|
console.error(error.message)
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,22 @@ describe('createPages', () => {
|
|||||||
let actions
|
let actions
|
||||||
let consoleLogSpy
|
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(() => {
|
beforeEach(() => {
|
||||||
actions = { createRedirect: jest.fn() }
|
actions = { createRedirect: jest.fn() }
|
||||||
pluginOptions = { query: 'allMarkdownRemark' }
|
pluginOptions = { query: 'allMarkdownRemark' }
|
||||||
@ -25,39 +41,34 @@ describe('createPages', () => {
|
|||||||
consoleLogSpy.mockRestore()
|
consoleLogSpy.mockRestore()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should create redirects correctly', async () => {
|
it('should create redirects for each post with a redirect_from field', async () => {
|
||||||
graphql.mockReturnValueOnce(
|
const data = { q: { edges } }
|
||||||
Promise.resolve({
|
graphql.mockReturnValueOnce(Promise.resolve({ data }))
|
||||||
data: {
|
const createRedirectSpy = jest.spyOn(actions, 'createRedirect')
|
||||||
q: {
|
|
||||||
edges: [
|
|
||||||
{
|
|
||||||
node: {
|
|
||||||
fields: { slug: '/post-1/' },
|
|
||||||
frontmatter: { redirect_from: ['/old-url-1', '/old-url-2'] }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
await createPages({ graphql, actions }, pluginOptions)
|
await createPages({ graphql, actions }, { query: markdownQuery })
|
||||||
|
|
||||||
expect(actions.createRedirect).toHaveBeenCalledTimes(2)
|
expect(createRedirectSpy).toHaveBeenCalledTimes(3)
|
||||||
expect(actions.createRedirect).toHaveBeenCalledWith({
|
expect(createRedirectSpy).toHaveBeenCalledWith({
|
||||||
fromPath: '/old-url-1',
|
fromPath: '/old-url-1',
|
||||||
toPath: '/post-1/',
|
toPath: '/post-1',
|
||||||
isPermanent: true,
|
isPermanent: true,
|
||||||
redirectInBrowser: true
|
redirectInBrowser: true
|
||||||
})
|
})
|
||||||
expect(actions.createRedirect).toHaveBeenCalledWith({
|
expect(createRedirectSpy).toHaveBeenCalledWith({
|
||||||
fromPath: '/old-url-2',
|
fromPath: '/old-url-2',
|
||||||
toPath: '/post-1/',
|
toPath: '/post-1',
|
||||||
isPermanent: true,
|
isPermanent: true,
|
||||||
redirectInBrowser: 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 () => {
|
it('should use pluginOptions.query when defined', async () => {
|
||||||
@ -83,16 +94,37 @@ describe('createPages', () => {
|
|||||||
await createPages({ graphql, actions }, pluginOptions)
|
await createPages({ graphql, actions }, pluginOptions)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should log and reject errors when the GraphQL query fails', async () => {
|
it('should log a success message when redirects are created', async () => {
|
||||||
graphql.mockReturnValueOnce(
|
const data = { q: { edges } }
|
||||||
Promise.resolve({ errors: [{ message: 'GraphQL error' }] })
|
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 {
|
try {
|
||||||
await createPages({ graphql, actions }, pluginOptions)
|
await createPages({ graphql, actions }, pluginOptions)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
expect(console.log).toHaveBeenCalledWith([{ message: 'GraphQL error' }])
|
expect(console.error).toHaveBeenCalledWith('GraphQL query failed')
|
||||||
expect(error).toEqual([{ message: 'GraphQL error' }])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
consoleSpy.mockRestore()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
{
|
{
|
||||||
"rootDir": "../",
|
"rootDir": "../",
|
||||||
"coverageDirectory": "<rootDir>/coverage/",
|
"coverageDirectory": "<rootDir>/coverage/"
|
||||||
"transformIgnorePatterns": ["node_modules/(?!chalk/.*)"]
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user