Skip to content
This repository was archived by the owner on Jan 28, 2025. It is now read-only.

feat: add HEAD http event to NextPages #43

Merged
merged 6 commits into from
Apr 7, 2019
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
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ events:
- http:
path: pageName # home, about, etc. Unless is the index page which is served at /
method: get
- http:
path: pageName # home, about, etc. Unless is the index page which is served at /
method: head
```

If you need to change the default configuration, such as `memorySize`, `timeout` etc. use the top level `provider` which will override the functions configuration. For example, to change the memorySize to 512MB:
Expand Down
15 changes: 15 additions & 0 deletions classes/NextPage.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const path = require("path");
const merge = require("lodash.merge");
const clone = require("lodash.clonedeep");
const toPosix = require("../utils/pathToPosix");
const PluginBuildDir = require("./PluginBuildDir");

Expand Down Expand Up @@ -85,10 +86,24 @@ class NextPage {
merge(configuration, this.serverlessFunctionOverrides);
}

const httpHeadEvents = this.getMatchingHttpHeadEvents(
configuration.events.filter(e => e.http.method === "get")
);

configuration.events = configuration.events.concat(httpHeadEvents);

return {
[this.functionName]: configuration
};
}

getMatchingHttpHeadEvents(httpGetEvents) {
return httpGetEvents.map(e => {
const headEvent = clone(e);
headEvent.http.method = "head";
return headEvent;
});
}
}

module.exports = NextPage;
167 changes: 121 additions & 46 deletions classes/__tests__/NextPage.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,19 @@ describe("NextPage", () => {
});

describe("#serverlessFunction", () => {
it("should return function http event path /", () => {
it("should have http GET event with path /", () => {
const { events } = page.serverlessFunction.indexPage;

expect(events).toHaveLength(1);

const httpEvent = events[0].http;
expect(httpEvent.method).toEqual("get");
expect(httpEvent.path).toEqual("/");
});

it("should have http HEAD event with path /", () => {
const { events } = page.serverlessFunction.indexPage;

const httpEvent = events[1].http;
expect(httpEvent.method).toEqual("head");
expect(httpEvent.path).toEqual("/");
});
});
Expand All @@ -47,13 +54,27 @@ describe("NextPage", () => {
expect(page.serverlessFunction.notFoundErrorPage).toBeDefined();
});

it("should return function http event path /{proxy+}", () => {
it("should return two events", () => {
const { events } = page.serverlessFunction.notFoundErrorPage;
expect(events).toHaveLength(2);
});

it("should return http event path /{proxy+} with GET method", () => {
const { events } = page.serverlessFunction.notFoundErrorPage;

expect(events).toHaveLength(1);
const httpGet = events[0].http;

const httpEvent = events[0].http;
expect(httpEvent.path).toEqual("/{proxy+}");
expect(httpGet.path).toEqual("/{proxy+}");
expect(httpGet.method).toEqual("get");
});

it("should return http event path /{proxy+} with HEAD method", () => {
const { events } = page.serverlessFunction.notFoundErrorPage;

const httpHead = events[1].http;

expect(httpHead.path).toEqual("/{proxy+}");
expect(httpHead.method).toEqual("head");
});
});
});
Expand All @@ -71,12 +92,15 @@ describe("NextPage", () => {
it("should have URI path matching subdirectories", () => {
const { events } = page.serverlessFunction.fridgesPage;

expect(events).toHaveLength(1);
expect(events).toHaveLength(2);

const httpEvent = events[0].http;
const httpGet = events[0].http;
const httpHead = events[1].http;

expect(httpEvent.path).toEqual("categories/fridge/fridges");
expect(httpEvent.method).toEqual("get");
expect(httpGet.path).toEqual("categories/fridge/fridges");
expect(httpGet.method).toEqual("get");
expect(httpHead.path).toEqual("categories/fridge/fridges");
expect(httpHead.method).toEqual("head");
});
});
});
Expand Down Expand Up @@ -167,54 +191,105 @@ describe("NextPage", () => {
expect(handler).toEqual(`${buildDir}/admin.render`);
});

it("should return function http event", () => {
it("should return 2 http events", () => {
const { events } = page.serverlessFunction.adminPage;
expect(events).toHaveLength(2);
});

expect(events).toHaveLength(1);
it("should return function http GET event", () => {
const { events } = page.serverlessFunction.adminPage;

const httpEvent = events[0].http;

expect(httpEvent.path).toEqual("admin");
expect(httpEvent.method).toEqual("get");
});

it("should override serverlessFunction with provided pageConfig", () => {
const serverlessFunctionOverrides = { foo: "bar" };

const pageWithCustomConfig = new NextPage(
pagePath,
serverlessFunctionOverrides
);

expect(pageWithCustomConfig.serverlessFunction.adminPage.foo).toBe(
"bar"
);
});

it("should NOT change handler with provided pageConfig", () => {
const serverlessFunctionOverrides = { handler: "invalid/handler" };
it("should return function http HEAD event", () => {
const { events } = page.serverlessFunction.adminPage;

const pageWithCustomConfig = new NextPage(
pagePath,
serverlessFunctionOverrides
);
const httpEvent = events[1].http;

expect(pageWithCustomConfig.serverlessFunction.adminPage.handler).toBe(
pageWithCustomConfig.pageHandler
);
expect(httpEvent.path).toEqual("admin");
expect(httpEvent.method).toEqual("head");
});

it("should NOT change runtime with provided pageConfig", () => {
const serverlessFunctionOverrides = { runtime: "python2.7" };

const pageWithCustomConfig = new NextPage(
pagePath,
serverlessFunctionOverrides
);

expect(pageWithCustomConfig.serverlessFunction.adminPage.runtime).toBe(
undefined
);
describe("When pageConfig override is provided", () => {
it("should create identical HEAD route for custom GET route", () => {
const serverlessFunctionOverrides = {
events: [
{
http: {
path: "admin/{id}",
request: {
parameters: {
id: true
}
}
}
}
]
};

const pageWithCustomConfig = new NextPage(
pagePath,
serverlessFunctionOverrides
);

const { events } = pageWithCustomConfig.serverlessFunction.adminPage;
expect(events).toHaveLength(2);

const httpGet = events[0].http;
const httpHead = events[1].http;

expect(httpGet.method).toBe("get");
expect(httpHead.method).toBe("head");

expect(httpGet.path).toBe("admin/{id}");
expect(httpHead.path).toBe("admin/{id}");

expect(httpGet.request.parameters.id).toBe(true);
expect(httpHead.request.parameters.id).toBe(true);
});

it("should override serverlessFunction with provided pageConfig", () => {
const serverlessFunctionOverrides = { foo: "bar" };

const pageWithCustomConfig = new NextPage(
pagePath,
serverlessFunctionOverrides
);

expect(pageWithCustomConfig.serverlessFunction.adminPage.foo).toBe(
"bar"
);
});

it("should NOT change handler with provided pageConfig", () => {
const serverlessFunctionOverrides = { handler: "invalid/handler" };

const pageWithCustomConfig = new NextPage(
pagePath,
serverlessFunctionOverrides
);

expect(
pageWithCustomConfig.serverlessFunction.adminPage.handler
).toBe(pageWithCustomConfig.pageHandler);
});

it("should NOT change runtime with provided pageConfig", () => {
const serverlessFunctionOverrides = { runtime: "python2.7" };

const pageWithCustomConfig = new NextPage(
pagePath,
serverlessFunctionOverrides
);

expect(
pageWithCustomConfig.serverlessFunction.adminPage.runtime
).toBe(undefined);
});
});
});
});
Expand Down
48 changes: 48 additions & 0 deletions integration/__tests__/package.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ describe.each`

