Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions packages/gatsby-plugin-sitemap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,28 @@ plugins: [
}
]
```

## Sitemap Index

We also support generating `sitemap index`.

- [Split up your large sitemaps](https://support.google.com/webmasters/answer/75712?hl=en)
- [Using Sitemap index files (to group multiple sitemap files)](https://www.sitemaps.org/protocol.html#index)

```javascript
// In your gatsby-config.js
siteMetadata: {
siteUrl: `https://www.example.com`,
},
plugins: [
{
resolve: `gatsby-plugin-sitemap`,
options: {
sitemapSize: 5000
}
}
]
```

Above is the minimal configuration to split large sitemap.
When number of URL in sitemap is more than 5000 plugin will create sitemap (e.g. `sitemap-0.xml`, `sitemap-1.xml`) and index (e.g. `sitemap.xml`) files.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Test plugin sitemap custom query runs 1`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>
<urlset xmlns=\\"http://www.sitemaps.org/schemas/sitemap/0.9\\" xmlns:news=\\"http://www.google.com/schemas/sitemap-news/0.9\\" xmlns:xhtml=\\"http://www.w3.org/1999/xhtml\\" xmlns:mobile=\\"http://www.google.com/schemas/sitemap-mobile/1.0\\" xmlns:image=\\"http://www.google.com/schemas/sitemap-image/1.1\\" xmlns:video=\\"http://www.google.com/schemas/sitemap-video/1.1\\">
<url> <loc>http://dummy.url/post/page-1</loc> <changefreq>weekly</changefreq> <priority>0.8</priority> </url>
</urlset>"
`;

exports[`Test plugin sitemap default settings work properly 1`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>
<urlset xmlns=\\"http://www.sitemaps.org/schemas/sitemap/0.9\\" xmlns:news=\\"http://www.google.com/schemas/sitemap-news/0.9\\" xmlns:xhtml=\\"http://www.w3.org/1999/xhtml\\" xmlns:mobile=\\"http://www.google.com/schemas/sitemap-mobile/1.0\\" xmlns:image=\\"http://www.google.com/schemas/sitemap-image/1.1\\" xmlns:video=\\"http://www.google.com/schemas/sitemap-video/1.1\\">
<url> <loc>http://dummy.url/page-1</loc> <changefreq>daily</changefreq> <priority>0.7</priority> </url>
<url> <loc>http://dummy.url/page-2</loc> <changefreq>daily</changefreq> <priority>0.7</priority> </url>
</urlset>"
`;

exports[`Test plugin sitemap sitemap index set sitempa size and urls are less than it. 1`] = `
"<?xml version=\\"1.0\\" encoding=\\"UTF-8\\"?>
<urlset xmlns=\\"http://www.sitemaps.org/schemas/sitemap/0.9\\" xmlns:news=\\"http://www.google.com/schemas/sitemap-news/0.9\\" xmlns:xhtml=\\"http://www.w3.org/1999/xhtml\\" xmlns:mobile=\\"http://www.google.com/schemas/sitemap-mobile/1.0\\" xmlns:image=\\"http://www.google.com/schemas/sitemap-image/1.1\\" xmlns:video=\\"http://www.google.com/schemas/sitemap-video/1.1\\">
<url> <loc>http://dummy.url/page-1</loc> <changefreq>daily</changefreq> <priority>0.7</priority> </url>
<url> <loc>http://dummy.url/page-2</loc> <changefreq>daily</changefreq> <priority>0.7</priority> </url>
</urlset>"
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Adds <Link> for site to head creates Link href with path prefix when __PATH_PREFIX__ sets 1`] = `
[MockFunction] {
"calls": Array [
Array [
Array [
<link
href="/hogwarts/sitemap.xml"
rel="sitemap"
type="application/xml"
/>,
],
],
],
"results": Array [
Object {
"type": "return",
"value": undefined,
},
],
}
`;

exports[`Adds <Link> for site to head creates Link if createLinkInHead is true 1`] = `
[MockFunction] {
"calls": Array [
Array [
Array [
<link
href="/sitemap.xml"
rel="sitemap"
type="application/xml"
/>,
],
],
],
"results": Array [
Object {
"type": "return",
"value": undefined,
},
],
}
`;

exports[`Adds <Link> for site to head does not create Link if createLinkInHead is false 1`] = `[MockFunction]`;
180 changes: 180 additions & 0 deletions packages/gatsby-plugin-sitemap/src/__tests__/gatsby-node.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
jest.mock(`fs`)

const fs = require(`fs`)
const path = require(`path`)
const { onPostBuild } = require(`../gatsby-node`)
const internals = require(`../internals`)
const pathPrefix = ``

