overhaul tests

This commit is contained in:
Rich Harris
2018-10-07 18:23:43 -04:00
committed by GitHub
parent 18acef3190
commit 5e59855a15
183 changed files with 4145 additions and 3126 deletions

View File

@@ -0,0 +1,70 @@
import * as path from 'path';
import * as assert from 'assert';
import { walk } from '../../utils';
import * as api from '../../../api';
describe('export', function() {
this.timeout(10000);
// hooks
before(() => {
return new Promise((fulfil, reject) => {
// TODO this is brittle. Make it unnecessary
process.chdir(__dirname);
process.env.NODE_ENV = 'production';
// TODO this API isn't great. Rethink it
const builder = api.build({
bundler: 'rollup'
}, {
src: path.join(__dirname, 'src'),
routes: path.join(__dirname, 'src/routes'),
dest: path.join(__dirname, '__sapper__/build')
});
builder.on('error', reject);
builder.on('done', () => {
// TODO it'd be nice if build and export returned promises.
// not sure how best to combine promise and event emitter
const exporter = api.exporter({
build: '__sapper__/build',
dest: '__sapper__/export',
static: 'static',
basepath: '',
timeout: 5000
});
exporter.on('error', (err: Error) => {
console.error(err);
reject(err);
});
exporter.on('done', () => fulfil());
});
});
});
it('crawls a site', () => {
const files = walk('__sapper__/export');
const client_assets = files.filter(file => file.startsWith('client/'));
const non_client_assets = files.filter(file => !file.startsWith('client/')).sort();
assert.ok(client_assets.length > 0);
assert.deepEqual(non_client_assets, [
'blog.json',
'blog/bar.json',
'blog/bar/index.html',
'blog/baz.json',
'blog/baz/index.html',
'blog/foo.json',
'blog/foo/index.html',
'blog/index.html',
'global.css',
'index.html',
'service-worker.js'
]);
});
// TODO test timeout, basepath
});

View File

@@ -0,0 +1,64 @@
import resolve from 'rollup-plugin-node-resolve';
import replace from 'rollup-plugin-replace';
import svelte from 'rollup-plugin-svelte';
const mode = process.env.NODE_ENV;
const dev = mode === 'development';
const config = require('../../../config/rollup.js');
export default {
client: {
input: config.client.input(),
output: config.client.output(),
plugins: [
replace({
'process.browser': true,
'process.env.NODE_ENV': JSON.stringify(mode)
}),
svelte({
dev,
hydratable: true,
emitCss: true
}),
resolve()
],
// temporary, pending Rollup 1.0
experimentalCodeSplitting: true
},
server: {
input: config.server.input(),
output: config.server.output(),
plugins: [
replace({
'process.browser': false,
'process.env.NODE_ENV': JSON.stringify(mode)
}),
svelte({
generate: 'ssr',
dev
}),
resolve({
preferBuiltins: true
})
],
external: ['sirv', 'polka'],
// temporary, pending Rollup 1.0
experimentalCodeSplitting: true
},
serviceworker: {
input: config.serviceworker.input(),
output: config.serviceworker.output(),
plugins: [
resolve(),
replace({
'process.browser': true,
'process.env.NODE_ENV': JSON.stringify(mode)
})
]
}
};

View File

@@ -0,0 +1,9 @@
import * as sapper from '../__sapper__/client.js';
window.start = () => sapper.start({
target: document.querySelector('#sapper')
});
window.prefetchRoutes = () => sapper.prefetchRoutes();
window.prefetch = href => sapper.prefetch(href);
window.goto = href => sapper.goto(href);

View File

@@ -0,0 +1,3 @@
<h1>{status}</h1>
<p>{error.message}</p>

View File

@@ -0,0 +1,11 @@
<h1>{post.title}</h1>
<script>
export default {
preload({ params }) {
return this.fetch(`blog/${params.slug}.json`).then(r => r.json()).then(post => {
return { post };
});
}
};
</script>

View File

@@ -0,0 +1,19 @@
import posts from './_posts.js';
export function get(req, res) {
const post = posts.find(post => post.slug === req.params.slug);
if (post) {
res.writeHead(200, {
'Content-Type': 'application/json'
});
res.end(JSON.stringify(post));
} else {
res.writeHead(404, {
'Content-Type': 'application/json'
});
res.end(JSON.stringify({ message: 'not found' }));
}
}

View File

@@ -0,0 +1,5 @@
export default [
{ slug: 'foo', title: 'once upon a foo' },
{ slug: 'bar', title: 'a bar is born' },
{ slug: 'baz', title: 'bazzily ever after' }
];

View File

@@ -0,0 +1,15 @@
<h1>blog</h1>
{#each posts as post}
<p><a href="blog/{post.slug}">{post.title}</a></p>
{/each}
<script>
export default {
preload() {
return this.fetch('blog.json').then(r => r.json()).then(posts => {
return { posts };
});
}
};
</script>

View File

@@ -0,0 +1,9 @@
import posts from './_posts.js';
export function get(req, res) {
res.writeHead(200, {
'Content-Type': 'application/json'
});
res.end(JSON.stringify(posts));
}

View File

@@ -0,0 +1,3 @@
<h1>Great success!</h1>
<a href="blog">blog</a>

View File

@@ -0,0 +1,15 @@
import sirv from 'sirv';
import polka from 'polka';
import * as sapper from '../__sapper__/server.js';
const { PORT, NODE_ENV } = process.env;
const dev = NODE_ENV === 'development';
polka()
.use(
sirv('static', { dev }),
sapper.middleware()
)
.listen(PORT, err => {
if (err) console.log('error', err);
});

View File

@@ -0,0 +1,82 @@
import { timestamp, files, shell, routes } from '../__sapper__/service-worker.js';
const ASSETS = `cache${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 = shell.concat(ASSETS);
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${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;
}
})
);
});

View File

@@ -0,0 +1,14 @@
<!doctype html>
<html lang="en">
<head>
<meta charset='utf-8'>
%sapper.base%
%sapper.styles%
%sapper.head%
</head>
<body>
<div id='sapper'>%sapper.html%</div>
%sapper.scripts%
</body>
</html>

View File

@@ -0,0 +1,3 @@
body {
font-family: 'Comic Sans MS';
}