Edgio provides an EdgeJS testing utility to facilitate in unit-testing your Edgio router logic, helping to mock and run your routes in a test environment just as they would be handled live on your production site.
Configuration
If not already configured for your project, we require using
jest
for unit-testing your Edgio router logic. It is also recommended to use nock
for mocking HTTP requests your application may make.Bash
1npm i -D jest babel-jest nock @babel/core @babel/preset-env @babel/preset-typescript
Create
babel.config.js
in the root of your project:JavaScript
1module.exports = {2 presets: [3 ['@babel/preset-env', {targets: {node: 'current'}}],4 '@babel/preset-typescript',5 ],6};
You can find more information around configuring Jest with their Getting Started guide.
Testing
At the top of each unit test, import the following:
JavaScript
1// reference to your Edgio router2import routes from '../routes';34// router helper functions5import {6 runRoute,7 appHost,8 backendHost,9 staticHost,10} from '@edgio/core/test-utils';1112// http mocking library13import nock from 'nock';
Assertions
By default, importing
@edgio/core/test-utils
will automatically add the following assertions to Jest’s expect
function:toHaveHeader(name, [value])
toHaveBody(string|RegExp)
toBeCachedByTheEdge()
toBeCachedByTheEdgeFor(seconds)
toBeCachedByTheBrowser()
toBeCachedByTheBrowserFor(seconds)
toBeCachedByTheServiceWorker()
toBeCachedByTheServiceWorkerFor(seconds)
toBeServedStale()
toBeServedStaleFor(seconds)
Route Testing
To test a specific route handler, import
runRoute
from @edgio/core/testing-utils
. This function accepts your router instance, and the path of the route to run.JavaScript
1import { runRoute } from '@edgio/core/test-utils'2import router from '../src/routes'34...56it('should run the /foo route', () => {7 const handler = jest.fn()8 router.match('/foo', handler)910 const response = await runRoute(router, '/foo')1112 expect(handler).toBeCalled()13 expect(response.request.path).toEqual('/foo')14})
For extended route testing, you can import
createRouteMock
to set the path
, method
, headers
, or body
of the request:JavaScript
1import { runRoute, createRouteMock } from '@edgio/core/test-utils'2import router from '../src/routes'34...56it('should run the /search route', () => {7 const handler = jest.fn()8 router.post('/search', handler)910 const response = await runRoute(router, createRouteMock({11 path: '/search',12 method: 'POST',13 body: '{"query": "foo"}'14 }))1516 expect(handler).toBeCalled()17 expect(response.request.path).toEqual('/search')18})
Host Mocking
If the route being tested has an upstream request or serves a static file, you will want to mock these requests and responses. This decouples your unit tests from your upstream and application logic, focusing just on how the router responds to the given request. For this, we use
nock
along with appHost
, backendHost
, and staticHost
imported from @edgio/core/testing-utils
.These functions reference the backend entries defined in your
edgio.config.js
file.Mocking appHost Example
If your route sends a response from your application, such as
renderWithApp
or using NextRoutes
, NuxtRoutes
, etc., use appHost()
to reference the host and port for mocking the request and response.JavaScript
1// src/router.ts2...3export default new Router()4 .get('/collections/:path*', ({ cache }) => {5 cache({6 edge: {7 maxAgeSeconds: 60 * 608 }9 })10 })11 .fallback(({ renderWithApp }) => renderWithApp())
…
JavaScript
1// routes.test.ts2it('should cache the collections page at the edge for 1 hour', async () => {3 nock(`http://${appHost()}`).get('/collections/c1').reply(200, '');45 const result = await runRoute(routes, '/collections/c1');6 expect(result).toBeCachedByTheEdgeFor(60 * 60);7});
Mocking backendHost Example
Routes that use
proxy
to fetch from a backend can be mocked using backendHost(name)
, where name
is the key used for the backend defined in edgio.config.js
.JavaScript
1// edgio.config.js2module.exports = {3 routes: './src/routes.ts',4 backends: {5 origin: {6 domainOrIp: 'api.example.com',7 hostHeader: 'api.example.com',8 },9 },10};1112// src/routes.ts13export default new Router().get('/collections/:path*', ({cache, proxy}) => {14 cache({15 edge: {16 maxAgeSeconds: 60 * 60,17 },18 });19 proxy('origin');20});
…
JavaScript
1// routes.test.ts2it('should cache the collections page at the edge for 1 hour', async () => {3 nock(`http://${backendHost('origin')}`)4 .get('/collections/c1')5 .reply(200, '');67 const result = await runRoute(routes, '/collections/c1');8 expect(result).toBeCachedByTheEdgeFor(60 * 60);9});
Mocking staticHost Example
For serving static assets, mock the asset host using
staticHost()
.JavaScript
1// src/routes.ts2export default new Router().get('/icons/:path*', ({cache, serveStatic}) => {3 cache({4 edge: {5 maxAgeSeconds: 60 * 60,6 },7 });8 serveStatic('assets/icons/:path*');9});
…
JavaScript
1// routes.test.ts2it('should cache the static asset at the edge for 1 hour', async () => {3 nock(`http://${staticHost()}`).get('/assets/icons/user.png').reply(200, '');45 const result = await runRoute(routes, '/icons/user.png');6 expect(result).toBeCachedByTheEdgeFor(60 * 60);7});
Example Tests
For a more detailed example of EdgeJS unit testing, check out our Edgio Templates for a full implementation.