Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: skip work when gatsby version supports adapters #639

Merged
merged 10 commits into from
Jul 19, 2023
Merged
Show file tree
Hide file tree
Changes from 6 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
1 change: 1 addition & 0 deletions plugin/test/fixtures/v5/with-adapters/.env.production
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pickle=word
14 changes: 14 additions & 0 deletions plugin/test/fixtures/v5/with-adapters/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
node_modules/
.cache/
public

# Local Netlify folder
.netlify
netlify/functions/gatsby/functions
deployment.json

# @netlify/plugin-gatsby ignores start
netlify/functions/gatsby
# @netlify/plugin-gatsby ignores end

package-lock.json
1 change: 1 addition & 0 deletions plugin/test/fixtures/v5/with-adapters/.nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v14.17.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Local functions can parse different ways of sending data file in multipart/form 1`] = `
Object {
"body": Object {
"something": "here",
},
"files": Array [
Object {
"buffer": Object {
"data": Array [
104,
105,
],
"type": "Buffer",
},
"encoding": "7bit",
"fieldname": "file",
"mimetype": "text/plain",
"originalname": "test.txt",
"size": 2,
},
],
}
`;

exports[`Local routing dynamic routes 1`] = `
Object {
"super": "additional",
"userId": "23",
}
`;

exports[`Local routing dynamic routes 2`] = `
Object {
"*": "super",
"0": "super",
}
`;

exports[`Local routing routes with special characters 1`] = `"I-Am-Capitalized.js"`;
33 changes: 33 additions & 0 deletions plugin/test/fixtures/v5/with-adapters/e2e-tests/build.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// eslint-disable-next-line node/no-unpublished-require
const { buildSite } = require('../../../../helpers')
const { readFileSync } = require('fs')

jest.setTimeout(240_000)
describe('A site using gatsby version with adapters', () => {
it('successfully builds and disables @netlify/plugin-gatsby and gatsby-plugin-netlify', async () => {
const {
success,
logs: { stdout, stderr },
} = await buildSite()

// in CI warnings are outputted to stderr (yikes)
const fullOutput = stdout + stderr

expect(success).toBeTruthy()

expect(fullOutput).toContain(
'Skipping @netlify/plugin-gatsby work, because used Gatsby version supports adapters.',
)
expect(fullOutput).toContain('Disabling plugin "gatsby-plugin-netlify"')

const _redirectsContent = readFileSync('public/_redirects', 'utf8')

expect(_redirectsContent).not.toContain(
'# @netlify/plugin-gatsby redirects start',
)
expect(_redirectsContent).not.toContain(
'## Created with gatsby-plugin-netlify',
)
expect(_redirectsContent).toContain('# gatsby-adapter-netlify start')
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hi
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const { runTests } = require('./test-helpers')

if (process.env.TEST_ENV === 'netlify') {
const { deploy_url } = require('../deployment.json')
runTests('Netlify', deploy_url)
} else {
runTests('Local', 'http://localhost:8888')
}
277 changes: 277 additions & 0 deletions plugin/test/fixtures/v5/with-adapters/e2e-tests/test-helpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,277 @@
/* eslint-disable no-unused-vars */
const fetch = require(`node-fetch`)
const { readFileSync } = require('fs')
const path = require('path')

const FormData = require('form-data')
// Based on Gatsby Functions integration tests
// Source: https://github.com/gatsbyjs/gatsby/blob/master/integration-tests/functions/test-helpers.js

exports.runTests = function runTests(env, host) {
jest.setTimeout(10_000)

async function fetchTwice(url, options) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this to ensure we hit the origin server?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't author the test suite so I'm not sure why it was done like that - it was copied from already existing suite in https://github.com/netlify/netlify-plugin-gatsby/tree/main/plugin/test/fixtures/v5/functions-without-gatsby-plugin/e2e-tests

Those test suites don't actually deploy, they are running ntl dev, and I just changed it to use netlify serve +
skipped some tests here

// `netlify serve` doesn't handle encoded paths same as the platform,
// so skipping these tests
// `${host}/api/some whitespace`,
// `${host}/api/with-äöü-umlaut`,
// `${host}/api/some-àè-french`,
// encodeURI(`${host}/api/some-אודות`),
due to how actual platform differs from netlify serve

just to show they are working when deployed:
/api/some whitespace
/api/with-äöü-umlaut
/api/some-àè-french
/api/some-אודות

const result = await fetch(url, options)
if (!result.headers.has('x-forwarded-host')) {
return result
}
return fetch(url, options)
}

describe(env, () => {
describe(`routing`, () => {
test(`top-level API`, async () => {
const result = await fetchTwice(`${host}/api/top-level`).then((res) =>
res.text(),
)

expect(result).toEqual('I am at the top-level')
})
test(`secondary-level API`, async () => {
const result = await fetchTwice(
`${host}/api/a-directory/function`,
).then((res) => res.text())

expect(result).toEqual('I am at a secondary-level')
})
test(`secondary-level API with index.js`, async () => {
const result = await fetchTwice(`${host}/api/a-directory`).then((res) =>
res.text(),
)

expect(result).toEqual('I am an index.js in a sub-directory!')
})
test(`secondary-level API`, async () => {
const result = await fetchTwice(`${host}/api/dir/function`).then(
(res) => res.text(),
)

expect(result).toEqual('I am another sub-directory function')
})
test(`routes with special characters`, async () => {
const routes = [
`${host}/api/I-Am-Capitalized`,
// `netlify serve` doesn't handle encoded paths same as the platform,
// so skipping these tests
// `${host}/api/some whitespace`,
// `${host}/api/with-äöü-umlaut`,
// `${host}/api/some-àè-french`,
// encodeURI(`${host}/api/some-אודות`),
]

for (const route of routes) {
const result = await fetchTwice(route).then((res) => res.text())

expect(result).toMatchSnapshot()
}
})

test(`dynamic routes`, async () => {
const routes = [
`${host}/api/users/23/additional`,
`${host}/api/dir/super`,
]

for (const route of routes) {
const result = await fetchTwice(route).then((res) => res.json())

expect(result).toMatchSnapshot()
}
})
})

describe(`environment variables`, () => {
test(`can use inside functions`, async () => {
const result = await fetchTwice(`${host}/api/env-variables`).then(
(res) => res.text(),
)

expect(result).toEqual(`word`)
})
})

describe(`typescript`, () => {
test(`typescript functions work`, async () => {
const result = await fetchTwice(`${host}/api/i-am-typescript`).then(
(res) => res.text(),
)

expect(result).toEqual('I am typescript')
})
})

describe(`function errors don't crash the server`, () => {
// This test mainly just shows that the server doesn't crash.
test(`normal`, async () => {
const result = await fetchTwice(`${host}/api/error-send-function-twice`)

expect(result.status).toEqual(200)
})
})

