123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542 |
- import request from 'supertest';
- import express from 'express';
- import path from 'path';
- import { jest } from '@jest/globals';
- import { getDirname } from '../utils.js';
- import store from '../store';
- import { MemoryBackend } from '../store/backends';
- import { MemoryFileBackend } from '../fileStore/backends';
- /*jest.mock('nanoid', () => {
- let count = 0;
- return {
- customAlphabet: () =>
- jest.fn(() => {
- return 'nanoid_' + count++;
- }),
- };
- });*/
- const __dirname = getDirname(import.meta.url);
- let delta = 0;
- // Fake date
- jest.spyOn(global.Date, 'now').mockImplementation(() => {
- delta += 1;
- const second = delta < 10 ? '0' + delta : '' + delta;
- return new Date(`2020-03-14T11:01:${second}.135Z`).valueOf();
- });
- describe('Store Test', () => {
- let query;
- let backend;
- beforeAll(() => {
- const app = express();
- app.use(express.json());
- app.use(express.urlencoded({ extended: true }));
- backend = MemoryBackend();
- app.use(
- '/:siteId',
- (req, _, next) => {
- req.siteId = req.params.siteId;
- next();
- },
- store({
- backend,
- })
- );
- query = request(app);
- });
- it('should get empty box', async () => {
- const box = 'myboxid_test1';
- await backend.createOrUpdateBox(`_fakeSiteId__${box}`, {
- security: 'public',
- });
- await query
- .get(`/fakeSiteId/store/${box}/`)
- .expect(200, [])
- .expect('Content-Type', /json/);
- });
- it('should add resource', async () => {
- const box = 'myboxid_test2';
- await backend.createOrUpdateBox(`_fakeSiteId__${box}`, {
- security: 'public',
- });
- const res = await query
- .post(`/fakeSiteId/store/${box}/`)
- .send({ test: true, value: 42 })
- .expect(200);
- expect(res.body).toEqual(
- expect.objectContaining({ test: true, value: 42 })
- );
- expect(typeof res.body._id).toEqual('string');
- expect(res.body._createdOn).toBeGreaterThanOrEqual(1584183661135);
- const res2 = await query
- .get(`/fakeSiteId/store/${box}/`)
- .expect(200)
- .expect('Content-Type', /json/);
- expect(res.body).toEqual(res2.body[0]);
- // Test object creation with id
- const resWithId = await query
- .post(`/fakeSiteId/store/${box}/myid`)
- .send({ foo: 'bar', bar: 'foo' })
- .expect(200);
- expect(resWithId.body._id).toBe('myid');
- });
- it('should get a resource', async () => {
- const box = 'myboxid_test3';
- await backend.createOrUpdateBox(`_fakeSiteId__${box}`, {
- security: 'public',
- });
- const res = await query
- .post(`/fakeSiteId/store/${box}/`)
- .send({ test: true, value: 42 })
- .expect(200);
- let resourceId = res.body._id;
- const res2 = await query
- .get(`/fakeSiteId/store/${box}/${resourceId}`)
- .expect(200)
- .expect('Content-Type', /json/);
- expect(res.body).toEqual(res2.body);
- });
- it('should update a resource', async () => {
- const box = 'myboxid_test4';
- await backend.createOrUpdateBox(`_fakeSiteId__${box}`, {
- security: 'public',
- });
- const res = await query
- .post(`/fakeSiteId/store/${box}/`)
- .send({ test: true, value: 40 })
- .expect(200);
- let resourceId = res.body._id;
- const res2 = await query
- .put(`/fakeSiteId/store/${box}/${resourceId}`)
- .send({ value: 42 })
- .expect(200);
- const res3 = await query
- .get(`/fakeSiteId/store/${box}/${resourceId}`)
- .expect(200);
- expect(res3.body.value).toEqual(42);
- const replaceWithId = await query
- .post(`/fakeSiteId/store/${box}/${resourceId}`)
- .send({ value: 52 })
- .expect(200);
- expect(replaceWithId.body).not.toEqual(
- expect.objectContaining({ test: true })
- );
- });
- it('should delete a resource', async () => {
- const box = 'myboxid_test5';
- await backend.createOrUpdateBox(`_fakeSiteId__${box}`, {
- security: 'public',
- });
- const res = await query
- .post(`/fakeSiteId/store/${box}/`)
- .send({ test: true, value: 40 })
- .expect(200);
- let resourceId = res.body._id;
- const res2 = await query
- .del(`/fakeSiteId/store/${box}/${resourceId}`)
- .expect(200)
- .expect('Content-Type', /json/);
- const res3 = await query.get(`/fakeSiteId/store/${box}/`).expect(200, []);
- });
- it('should return 404', async () => {
- const box = 'boxId_400';
- await backend.createOrUpdateBox(`_fakeSiteId__${box}`, {
- security: 'public',
- });
- await query.get(`/fakeSiteId/store/${box}/noresource`).expect(404);
- await query.delete(`/fakeSiteId/store/${box}/noresource`).expect(404);
- });
- it('should return 403', async () => {
- let box = 'boxId_500';
- await backend.createOrUpdateBox(`_fakeSiteId__${box}`, {
- security: 'readOnly',
- });
- await query.get(`/fakeSiteId/store/${box}/`).expect(200);
- await query
- .post(`/fakeSiteId/store/${box}/`)
- .send({ test: true, value: 40 })
- .expect(403);
- box = 'boxId_550';
- await backend.createOrUpdateBox(box);
- await query.get(`/fakeSiteId/store/${box}/`).expect(403);
- });
- it('should store and get a file', async () => {
- let box = 'boxId_600';
- await backend.createOrUpdateBox(`_fakeSiteId__${box}`, {
- security: 'public',
- });
- await query
- .post(`/fakeSiteId/store/${box}/1234`)
- .send({ test: true, value: 42 })
- .expect(200);
- const res = await query
- .post(`/fakeSiteId/store/${box}/1234/file/`)
- .attach('file', path.resolve(__dirname, 'testFile.txt'))
- .expect(200);
- const fileUrl = res.text;
- const fileRes = await query
- .get(`/${fileUrl}`)
- .buffer(false)
- .redirects(1)
- .expect(200);
- });
- });
- describe('Store Hook Tests', () => {
- let query;
- let backend;
- let hooks;
- beforeAll(() => {
- const app = express();
- app.use(express.json());
- app.use(express.urlencoded({ extended: true }));
- backend = MemoryBackend();
- hooks = {};
- app.use(
- '/:siteId',
- (req, _, next) => {
- req.siteId = req.params.siteId;
- next();
- },
- store({
- backend,
- hooks,
- })
- );
- query = request(app);
- });
- it('should call hooks for list', async () => {
- let box = 'boxId_1000';
- await backend.createOrUpdateBox(`_fakeSiteId__${box}`, {
- security: 'public',
- });
- hooks.before = [
- jest.fn((context) => context),
- jest.fn((context) => context),
- ];
- hooks.after = [
- jest.fn((context) => context),
- jest.fn((context) => context),
- ];
- await query.get(`/fakeSiteId/store/${box}/`).expect(200);
- expect(hooks.before[0]).toHaveBeenCalled();
- expect(hooks.before[1]).toHaveBeenCalled();
- expect(hooks.after[0]).toHaveBeenCalled();
- expect(hooks.after[1]).toHaveBeenCalled();
- });
- it('should call hooks for post & get & delete', async () => {
- let box = 'boxId_1100';
- await backend.createOrUpdateBox(`_fakeSiteId__${box}`, {
- security: 'public',
- });
- hooks.before = [
- jest.fn((context) => context),
- jest.fn((context) => context),
- ];
- hooks.after = [
- jest.fn((context) => context),
- jest.fn((context) => context),
- ];
- await query
- .post(`/fakeSiteId/store/${box}/1234`)
- .send({ test: true, value: 42 })
- .expect(200);
- expect(hooks.before[0]).toHaveBeenCalledTimes(1);
- expect(hooks.before[1]).toHaveBeenCalledTimes(1);
- expect(hooks.after[0]).toHaveBeenCalledTimes(1);
- expect(hooks.after[1]).toHaveBeenCalledTimes(1);
- jest.clearAllMocks();
- await query.get(`/fakeSiteId/store/${box}/1234`).expect(200);
- expect(hooks.before[0]).toHaveBeenCalled();
- expect(hooks.before[1]).toHaveBeenCalled();
- expect(hooks.after[0]).toHaveBeenCalled();
- expect(hooks.after[1]).toHaveBeenCalled();
- jest.clearAllMocks();
- await query.delete(`/fakeSiteId/store/${box}/1234`).expect(200);
- expect(hooks.before[0]).toHaveBeenCalled();
- expect(hooks.before[1]).toHaveBeenCalled();
- expect(hooks.after[0]).toHaveBeenCalled();
- expect(hooks.after[1]).toHaveBeenCalled();
- });
- it('hooks should modify post', async () => {
- let box = 'boxId_1200';
- await backend.createOrUpdateBox(`_fakeSiteId__${box}`, {
- security: 'public',
- });
- hooks.before = [
- jest.fn((context) => ({ ...context, body: { value: 256 } })),
- jest.fn((context) => ({
- ...context,
- body: { ...context.body, foo: 'bar' },
- })),
- ];
- hooks.after = [
- jest.fn((context) => context),
- jest.fn((context) => context),
- ];
- await query
- .post(`/fakeSiteId/store/${box}/1234`)
- .send({ test: true, value: 42 })
- .expect(200);
- const result = await query.get(`/fakeSiteId/store/${box}/1234`).expect(200);
- expect(result.body).toEqual(
- expect.objectContaining({ value: 256, foo: 'bar' })
- );
- });
- it('hooks should modify get', async () => {
- let box = 'boxId_1300';
- await backend.createOrUpdateBox(`_fakeSiteId__${box}`, {
- security: 'public',
- });
- hooks.before = [
- jest.fn((context) => context),
- jest.fn((context) => context),
- ];
- hooks.after = [
- jest.fn((context) => ({ ...context, response: { value: 256 } })),
- jest.fn((context) => ({
- ...context,
- response: { ...context.response, foo: 'bar' },
- })),
- ];
- await query
- .post(`/fakeSiteId/store/${box}/1234`)
- .send({ test: true, value: 42 })
- .expect(200);
- const result = await query.get(`/fakeSiteId/store/${box}/1234`).expect(200);
- expect(result.body).toEqual(
- expect.objectContaining({ value: 256, foo: 'bar' })
- );
- });
- it('hooks should force access to private store', async () => {
- let box = 'boxId_1400';
- await backend.createOrUpdateBox(`_fakeSiteId__${box}`, {
- security: 'private',
- });
- hooks.before = [
- jest.fn((context) => ({ ...context, allow: true })),
- jest.fn((context) => context),
- ];
- await query
- .post(`/fakeSiteId/store/${box}/1234`)
- .send({ test: true, value: 42 })
- .expect(200);
- await query.get(`/fakeSiteId/store/${box}`).expect(200);
- await query.get(`/fakeSiteId/store/${box}/1234`).expect(200);
- await query.delete(`/fakeSiteId/store/${box}/1234`).expect(200);
- });
- it('should store even if private box', async () => {
- let box = 'boxId_1500';
- await backend.createOrUpdateBox(`_fakeSiteId__${box}`, {
- security: 'private',
- });
- await query
- .post(`/fakeSiteId/store/${box}/1234/file/`)
- .attach('file', path.resolve(__dirname, 'testFile.txt'))
- .expect(403);
- hooks.beforeFile = [
- jest.fn((context) => ({ ...context, allow: true })),
- jest.fn((context) => context),
- ];
- await query
- .post(`/fakeSiteId/store/${box}/1234/file/`)
- .attach('file', path.resolve(__dirname, 'testFile.txt'))
- .expect(200);
- });
- });
- describe('Store File Test', () => {
- let query;
- let backend;
- let fileBackend;
- beforeAll(() => {
- const app = express();
- app.use(express.json());
- app.use(express.urlencoded({ extended: true }));
- backend = MemoryBackend();
- fileBackend = MemoryFileBackend();
- app.use(
- '/:siteId',
- (req, _, next) => {
- req.siteId = req.params.siteId;
- next();
- },
- store({
- backend,
- fileBackend,
- })
- );
- query = request(app);
- });
- it('should store even if resource missing', async () => {
- let box = 'boxId_600';
- await backend.createOrUpdateBox(`_fakeSiteId__${box}`, {
- security: 'public',
- });
- const res = await query
- .post(`/fakeSiteId/store/${box}/1234/file/`)
- .attach('file', path.resolve(__dirname, 'testFile.txt'))
- .expect(200);
- const fileUrl = res.text;
- await query.get(`/${fileUrl}`).buffer(false).redirects(1).expect(200);
- });
- it('should store and get a file', async () => {
- let box = 'boxId_600';
- await backend.createOrUpdateBox(`_fakeSiteId__${box}`, {
- security: 'public',
- });
- await query
- .post(`/fakeSiteId/store/${box}/1234`)
- .send({ test: true, value: 42 })
- .expect(200);
- const res = await query
- .post(`/fakeSiteId/store/${box}/1234/file/`)
- .attach('file', path.resolve(__dirname, 'testFile.txt'))
- .expect(200);
- const fileUrl = res.text;
- await query.get(`/${fileUrl}`).buffer(false).redirects(1).expect(200);
- });
- it('should not allow to store a file on readOnly store', async () => {
- let box = 'boxId_600';
- await backend.createOrUpdateBox(`_fakeSiteId__${box}`, {
- security: 'readOnly',
- });
- const fakeFile = { filename: 'test.txt', mimetype: 'text/plain' };
- await query
- .post(`/fakeSiteId/store/${box}/1234/file/`)
- .attach('file', path.resolve(__dirname, 'testFile.txt'))
- .expect(403);
- const fileName = await fileBackend.store(
- 'fakeSiteId',
- box,
- '1234',
- fakeFile
- );
- await query
- .get(`/fakeSiteId/store/${box}/1234/file/${fileName}`)
- .buffer(false)
- .redirects(1)
- .expect(200);
- });
- it('should not allow to store and get a file on private store', async () => {
- let box = 'boxId_600';
- await backend.createOrUpdateBox(`_fakeSiteId__${box}`, {
- security: 'private',
- });
- const fakeFile = { filename: 'test.txt', mimetype: 'text/plain' };
- await query
- .post(`/fakeSiteId/store/${box}/1234/file/`)
- .attach('file', path.resolve(__dirname, 'testFile.txt'))
- .expect(403);
- const fileName = await fileBackend.store(
- 'fakeSiteId',
- box,
- '1234',
- fakeFile
- );
- await query
- .get(`/fakeSiteId/store/${box}/1234/file/${fileName}`)
- .buffer(false)
- .redirects(1)
- .expect(403);
- });
- });
|