chore: unify the workpad update handler (#31218) (#31817)

* test: assets and structures routes

* chore: unify the workpad update handler

the 3 functions were pretty much the same already
This commit is contained in:
Joe Fleming 2019-02-27 10:23:00 -07:00 committed by GitHub
parent 1267d2e0aa
commit d3491fad76
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 214 additions and 59 deletions

View file

@ -65,29 +65,10 @@ export function workpad(server) {
);
}
function updateWorkpad(req) {
const savedObjectsClient = req.getSavedObjectsClient();
const { id } = req.params;
const now = new Date().toISOString();
return savedObjectsClient.get(CANVAS_TYPE, id).then(workpad => {
// TODO: Using create with force over-write because of version conflict issues with update
return savedObjectsClient.create(
CANVAS_TYPE,
{
...omit(req.payload, 'id'),
'@timestamp': now,
'@created': workpad.attributes['@created'],
},
{ overwrite: true, id }
);
});
}
function updateWorkpadAssets(req) {
function updateWorkpad(req, newPayload) {
const savedObjectsClient = req.getSavedObjectsClient();
const { id } = req.params;
const payload = newPayload ? newPayload : req.payload;
const now = new Date().toISOString();
@ -97,30 +78,9 @@ export function workpad(server) {
CANVAS_TYPE,
{
...workpad.attributes,
assets: req.payload,
'@timestamp': now,
'@created': workpad.attributes['@created'],
},
{ overwrite: true, id }
);
});
}
function updateWorkpadStructures(req) {
const savedObjectsClient = req.getSavedObjectsClient();
const { id } = req.params;
const now = new Date().toISOString();
return savedObjectsClient.get(CANVAS_TYPE, id).then(workpad => {
// TODO: Using create with force over-write because of version conflict issues with update
return savedObjectsClient.create(
CANVAS_TYPE,
{
...workpad.attributes, // retain preexisting assets and prop order (or maybe better to call out the `assets` prop?)
...req.payload,
'@timestamp': now,
'@created': workpad.attributes['@created'],
...omit(payload, 'id'), // never write the id property
'@timestamp': now, // always update the modified time
'@created': workpad.attributes['@created'], // ensure created is not modified
},
{ overwrite: true, id }
);
@ -196,7 +156,8 @@ export function workpad(server) {
path: `${routePrefixAssets}/{id}`,
config: { payload: { allow: 'application/json', maxBytes: 26214400 } }, // 25MB payload limit
handler: function(request) {
return updateWorkpadAssets(request)
const payload = { assets: request.payload };
return updateWorkpad(request, payload)
.then(() => ({ ok: true }))
.catch(formatResponse);
},
@ -208,7 +169,7 @@ export function workpad(server) {
path: `${routePrefixStructures}/{id}`,
config: { payload: { allow: 'application/json', maxBytes: 26214400 } }, // 25MB payload limit
handler: function(request) {
return updateWorkpadStructures(request)
return updateWorkpad(request)
.then(() => ({ ok: true }))
.catch(formatResponse);
},

View file

@ -5,9 +5,18 @@
*/
import Hapi from 'hapi';
import { CANVAS_TYPE, API_ROUTE_WORKPAD } from '../../common/lib/constants';
import {
CANVAS_TYPE,
API_ROUTE_WORKPAD,
API_ROUTE_WORKPAD_ASSETS,
API_ROUTE_WORKPAD_STRUCTURES,
} from '../../common/lib/constants';
import { workpad } from './workpad';
const routePrefix = API_ROUTE_WORKPAD;
const routePrefixAssets = API_ROUTE_WORKPAD_ASSETS;
const routePrefixStructures = API_ROUTE_WORKPAD_STRUCTURES;
jest.mock('uuid/v4', () => jest.fn().mockReturnValue('123abc'));
describe(`${CANVAS_TYPE} API`, () => {
@ -53,11 +62,11 @@ describe(`${CANVAS_TYPE} API`, () => {
});
workpad(mockServer);
describe(`GET ${API_ROUTE_WORKPAD}/{id}`, () => {
describe(`GET ${routePrefix}/{id}`, () => {
test('returns successful response', async () => {
const request = {
method: 'GET',
url: `${API_ROUTE_WORKPAD}/123`,
url: `${routePrefix}/123`,
};
savedObjectsClient.get.mockResolvedValueOnce({ id: '123', attributes: { foo: true } });
@ -91,11 +100,11 @@ Object {
});
});
describe(`POST ${API_ROUTE_WORKPAD}`, () => {
describe(`POST ${routePrefix}`, () => {
test('returns successful response without id in payload', async () => {
const request = {
method: 'POST',
url: API_ROUTE_WORKPAD,
url: routePrefix,
payload: {
foo: true,
},
@ -140,7 +149,7 @@ Object {
test('returns succesful response with id in payload', async () => {
const request = {
method: 'POST',
url: API_ROUTE_WORKPAD,
url: routePrefix,
payload: {
id: '123',
foo: true,
@ -184,11 +193,11 @@ Object {
});
});
describe(`PUT ${API_ROUTE_WORKPAD}/{id}`, () => {
describe(`PUT ${routePrefix}/{id}`, () => {
test('formats successful response', async () => {
const request = {
method: 'PUT',
url: `${API_ROUTE_WORKPAD}/123`,
url: `${routePrefix}/123`,
payload: {
id: '234',
foo: true,
@ -254,11 +263,11 @@ Object {
});
});
describe(`DELETE ${API_ROUTE_WORKPAD}/{id}`, () => {
describe(`DELETE ${routePrefix}/{id}`, () => {
test('formats successful response', async () => {
const request = {
method: 'DELETE',
url: `${API_ROUTE_WORKPAD}/123`,
url: `${routePrefix}/123`,
};
savedObjectsClient.delete.mockResolvedValueOnce({});
@ -291,10 +300,10 @@ Object {
});
});
describe(`GET ${API_ROUTE_WORKPAD}/find`, async () => {
describe(`GET ${routePrefix}/find`, async () => {
const request = {
method: 'GET',
url: `${API_ROUTE_WORKPAD}/find?name=abc&page=2&perPage=10`,
url: `${routePrefix}/find?name=abc&page=2&perPage=10`,
};
savedObjectsClient.find.mockResolvedValueOnce({
@ -354,4 +363,189 @@ Object {
}
`);
});
describe(`PUT ${routePrefixAssets}/{id}`, () => {
test('only updates assets', async () => {
const request = {
method: 'PUT',
url: `${routePrefixAssets}/123`,
payload: {
'asset-123': {
id: 'asset-123',
'@created': '2019-02-14T00:00:00.000Z',
type: 'dataurl',
value: 'mockbase64data',
},
'asset-456': {
id: 'asset-456',
'@created': '2019-02-15T00:00:00.000Z',
type: 'dataurl',
value: 'mockbase64data',
},
},
};
// provide some existing workpad data to check that it's preserved
savedObjectsClient.get.mockResolvedValueOnce({
attributes: {
'@created': new Date().toISOString(),
name: 'fake workpad',
},
});
savedObjectsClient.create.mockResolvedValueOnce({});
const { payload, statusCode } = await mockServer.inject(request);
const response = JSON.parse(payload);
expect(statusCode).toBe(200);
expect(response).toMatchInlineSnapshot(`
Object {
"ok": true,
}
`);
expect(savedObjectsClient.get).toMatchInlineSnapshot(`
[MockFunction] {
"calls": Array [
Array [
"canvas-workpad",
"123",
],
],
"results": Array [
Object {
"isThrow": false,
"value": Promise {},
},
],
}
`);
expect(savedObjectsClient.create).toMatchInlineSnapshot(`
[MockFunction] {
"calls": Array [
Array [
"canvas-workpad",
Object {
"@created": "2019-02-12T21:01:22.479Z",
"@timestamp": "2019-02-12T21:01:22.479Z",
"assets": Object {
"asset-123": Object {
"@created": "2019-02-14T00:00:00.000Z",
"id": "asset-123",
"type": "dataurl",
"value": "mockbase64data",
},
"asset-456": Object {
"@created": "2019-02-15T00:00:00.000Z",
"id": "asset-456",
"type": "dataurl",
"value": "mockbase64data",
},
},
"name": "fake workpad",
},
Object {
"id": "123",
"overwrite": true,
},
],
],
"results": Array [
Object {
"isThrow": false,
"value": Promise {},
},
],
}
`);
});
});
describe(`PUT ${routePrefixStructures}/{id}`, () => {
test('only updates workpad', async () => {
const request = {
method: 'PUT',
url: `${routePrefixStructures}/123`,
payload: {
name: 'renamed workpad',
css: '.canvasPage { color: LavenderBlush; }',
},
};
// provide some existing asset data and a name to replace
savedObjectsClient.get.mockResolvedValueOnce({
attributes: {
'@created': new Date().toISOString(),
name: 'fake workpad',
assets: {
'asset-123': {
id: 'asset-123',
'@created': '2019-02-14T00:00:00.000Z',
type: 'dataurl',
value: 'mockbase64data',
},
},
},
});
savedObjectsClient.create.mockResolvedValueOnce({});
const { payload, statusCode } = await mockServer.inject(request);
const response = JSON.parse(payload);
expect(statusCode).toBe(200);
expect(response).toMatchInlineSnapshot(`
Object {
"ok": true,
}
`);
expect(savedObjectsClient.get).toMatchInlineSnapshot(`
[MockFunction] {
"calls": Array [
Array [
"canvas-workpad",
"123",
],
],
"results": Array [
Object {
"isThrow": false,
"value": Promise {},
},
],
}
`);
expect(savedObjectsClient.create).toMatchInlineSnapshot(`
[MockFunction] {
"calls": Array [
Array [
"canvas-workpad",
Object {
"@created": "2019-02-12T21:01:22.479Z",
"@timestamp": "2019-02-12T21:01:22.479Z",
"assets": Object {
"asset-123": Object {
"@created": "2019-02-14T00:00:00.000Z",
"id": "asset-123",
"type": "dataurl",
"value": "mockbase64data",
},
},
"css": ".canvasPage { color: LavenderBlush; }",
"name": "renamed workpad",
},
Object {
"id": "123",
"overwrite": true,
},
],
],
"results": Array [
Object {
"isThrow": false,
"value": Promise {},
},
],
}
`);
});
});
});