Skip to content

Commit d547a28

Browse files
authored
feat: Add support for advanced redirect types (#117)
* feat: add conversion of country and language redirects to _redirects file * feat: add conversion of wildcard and splat redirects to _redirects file * feat: add conversion of query param redirects to _redirects file * test: Add test for create-redirects
1 parent 5b9d6a3 commit d547a28

File tree

5 files changed

+315
-176
lines changed

5 files changed

+315
-176
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`create-redirects writes file 1`] = `
4+
"
5+
## Created with gatsby-plugin-netlify
6+
/foo /bar 302
7+
/blog /canada/blog 302 Country=ca
8+
/speaker /english/speaker 302 Language=en
9+
/speaker /french/speaker 302 Language=fr
10+
/param id=7 /test 302
11+
/dogs/* /animals/:splat 302
12+
/cats id=:id /animals/:id 302"
13+
`;
+2-173
Original file line numberDiff line numberDiff line change
@@ -1,179 +1,9 @@
1-
/* eslint-disable max-lines, max-nested-callbacks */
2-
import { tmpdir } from 'os'
3-
import { join } from 'path'
4-
5-
import { existsSync, mkdtemp, readFile } from 'fs-extra'
1+
import { existsSync, readFile } from 'fs-extra'
62

73
import buildHeadersProgram from '../build-headers-program'
84
import { DEFAULT_OPTIONS } from '../constants'
95

10-
// eslint-disable-next-line max-lines-per-function
11-
const createPluginData = async () => {
12-
const tmpDir = await mkdtemp(join(tmpdir(), `gatsby-plugin-netlify-`))
13-
14-
return {
15-
components: new Map([
16-
[
17-
1,
18-
{
19-
componentChunkName: `component---node-modules-gatsby-plugin-offline-app-shell-js`,
20-
},
21-
],
22-
[
23-
2,
24-
{
25-
componentChunkName: `component---src-templates-blog-post-js`,
26-
},
27-
],
28-
[
29-
3,
30-
{
31-
componentChunkName: `component---src-pages-404-js`,
32-
},
33-
],
34-
[
35-
4,
36-
{
37-
componentChunkName: `component---src-pages-index-js`,
38-
},
39-
],
40-
]),
41-
pages: new Map([
42-
[
43-
`/offline-plugin-app-shell-fallback/`,
44-
{
45-
jsonName: `offline-plugin-app-shell-fallback-a30`,
46-
internalComponentName: `ComponentOfflinePluginAppShellFallback`,
47-
path: `/offline-plugin-app-shell-fallback/`,
48-
matchPath: undefined,
49-
componentChunkName: `component---node-modules-gatsby-plugin-offline-app-shell-js`,
50-
isCreatedByStatefulCreatePages: false,
51-
context: {},
52-
updatedAt: 1_557_740_602_268,
53-
pluginCreator___NODE: `63e5f7ff-e5f1-58f7-8e2c-55872ac42281`,
54-
pluginCreatorId: `63e5f7ff-e5f1-58f7-8e2c-55872ac42281`,
55-
},
56-
],
57-
[
58-
`/hi-folks/`,
59-
{
60-
jsonName: `hi-folks-a2b`,
61-
internalComponentName: `ComponentHiFolks`,
62-
path: `/hi-folks/`,
63-
matchPath: undefined,
64-
componentChunkName: `component---src-templates-blog-post-js`,
65-
isCreatedByStatefulCreatePages: false,
66-
context: {},
67-
updatedAt: 1_557_740_602_330,
68-
pluginCreator___NODE: `7374ebf2-d961-52ee-92a2-c25e7cb387a9`,
69-
pluginCreatorId: `7374ebf2-d961-52ee-92a2-c25e7cb387a9`,
70-
},
71-
],
72-
[
73-
`/my-second-post/`,
74-
{
75-
jsonName: `my-second-post-2aa`,
76-
internalComponentName: `ComponentMySecondPost`,
77-
path: `/my-second-post/`,
78-
matchPath: undefined,
79-
componentChunkName: `component---src-templates-blog-post-js`,
80-
isCreatedByStatefulCreatePages: false,
81-
context: {},
82-
updatedAt: 1_557_740_602_333,
83-
pluginCreator___NODE: `7374ebf2-d961-52ee-92a2-c25e7cb387a9`,
84-
pluginCreatorId: `7374ebf2-d961-52ee-92a2-c25e7cb387a9`,
85-
},
86-
],
87-
[
88-
`/hello-world/`,
89-
{
90-
jsonName: `hello-world-8bc`,
91-
internalComponentName: `ComponentHelloWorld`,
92-
path: `/hello-world/`,
93-
matchPath: undefined,
94-
componentChunkName: `component---src-templates-blog-post-js`,
95-
isCreatedByStatefulCreatePages: false,
96-
context: {},
97-
updatedAt: 1_557_740_602_335,
98-
pluginCreator___NODE: `7374ebf2-d961-52ee-92a2-c25e7cb387a9`,
99-
pluginCreatorId: `7374ebf2-d961-52ee-92a2-c25e7cb387a9`,
100-
},
101-
],
102-
[
103-
`/404/`,
104-
{
105-
jsonName: `404-22d`,
106-
internalComponentName: `Component404`,
107-
path: `/404/`,
108-
matchPath: undefined,
109-
componentChunkName: `component---src-pages-404-js`,
110-
isCreatedByStatefulCreatePages: true,
111-
context: {},
112-
updatedAt: 1_557_740_602_358,
113-
pluginCreator___NODE: `049c1cfd-95f7-5555-a4ac-9b396d098b26`,
114-
pluginCreatorId: `049c1cfd-95f7-5555-a4ac-9b396d098b26`,
115-
},
116-
],
117-
[
118-
`/`,
119-
{
120-
jsonName: `index`,
121-
internalComponentName: `ComponentIndex`,
122-
path: `/`,
123-
matchPath: undefined,
124-
componentChunkName: `component---src-pages-index-js`,
125-
isCreatedByStatefulCreatePages: true,
126-
context: {},
127-
updatedAt: 1_557_740_602_361,
128-
pluginCreator___NODE: `049c1cfd-95f7-5555-a4ac-9b396d098b26`,
129-
pluginCreatorId: `049c1cfd-95f7-5555-a4ac-9b396d098b26`,
130-
},
131-
],
132-
[
133-
`/404.html`,
134-
{
135-
jsonName: `404-html-516`,
136-
internalComponentName: `Component404Html`,
137-
path: `/404.html`,
138-
matchPath: undefined,
139-
componentChunkName: `component---src-pages-404-js`,
140-
isCreatedByStatefulCreatePages: true,
141-
context: {},
142-
updatedAt: 1_557_740_602_382,
143-
pluginCreator___NODE: `f795702c-a3b8-5a88-88ee-5d06019d44fa`,
144-
pluginCreatorId: `f795702c-a3b8-5a88-88ee-5d06019d44fa`,
145-
},
146-
],
147-
]),
148-
manifest: {
149-
'main.js': `render-page.js`,
150-
'main.js.map': `render-page.js.map`,
151-
app: [
152-
`webpack-runtime-acaa8994f1f704475e21.js`,
153-
`styles.1025963f4f2ec7abbad4.css`,
154-
`styles-565f081c8374bbda155f.js`,
155-
`app-f33c13590352da20930f.js`,
156-
],
157-
'component---node-modules-gatsby-plugin-offline-app-shell-js': [
158-
`component---node-modules-gatsby-plugin-offline-app-shell-js-78f9e4dea04737fa062d.js`,
159-
],
160-
'component---src-templates-blog-post-js': [
161-
`0-0180cd94ef2497ac7db8.js`,
162-
`component---src-templates-blog-post-js-517987eae96e75cddbe7.js`,
163-
],
164-
'component---src-pages-404-js': [
165-
`0-0180cd94ef2497ac7db8.js`,
166-
`component---src-pages-404-js-53e6c51a5a7e73090f50.js`,
167-
],
168-
'component---src-pages-index-js': [
169-
`0-0180cd94ef2497ac7db8.js`,
170-
`component---src-pages-index-js-0bdd01c77ee09ef0224c.js`,
171-
],
172-
},
173-
pathPrefix: ``,
174-
publicFolder: (...files: any[]) => join(tmpDir, ...files),
175-
}
176-
}
6+
import { createPluginData } from './helpers'
1777