describe("API gateway", () => {
let apiGWPageResources;
let apiGWGETMethodResources;
let apiGWHEADMethodResources;

beforeAll(() => {
apiGWPageResources = {
Expand All @@ -122,6 +124,22 @@ describe.each`
blog: resources.ApiGatewayResourceBlog,
fridges: resources.ApiGatewayResourceCategoriesFridgeFridges
};

apiGWGETMethodResources = {
home: resources.ApiGatewayMethodHomeGet,
about: resources.ApiGatewayMethodAboutGet,
post: resources.ApiGatewayMethodPostsIdVarGet,
blog: resources.ApiGatewayMethodBlogGet,
fridges: resources.ApiGatewayMethodCategoriesFridgeFridgesGet
};

apiGWHEADMethodResources = {
home: resources.ApiGatewayMethodHomeHead,
about: resources.ApiGatewayMethodAboutHead,
post: resources.ApiGatewayMethodPostsIdVarHead,
blog: resources.ApiGatewayMethodBlogHead,
fridges: resources.ApiGatewayMethodCategoriesFridgeFridgesHead
};
});

it.each`
Expand Down Expand Up @@ -153,6 +171,36 @@ describe.each`
);
});

it.each`
pageName | uri
${"home"} | ${"home"}
${"about"} | ${"about"}
${"blog"} | ${"blog"}
${"fridges"} | ${"fridges"}
`("page $pageName should have GET and HEAD methods", ({ pageName }) => {
expect(apiGWPageResources[pageName].Properties.PathPart).toEqual(
pageName
);
});

it.each`
pageName | uri
${"home"} | ${"home"}
${"about"} | ${"about"}
${"blog"} | ${"blog"}
${"fridges"} | ${"fridges"}
`(
"page $pageName should have a GET and HEAD methods",
({ pageName }) => {
expect(
apiGWGETMethodResources[pageName].Properties.HttpMethod
).toEqual("GET");
expect(
apiGWHEADMethodResources[pageName].Properties.HttpMethod
).toEqual("HEAD");
}
);

it("post page should have custom path and id parameter", () => {
expect(apiGWPageResources["post"].Properties.PathPart).toEqual(
"posts"
Expand Down