diff --git a/package.json b/package.json index 4f72ffb5c8..3d6945f393 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "test": "jest --runInBand", "test:api-unit": "jest \"server/.*.spec.js\" --verbose", "test:api-unit:themes": "jest \"server/.*.spec.js\" -t \"theme bundle\" --verbose", + "test:api-unit:css": "jest \"server/.*.spec.js\" -t \"Get CSS\" --verbose", "test:coverage": "jest --coverage --silent --runInBand", "test:dev": "jest --verbose --watch", "test:basic": "jest tests/markdown/basic.test.js --verbose", diff --git a/server/app.js b/server/app.js index 8b3e4652b5..9afc9f2708 100644 --- a/server/app.js +++ b/server/app.js @@ -9,7 +9,7 @@ const yaml = require('js-yaml'); const app = express(); const config = require('./config.js'); -const { homebrewApi, getBrew, getUsersBrewThemes } = require('./homebrew.api.js'); +const { homebrewApi, getBrew, getUsersBrewThemes, getCSS } = require('./homebrew.api.js'); const GoogleActions = require('./googleActions.js'); const serveCompressedStaticAssets = require('./static-assets.mv.js'); const sanitizeFilename = require('sanitize-filename'); @@ -201,6 +201,9 @@ app.get('/download/:id', asyncHandler(getBrew('share')), (req, res)=>{ res.status(200).send(brew.text); }); +//Serve brew styling +app.get('/css/:id', asyncHandler(getBrew('share')), (req, res)=>{getCSS(req, res);}); + //User Page app.get('/user/:username', async (req, res, next)=>{ const ownAccount = req.account && (req.account.username == req.params.username); diff --git a/server/homebrew.api.js b/server/homebrew.api.js index c314454e2f..52fe57360e 100644 --- a/server/homebrew.api.js +++ b/server/homebrew.api.js @@ -148,6 +148,20 @@ const api = { next(); }; }, + + getCSS : async (req, res)=>{ + const { brew } = req; + if(!brew) return res.status(404).send(''); + splitTextStyleAndMetadata(brew); + if(!brew.style) return res.status(404).send(''); + + res.set({ + 'Cache-Control' : 'no-cache', + 'Content-Type' : 'text/css' + }); + return res.status(200).send(brew.style); + }, + mergeBrewText : (brew)=>{ let text = brew.text; if(brew.style !== undefined) { diff --git a/server/homebrew.api.spec.js b/server/homebrew.api.spec.js index 5f1739b972..d168c73fb8 100644 --- a/server/homebrew.api.spec.js +++ b/server/homebrew.api.spec.js @@ -50,6 +50,7 @@ describe('Tests for api', ()=>{ res = { status : jest.fn(()=>res), send : jest.fn(()=>{}), + set : jest.fn(()=>{}), setHeader : jest.fn(()=>{}) }; @@ -916,4 +917,66 @@ brew`); expect(saved.googleId).toEqual(brew.googleId); }); }); + describe('Get CSS', ()=>{ + it('should return brew style content as CSS text', async ()=>{ + const testBrew = { title: 'test brew', text: '```css\n\nI Have a style!\n````\n\n' }; + + const toBrewPromise = (brew)=>new Promise((res)=>res({ toObject: ()=>brew })); + api.getId = jest.fn(()=>({ id: '1', googleId: undefined })); + model.get = jest.fn(()=>toBrewPromise(testBrew)); + + const fn = api.getBrew('share', true); + const req = { brew: {} }; + const next = jest.fn(); + await fn(req, null, next); + await api.getCSS(req, res); + + expect(req.brew).toEqual(testBrew); + expect(req.brew).toHaveProperty('style', '\nI Have a style!\n'); + expect(res.status).toHaveBeenCalledWith(200); + expect(res.send).toHaveBeenCalledWith("\nI Have a style!\n"); + expect(res.set).toHaveBeenCalledWith({ + 'Cache-Control' : 'no-cache', + 'Content-Type' : 'text/css' + }); + }); + + it('should return 404 when brew has no style content', async ()=>{ + const testBrew = { title: 'test brew', text: 'I don\'t have a style!' }; + + const toBrewPromise = (brew)=>new Promise((res)=>res({ toObject: ()=>brew })); + api.getId = jest.fn(()=>({ id: '1', googleId: undefined })); + model.get = jest.fn(()=>toBrewPromise(testBrew)); + + const fn = api.getBrew('share', true); + const req = { brew: {} }; + const next = jest.fn(); + await fn(req, null, next); + await api.getCSS(req, res); + + expect(req.brew).toEqual(testBrew); + expect(req.brew).toHaveProperty('style'); + expect(res.status).toHaveBeenCalledWith(404); + expect(res.send).toHaveBeenCalledWith(''); + }); + + it('should return 404 when brew does not exist', async ()=>{ + const testBrew = { }; + + const toBrewPromise = (brew)=>new Promise((res)=>res({ toObject: ()=>brew })); + api.getId = jest.fn(()=>({ id: '1', googleId: undefined })); + model.get = jest.fn(()=>toBrewPromise(testBrew)); + + const fn = api.getBrew('share', true); + const req = { brew: {} }; + const next = jest.fn(); + await fn(req, null, next); + await api.getCSS(req, res); + + expect(req.brew).toEqual(testBrew); + expect(req.brew).toHaveProperty('style'); + expect(res.status).toHaveBeenCalledWith(404); + expect(res.send).toHaveBeenCalledWith(''); + }); + }); });