1788
jest.mock(`fs-extra`, () => {
1799
const actualFsExtra = jest.requireActual(`fs-extra`)
@@ -308,4 +138,3 @@ describe(`build-headers-program`, () => {
308138
expect(reporter.panic).toHaveBeenCalled()
309139
})
310140
})
311-
/* eslint-enable max-lines, max-nested-callbacks */

src/__tests__/create-redirects.ts

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { readFile } from 'fs-extra'
2+
3+
import createRedirects from '../create-redirects'
4+
5+
import { createPluginData } from './helpers'
6+
7+
jest.mock(`fs-extra`, () => {
8+
const actualFsExtra = jest.requireActual(`fs-extra`)
9+
return {
10+
...actualFsExtra,
11+
}
12+
})
13+
14+
const redirects = [
15+
{
16+
"fromPath": "/foo",
17+
"isPermanent": false,
18+
"ignoreCase": true,
19+
"redirectInBrowser": false,
20+
"toPath": "/bar"
21+
},
22+
{
23+
"fromPath": "/blog",
24+
"isPermanent": false,
25+
"ignoreCase": true,
26+
"redirectInBrowser": false,
27+
"toPath": "/canada/blog",
28+
"conditions": {
29+
"country": "ca"
30+
}
31+
},
32+
{
33+
"fromPath": "/speaker",
34+
"isPermanent": false,
35+
"ignoreCase": true,
36+
"redirectInBrowser": false,
37+
"toPath": "/english/speaker",
38+
"conditions": {
39+
"language": [
40+
"en"
41+
]
42+
}
43+
},
44+
{
45+
"fromPath": "/speaker",
46+
"isPermanent": false,
47+
"ignoreCase": true,
48+
"redirectInBrowser": false,
49+
"toPath": "/french/speaker",
50+
"conditions": {
51+
"language": [
52+
"fr"
53+
]
54+
}
55+
},
56+
{
57+
"fromPath": "/param?id=7",
58+
"isPermanent": false,
59+
"ignoreCase": true,
60+
"redirectInBrowser": false,
61+
"toPath": "/test"
62+
},
63+
{
64+
"fromPath": "/dogs/*",
65+
"isPermanent": false,
66+
"ignoreCase": true,
67+
"redirectInBrowser": false,
68+
"toPath": "/animals/*"
69+
},
70+
{
71+
"fromPath": "/cats?id=:id",
72+
"isPermanent": false,
73+
"ignoreCase": true,
74+
"redirectInBrowser": false,
75+
"toPath": "/animals/:id"
76+
}
77+
]
78+
79+
describe(`create-redirects`, () => {
80+
81+
it(`writes file`, async () => {
82+
const pluginData = await createPluginData()
83+
84+
await createRedirects(pluginData, redirects, [])
85+
86+
const output = await readFile(pluginData.publicFolder(`_redirects`), `utf8`)
87+
expect(output).toMatchSnapshot()
88+
})
89+
})

0 commit comments

Comments
 (0)