\ No newline at end of file
diff --git a/test/apps/preprocess/src/routes/index.svelte b/test/apps/preprocess/src/routes/index.svelte
new file mode 100644
index 000000000..a5c6174a4
--- /dev/null
+++ b/test/apps/preprocess/src/routes/index.svelte
@@ -0,0 +1 @@
+
Great success!
diff --git a/test/apps/preprocess/src/server.js b/test/apps/preprocess/src/server.js
new file mode 100644
index 000000000..243171f34
--- /dev/null
+++ b/test/apps/preprocess/src/server.js
@@ -0,0 +1,15 @@
+import polka from 'polka';
+import * as sapper from '@sapper/server';
+
+import { start } from '../../common.js';
+
+const app = polka()
+ .use(
+ sapper.middleware({
+ preprocess: (body) => {
+ return body.replace('%custom.data%', '
works!
');
+ }
+ })
+ );
+
+start(app);
diff --git a/test/apps/preprocess/src/service-worker.js b/test/apps/preprocess/src/service-worker.js
new file mode 100644
index 000000000..8adb97a43
--- /dev/null
+++ b/test/apps/preprocess/src/service-worker.js
@@ -0,0 +1,82 @@
+import * as sapper from '@sapper/service-worker';
+
+const ASSETS = `cache${sapper.timestamp}`;
+
+// `shell` is an array of all the files generated by webpack,
+// `files` is an array of everything in the `static` directory
+const to_cache = sapper.shell.concat(sapper.files);
+const cached = new Set(to_cache);
+
+self.addEventListener('install', event => {
+ event.waitUntil(
+ caches
+ .open(ASSETS)
+ .then(cache => cache.addAll(to_cache))
+ .then(() => {
+ self.skipWaiting();
+ })
+ );
+});
+
+self.addEventListener('activate', event => {
+ event.waitUntil(
+ caches.keys().then(async keys => {
+ // delete old caches
+ for (const key of keys) {
+ if (key !== ASSETS) await caches.delete(key);
+ }
+
+ self.clients.claim();
+ })
+ );
+});
+
+self.addEventListener('fetch', event => {
+ if (event.request.method !== 'GET') return;
+
+ const url = new URL(event.request.url);
+
+ // don't try to handle e.g. data: URIs
+ if (!url.protocol.startsWith('http')) return;
+
+ // ignore dev server requests
+ if (url.hostname === self.location.hostname && url.port !== self.location.port) return;
+
+ // always serve assets and webpack-generated files from cache
+ if (url.host === self.location.host && cached.has(url.pathname)) {
+ event.respondWith(caches.match(event.request));
+ return;
+ }
+
+ // for pages, you might want to serve a shell `index.html` file,
+ // which Sapper has generated for you. It's not right for every
+ // app, but if it's right for yours then uncomment this section
+ /*
+ if (url.origin === self.origin && routes.find(route => route.pattern.test(url.pathname))) {
+ event.respondWith(caches.match('/index.html'));
+ return;
+ }
+ */
+
+ if (event.request.cache === 'only-if-cached') return;
+
+ // for everything else, try the network first, falling back to
+ // cache if the user is offline. (If the pages never change, you
+ // might prefer a cache-first approach to a network-first one.)
+ event.respondWith(
+ caches
+ .open(`offline${sapper.timestamp}`)
+ .then(async cache => {
+ try {
+ const response = await fetch(event.request);
+ cache.put(event.request, response.clone());
+ return response;
+ } catch(err) {
+ const response = await cache.match(event.request);
+ if (response) return response;
+
+ throw err;
+ }
+ })
+ );
+});
diff --git a/test/apps/preprocess/src/template.html b/test/apps/preprocess/src/template.html
new file mode 100644
index 000000000..1786f84be
--- /dev/null
+++ b/test/apps/preprocess/src/template.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+ %sapper.base%
+ %sapper.styles%
+ %sapper.head%
+
+
+ %custom.data%
+
%sapper.html%
+ %sapper.scripts%
+
+
diff --git a/test/apps/preprocess/test.ts b/test/apps/preprocess/test.ts
new file mode 100644
index 000000000..d71bdafd4
--- /dev/null
+++ b/test/apps/preprocess/test.ts
@@ -0,0 +1,40 @@
+import * as assert from 'assert';
+import { build } from '../../../api';
+import { AppRunner } from '../AppRunner';
+
+describe('preprocess', function() {
+ this.timeout(10000);
+
+ let r: AppRunner;
+
+ // hooks
+ before('build app', () => build({ cwd: __dirname }));
+ before('start runner', async () => {
+ r = await new AppRunner().start(__dirname);
+ });
+
+ after(() => r && r.end());
+
+ // tests
+ it('respects `options.preprocess` data replacement', async () => {
+ await r.load('/');
+
+ assert.equal(
+ await r.text('#test'),
+ 'works!'
+ );
+ });
+
+ it('respects `options.preprocess` data replacement on error page', async () => {
+ await r.load('/error-page');
+
+ assert.equal(
+ await r.text('#test'),
+ 'works!'
+ );
+ });
+
+ it('survives the tests with no server errors', () => {
+ assert.deepEqual(r.errors, []);
+ });
+});