describe(`response formats`, () => {
test(`returns json correctly`, async () => {
const res = await fetchTwice(`${host}/api/i-am-json`)
const result = await res.json()

expect(result).toEqual({
amIJSON: true,
})
expect(res.headers.get('content-type')).toEqual('application/json')
})
test(`returns json correctly via send`, async () => {
const res = await fetchTwice(`${host}/api/i-am-json-too`)
const result = await res.json()

expect(result).toEqual({
amIJSON: true,
})
expect(res.headers.get('content-type')).toEqual('application/json')
})
test(`returns boolean correctly via send`, async () => {
const res = await fetchTwice(`${host}/api/i-am-false`)
const result = await res.json()

expect(result).toEqual(false)
expect(res.headers.get('content-type')).toEqual('application/json')
})
test(`returns status correctly via send`, async () => {
const res = await fetchTwice(`${host}/api/i-am-status`)
const result = await res.text()

expect(result).toEqual('OK')
expect(res.headers.get('content-type')).toEqual(
'text/plain; charset=utf-8',
)
})
test(`returns text correctly`, async () => {
const res = await fetchTwice(`${host}/api/i-am-text`)
const result = await res.text()

expect(result).toEqual('I am text')
expect(res.headers.get('content-type')).toEqual(
'text/html; charset=utf-8',
)
})
})

describe(`functions can send custom statuses`, () => {
test(`can return 200 status`, async () => {
const res = await fetchTwice(`${host}/api/status`)

expect(res.status).toEqual(200)
})

test(`can return 404 status`, async () => {
const res = await fetchTwice(`${host}/api/status?code=404`)

expect(res.status).toEqual(404)
})

test(`can return 500 status`, async () => {
const res = await fetchTwice(`${host}/api/status?code=500`)

expect(res.status).toEqual(500)
})
})

describe(`functions can parse different ways of sending data`, () => {
test(`query string`, async () => {
const result = await fetchTwice(`${host}/api/parser?amIReal=true`).then(
(res) => res.json(),
)

expect(result).toEqual({
amIReal: 'true',
})
})

test(`form parameters`, async () => {
const { URLSearchParams } = require('url')
const params = new URLSearchParams()
params.append('a', `form parameters`)
const result = await fetchTwice(`${host}/api/parser`, {
method: `POST`,
body: params,
}).then((res) => res.json())

expect(result).toEqual({
a: 'form parameters',
})
})

test(`form data`, async () => {
const form = new FormData()
form.append('a', `form-data`)
const result = await fetchTwice(`${host}/api/parser`, {
method: `POST`,
body: form,
}).then((res) => res.json())

expect(result).toEqual({
a: 'form-data',
})
})

test(`json body`, async () => {
const body = { a: `json` }
const result = await fetchTwice(`${host}/api/parser`, {
method: `POST`,
body: JSON.stringify(body),
headers: { 'Content-Type': 'application/json' },
}).then((res) => res.json())

expect(result).toEqual({
a: 'json',
})
})

it(`file in multipart/form`, async () => {
const file = readFileSync(path.join(__dirname, './fixtures/test.txt'))

const form = new FormData()
form.append('file', file, {
filename: 'test.txt',
contentType: 'text/plain',
})
form.append('something', 'here')
const result = await fetchTwice(`${host}/api/parser`, {
method: `POST`,
body: form,
headers: form.getHeaders(),
}).then((res) => res.json())

expect(result).toMatchSnapshot()
})
})

describe(`functions get parsed cookies`, () => {
test(`cookie`, async () => {
const result = await fetchTwice(`${host}/api/cookie-me`, {
headers: { cookie: `foo=blue;` },
}).then((res) => res.json())

expect(result).toEqual({
foo: 'blue',
})
})
})

describe(`functions can redirect`, () => {
test(`normal`, async () => {
const result = await fetchTwice(`${host}/api/redirect-me`)

expect(result.url).toEqual(`${host}/`)
})
})

describe(`functions can have custom middleware`, () => {
test(`normal`, async () => {
const result = await fetchTwice(`${host}/api/cors`)

const headers = Object.fromEntries(result.headers)
expect(headers[`access-control-allow-origin`]).toEqual(`*`)
})
})
})
}
6 changes: 6 additions & 0 deletions plugin/test/fixtures/v5/with-adapters/gatsby-config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
siteMetadata: {
title: 'Function test',
},
plugins: [`gatsby-plugin-netlify`],
}
6 changes: 6 additions & 0 deletions plugin/test/fixtures/v5/with-adapters/netlify.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[build]
command = "npm run build"
publish = "public/"

[[plugins]]
package = "../../../../src/index.ts"
Loading