Cache clearing test case

node v8.17.0
version: 2.0.0
endpointsharetweet
var express = require("@runkit/runkit/express-endpoint/1.0.0"); var app = express(exports); const DELAY_TIME = 200; const VARY_HEADER = 'Force-Reload'; app.set('etag', false); app.set('x-powered-by', false); // Serve the test endpoint (with delay to allow caching to be tested) app.get('/test/:testid', (req, res) => { res.set('Cache-Control', 'max-age=86400'); res.set('Vary', VARY_HEADER); res.set('Content-type', 'text/html; charset=utf8'); setTimeout(() => { res.end(Date.now() + ' ' + Math.random()); }, DELAY_TIME); }); // Serve the Clear-Site-Data endpoint app.get('/clear-site-data', (req, res) => { res.set('Cache-Control', 'no-cache'); res.set('Clear-Site-Data', '"cache"'); res.end('OK'); }); // Serve the location.reload(true) clearer page app.get('/reloader-frame', (req, res) => { if (!req.query.url || req.query.url.match(/[^\w\/\.]/)) throw new Error ('Invalid param "url"'); res.set('Cache-Control', 'max-age=86400; immutable'); res.set('Content-type', 'text/html; charset=utf8'); res.end(` <html> <body> <iframe id='frame' src='${req.query.url}'></iframe> <script> const ifr = document.getElementById('frame'); ifr.addEventListener('load', e => { const content = ifr.contentWindow.document.body.innerHTML; const saved = localStorage.getItem('cache-test-saved'); if (saved) { localStorage.removeItem('cache-test-saved'); parent.postMessage(content, '*'); } else { localStorage.setItem('cache-test-saved', content); location.reload(true); } }); </script> </body> </html> `); }); // Serve the test page app.get('/', (req, res) => { res.set('Content-type', 'text/html; charset=utf-8'); res.set('Cache-control', 'no-cache'); res.end(` <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width"> <title>Cache clearance tests</title> <link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/mocha/4.0.1/mocha.css' /> <style>iframe { visibility: hidden; }</style> <script src='https://cdnjs.cloudflare.com/ajax/libs/expect.js/0.2.0/expect.js'></script> <script src='https://cdnjs.cloudflare.com/ajax/libs/mocha/4.0.1/mocha.js'></script> </head> <body> <div id="mocha"></div> <script> const SERVER_DELAY = ${DELAY_TIME}; const SERVER_VARY = '${VARY_HEADER}'; const previousContent = {}; async function isLoadedFromCache(url, mechanism, config) { let newcontent; if (mechanism == 'fetch') { config = config || {}; config.credentials = 'include'; newcontent = await fetch(url, config).then(resp => resp.text()); } else if (mechanism == 'nav') { const ifr = document.createElement('iframe'); ifr.src = url; document.body.appendChild(ifr); await new Promise(resolve => ifr.addEventListener('load', resolve)); newcontent = ifr.contentWindow.document.body.innerHTML; ifr.remove(); } else if (mechanism == 'reloader') { const reloaderUrl = '/reloader-frame?url='+encodeURIComponent(url); const ifr = document.createElement('iframe'); ifr.src = reloaderUrl; document.body.appendChild(ifr); newcontent = await new Promise(resolve => { window.addEventListener('message', function handler(e) { if (e.source === ifr.contentWindow) { window.removeEventListener('message', handler); resolve(e.data); } }); }); ifr.remove(); } const result = previousContent[url] === newcontent; previousContent[url] = newcontent; return result; } mocha.setup({ timeout: 5000, ui: 'bdd' }); describe('Has a single working cache', function() { const url1 = '/test/'+Math.floor(Math.random()*100000); const url2 = '/test/'+Math.floor(Math.random()*100000); it('should not be cached at the start of the run', async () => { expect(await isLoadedFromCache(url1, 'fetch')).to.be(false); expect(await isLoadedFromCache(url2, 'nav')).to.be(false); }); it('should hit cache on second fetch', async () => { expect(await isLoadedFromCache(url1, 'fetch')).to.be(true); }); it('should hit cache on second navigation', async () => { expect(await isLoadedFromCache(url2, 'nav')).to.be(true); }); it('should hit cache on navigation if loaded by fetch', async () => { expect(await isLoadedFromCache(url1, 'nav')).to.be(true); }); it('should hit cache on fetch if loaded by navigation', async () => { expect(await isLoadedFromCache(url2, 'fetch')).to.be(true); }); }); describe('Supports clearing cache using Vary', function() { const url = '/test/'+Math.floor(Math.random()*100000); // Populates the cache before(async function() { await isLoadedFromCache(url, 'fetch'); }); it('starts out with cache populated', async () => { expect(await isLoadedFromCache(url, 'fetch')).to.be(true); }); it('should make a network request if varied header changes', async () => { const options = { headers: {} }; options.headers[SERVER_VARY] = Math.random(); expect(await isLoadedFromCache(url, 'fetch', options)).to.be(false); }); it('should hit the network again for the next fetch', async () => { expect(await isLoadedFromCache(url, 'fetch')).to.be(false); }); it('should hit cache for subsequent fetches', async () => { expect(await isLoadedFromCache(url, 'fetch')).to.be(true); }); it('should also use the new cache for subsequent navigations', async () => { expect(await isLoadedFromCache(url, 'nav')).to.be(true); }); }); describe('Supports clearing cache using FetchOptions.cache', function() { const url = '/test/'+Math.floor(Math.random()*100000); before(async function() { await isLoadedFromCache(url, 'fetch'); }); it('starts out with cache populated', async () => { expect(await isLoadedFromCache(url, 'fetch')).to.be(true); }); it('should make a network request if FetchOptions.cache is set to "reload"', async () => { const options = { cache: 'reload' }; expect(await isLoadedFromCache(url, 'fetch', options)).to.be(false); }); it('should then hit cache on subsequent fetches', async () => { expect(await isLoadedFromCache(url, 'fetch')).to.be(true); }); it('should make a network request if FetchOptions.cache is set to "reload" (repeat)', async () => { const options = { cache: 'reload' }; expect(await isLoadedFromCache(url, 'fetch', options)).to.be(false); }); it('should also use the new cache for subsequent navigations', async () => { expect(await isLoadedFromCache(url, 'nav')).to.be(true); }); }); describe('Supports clearing cache using Clear-Site-Data', function() { const url1 = '/test/'+Math.floor(Math.random()*100000); const url2 = '/test/'+Math.floor(Math.random()*100000); before(async function() { await isLoadedFromCache(url1, 'fetch'); await isLoadedFromCache(url2, 'nav'); }); it('should hit network for a fetch if a Clear-Site-Data response is received first', async () => { expect(await isLoadedFromCache(url1, 'fetch')).to.be(true); await isLoadedFromCache('/clear-site-data', 'fetch', {"credentials": "same-origin"}); expect(await isLoadedFromCache(url1, 'fetch')).to.be(false); }); it('should hit network for a navigation if a Clear-Site-Data response is received first', async () => { expect(await isLoadedFromCache(url2, 'nav')).to.be(true); await isLoadedFromCache('/clear-site-data', 'nav'); expect(await isLoadedFromCache(url2, 'nav')).to.be(false); }); it('should clear nav cache even if CSD is received via fetch', async () => { expect(await isLoadedFromCache(url2, 'nav')).to.be(true); await isLoadedFromCache('/clear-site-data', 'fetch', {"credentials": "same-origin"}); expect(await isLoadedFromCache(url2, 'nav')).to.be(false); }); it('should clear fetch cache even if CSD is received via nav', async () => { expect(await isLoadedFromCache(url1, 'fetch')).to.be(true); await isLoadedFromCache('/clear-site-data', 'nav'); expect(await isLoadedFromCache(url1, 'fetch')).to.be(false); }); }); describe('Supports clearing cache using location.reload(true)', function() { const url = '/test/'+Math.floor(Math.random()*100000); before(async function() { await isLoadedFromCache(url, 'nav'); }); it('starts out with cache populated', async () => { expect(await isLoadedFromCache(url, 'nav')).to.be(true); }); it('should hit network when doing location.reload(true)', async () => { expect(await isLoadedFromCache(url, 'reloader')).to.be(false); }); it('should hit cache subsequently', async () => { expect(await isLoadedFromCache(url, 'nav')).to.be(true); }); }); mocha.run(); </script> </body> </html> `); }); // Return a 404 if no routes match app.use((req, res, next) => { res.set('Cache-Control', 'max-age=0; private'); res.status(404).end('Not found'); });
Loading…

no comments

    sign in to comment