describe(`Test plugin sitemap`, async () => {
it(`default settings work properly`, async () => {
internals.writeFile = jest.fn()
internals.writeFile.mockResolvedValue(true)
const graphql = jest.fn()
graphql.mockResolvedValue({
data: {
site: {
siteMetadata: {
siteUrl: `http://dummy.url`,
},
},
allSitePage: {
edges: [
{
node: {
path: `/page-1`,
},
},
{
node: {
path: `/page-2`,
},
},
],
},
},
})
await onPostBuild({ graphql, pathPrefix }, {})
const [filePath, contents] = internals.writeFile.mock.calls[0]
expect(filePath).toEqual(path.join(`public`, `sitemap.xml`))
expect(contents).toMatchSnapshot()
})
it(`custom query runs`, async () => {
internals.writeFile = jest.fn()
internals.writeFile.mockResolvedValue(true)
const graphql = jest.fn()
graphql.mockResolvedValue({
data: {
site: {
siteMetadata: {
siteUrl: `http://dummy.url`,
},
},
allSitePage: {
edges: [
{
node: {
path: `/page-1`,
},
},
{
node: {
path: `/post/exclude-page`,
},
},
],
},
},
})
const customQuery = `
{
site {
siteMetadata {
siteUrl
}
}

allSitePage {
edges {
node {
path
}
}
}
}`
const options = {
output: `custom-sitemap.xml`,
serialize: ({ site, allSitePage }) =>
allSitePage.edges.map(edge => {
return {
url: site.siteMetadata.siteUrl + `/post` + edge.node.path,
changefreq: `weekly`,
priority: 0.8,
}
}),
exclude: [`/post/exclude-page`],
query: customQuery,
}
await onPostBuild({ graphql, pathPrefix }, options)
const [filePath, contents] = internals.writeFile.mock.calls[0]
expect(filePath).toEqual(path.join(`public`, `custom-sitemap.xml`))
expect(contents).toMatchSnapshot()
expect(graphql).toBeCalledWith(customQuery)
})
describe(`sitemap index`, () => {
let graphql = null
const queryResult = {
data: {
site: {
siteMetadata: {
siteUrl: `http://dummy.url`,
},
},
allSitePage: {
edges: [
{
node: {
path: `/page-1`,
},
},
{
node: {
path: `/page-2`,
},
},
],
},
},
}
beforeEach(() => {
graphql = jest.fn()
graphql.mockResolvedValue(queryResult)

internals.renameFile = jest.fn()
internals.renameFile.mockResolvedValue(true)

internals.writeFile = jest.fn()
internals.writeFile.mockResolvedValue(true)

fs.createWriteStream.mockReset()
fs.createWriteStream.mockReturnValue({
once: jest.fn((event, cb) => cb()),
write: jest.fn(),
end: jest.fn(),
})

fs.statSync.mockReset()
fs.statSync.mockReturnValue({
isDirectory: jest.fn(() => true),
})
})

it(`set sitemap size and urls are more than it.`, async () => {
const options = {
sitemapSize: 1,
}
await onPostBuild({ graphql, pathPrefix }, options)
expect(fs.createWriteStream.mock.calls[0][0]).toEqual(
`./public/sitemap-0.xml`
)
expect(fs.createWriteStream.mock.calls[1][0]).toEqual(
`./public/sitemap-1.xml`
)
expect(fs.createWriteStream.mock.calls[2][0]).toEqual(
`./public/sitemap-index.xml`
)
const [originalFile, newFile] = internals.renameFile.mock.calls[0]
expect(originalFile).toEqual(path.join(`public`, `sitemap-index.xml`))
expect(newFile).toEqual(path.join(`public`, `sitemap.xml`))
})
it(`set sitempa size and urls are less than it.`, async () => {
const options = {
sitemapSize: 100,
}
await onPostBuild({ graphql, pathPrefix }, options)
const [filePath, contents] = internals.writeFile.mock.calls[0]
expect(filePath).toEqual(path.join(`public`, `sitemap.xml`))
expect(contents).toMatchSnapshot()
})
})
})
67 changes: 67 additions & 0 deletions packages/gatsby-plugin-sitemap/src/__tests__/gatsby-ssr.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
const { onRenderBody } = require(`../gatsby-ssr`)

const defaultPathPrefix = global.__PATH_PREFIX__

describe(`Adds <Link> for site to head`, () => {
beforeEach(() => {
global.__PATH_PREFIX__ = ``
})

afterEach(() => {
global.__PATH_PREFIX__ = defaultPathPrefix
})

it(`creates Link if createLinkInHead is true`, async () => {
const pluginOptions = {
createLinkInHead: true,
output: `sitemap.xml`,
}
const setHeadComponents = jest.fn()

await onRenderBody(
{
setHeadComponents,
},
pluginOptions
)

expect(setHeadComponents).toMatchSnapshot()
expect(setHeadComponents).toHaveBeenCalledTimes(1)
})
it(`does not create Link if createLinkInHead is false`, async () => {
const pluginOptions = {
createLinkInHead: false,
output: `sitemap.xml`,
}
const setHeadComponents = jest.fn()

await onRenderBody(
{
setHeadComponents,
},
pluginOptions
)

expect(setHeadComponents).toMatchSnapshot()
expect(setHeadComponents).toHaveBeenCalledTimes(0)
})
it(`creates Link href with path prefix when __PATH_PREFIX__ sets`, async () => {
global.__PATH_PREFIX__ = `/hogwarts`

const pluginOptions = {
createLinkInHead: true,
output: `sitemap.xml`,
}
const setHeadComponents = jest.fn()

await onRenderBody(
{
setHeadComponents,
},
pluginOptions
)

expect(setHeadComponents).toMatchSnapshot()
expect(setHeadComponents).toHaveBeenCalledTimes(1)
})
})
Loading