Skip to content

Commit

Permalink
Add basic smoke tests for adapter-node
Browse files Browse the repository at this point in the history
* verify the server starts
* verify it can serve a 404

---

Additional changes:

- create a server_base that creates the server but does not start it
- keep the existing server.js file which starts the server (non-breaking
interface)
- update the package type to module to enable esm imports

BUG #639
  • Loading branch information
samccone committed Mar 31, 2021
1 parent feb2db7 commit a056e19
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 54 deletions.
6 changes: 5 additions & 1 deletion packages/adapter-node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@
"name": "@sveltejs/adapter-node",
"version": "1.0.0-next.11",
"main": "index.js",
"type": "module",
"files": [
"files"
],
"scripts": {
"dev": "rollup -cw",
"build": "rollup -c",
"test": "uvu tests",
"lint": "eslint --ignore-path .gitignore \"**/*.{ts,js,svelte}\" && npm run check-format",
"format": "prettier --write . --config ../../.prettierrc --ignore-path .gitignore",
"check-format": "prettier --check . --config ../../.prettierrc --ignore-path .gitignore",
Expand All @@ -17,9 +19,11 @@
"@rollup/plugin-json": "^4.1.0",
"@sveltejs/kit": "workspace:*",
"compression": "^1.7.4",
"node-fetch": "^2.6.1",
"polka": "^1.0.0-next.13",
"rollup": "^2.41.1",
"sirv": "^1.0.11",
"typescript": "^4.2.3"
"typescript": "^4.2.3",
"uva": "^0.1.1"
}
}
1 change: 1 addition & 0 deletions packages/adapter-node/src/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export function render() {}
60 changes: 8 additions & 52 deletions packages/adapter-node/src/server.js
Original file line number Diff line number Diff line change
@@ -1,57 +1,13 @@
import compression from 'compression';
import fs from 'fs';
import polka from 'polka';
import { dirname, join } from 'path';
import sirv from 'sirv';
import { URL, fileURLToPath } from 'url';
// eslint-disable-next-line import/no-unresolved
import { get_body } from '@sveltejs/kit/http';
// App is a dynamic file built from the application layer.
/*eslint import/no-unresolved: [2, { ignore: ['\.\/app\.js$'] }]*/
import * as app from './app.js';

const __dirname = dirname(fileURLToPath(import.meta.url));
import { createServer } from './server_base.js';

const { PORT = 3000 } = process.env; // TODO configure via svelte.config.js

const mutable = (dir) =>
sirv(dir, {
etag: true,
maxAge: 0
});

const noop_handler = (_req, _res, next) => next();

const prerendered_handler = fs.existsSync('prerendered') ? mutable('prerendered') : noop_handler;

const assets_handler = sirv(join(__dirname, '/assets'), {
maxAge: 31536000,
immutable: true
const instance = createServer().listen(PORT, (err) => {
if (err) {
console.log('error', err);
} else {
console.log(`Listening on port ${PORT}`);
}
});

polka()
.use(compression({ threshold: 0 }), assets_handler, prerendered_handler, async (req, res) => {
const parsed = new URL(req.url || '', 'http://localhost');
const rendered = await app.render({
method: req.method,
headers: req.headers, // TODO: what about repeated headers, i.e. string[]
path: parsed.pathname,
body: await get_body(req),
query: parsed.searchParams
});

if (rendered) {
res.writeHead(rendered.status, rendered.headers);
res.end(rendered.body);
} else {
res.statusCode = 404;
res.end('Not found');
}
})
.listen(PORT, (err) => {
if (err) {
console.log('error', err);
} else {
console.log(`Listening on port ${PORT}`);
}
});
export { instance };
56 changes: 56 additions & 0 deletions packages/adapter-node/src/server_base.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import compression from 'compression';
import fs from 'fs';
import polka from 'polka';
import { dirname, join } from 'path';
import sirv from 'sirv';
import { URL, fileURLToPath } from 'url';
// eslint-disable-next-line import/no-unresolved
import { get_body } from '@sveltejs/kit/http';
// App is a dynamic file built from the application layer.
/*eslint import/no-unresolved: [2, { ignore: ['\.\/app\.js$'] }]*/
import * as app from './app.js';

const __dirname = dirname(fileURLToPath(import.meta.url));

const mutable = (dir) =>
sirv(dir, {
etag: true,
maxAge: 0
});

const noop_handler = (_req, _res, next) => next();

const prerendered_handler = fs.existsSync('prerendered') ? mutable('prerendered') : noop_handler;

const assets_handler = sirv(join(__dirname, '/assets'), {
maxAge: 31536000,
immutable: true
});

export function createServer() {
const server = polka().use(
compression({ threshold: 0 }),
assets_handler,
prerendered_handler,
async (req, res) => {
const parsed = new URL(req.url || '', 'http://localhost');
const rendered = await app.render({
method: req.method,
headers: req.headers, // TODO: what about repeated headers, i.e. string[]
path: parsed.pathname,
body: await get_body(req),
query: parsed.searchParams
});

if (rendered) {
res.writeHead(rendered.status, rendered.headers);
res.end(rendered.body);
} else {
res.statusCode = 404;
res.end('Not found');
}
}
);

return server;
}
19 changes: 19 additions & 0 deletions packages/adapter-node/tests/setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import * as path from 'path';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
import * as fs from 'fs';
import { fileURLToPath } from 'url';
const appPath = path.resolve(path.join(__dirname, '../src/app.js'));
const assetsPath = path.resolve(path.join(__dirname, '../src/assets'));

fs.writeFileSync(
appPath,
`
export function render() {}
`
);

try {
fs.mkdirSync(assetsPath);
} catch (e) {
// it is ok if this is already there.
}
33 changes: 33 additions & 0 deletions packages/adapter-node/tests/smoke.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { test } from 'uvu';
import { createServer } from '../src/server_base.js';
import * as assert from 'uvu/assert';
import fetch from 'node-fetch';

const { PORT = 3000 } = process.env;

function startServer() {
const server = createServer();
return new Promise((res, rej) => {
server.listen(PORT, (err) => {
if (err) {
rej(err);
}
res(server);
});
});
}

test('starts a server', async () => {
const server = await startServer();
assert.ok('server started');
server.server.close();
});

test('serves a 404', async () => {
const server = await startServer();
const res = await fetch(`http://localhost:${PORT}/nothing`);
assert.equal(res.status, 404);
server.server.close();
});

test.run();
32 changes: 31 additions & 1 deletion pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit a056e19

Please sign in to comment.