Skip to content

Commit

Permalink
#106 add rest endpoint to export a specific room
Browse files Browse the repository at this point in the history
  • Loading branch information
[email protected] authored and [email protected] committed Sep 5, 2020
1 parent 1775533 commit a719040
Show file tree
Hide file tree
Showing 4 changed files with 193 additions and 27 deletions.
88 changes: 62 additions & 26 deletions server/src/rest.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,34 +17,70 @@ import express from 'express';
*/
function init(app, store) {
const restRouter = express.Router();
restRouter.get('/status', (req, res) => buildStatusObject().then((status) => res.json(status)));

restRouter.get('/status', (req, res) =>
buildStatusObject(store).then((status) => res.json(status))
);
restRouter.get('/room/:roomId', (req, res) =>
buildRoomExportObject(store, req.params.roomId).then((roomExport) => {
if (roomExport) {
res.json(roomExport);
} else {
res.status(404).json({message: 'room not found'});
}
})
);

app.use('/api', restRouter);
}

export default {init};

export async function buildStatusObject(store) {
const allRooms = await store.getAllRooms();
const rooms = allRooms
.map(
(room) =>
new Immutable.Map({
storyCount: room.get('stories').size,
userCount: room.get('users').size,
userCountDisconnected: room.get('users').filter((user) => user.get('disconnected')).size,
lastActivity: room.get('lastActivity'),
markedForDeletion: room.get('markedForDeletion'),
created: room.get('created')
})
)
.toList()
.toJS();

function buildStatusObject() {
return store.getAllRooms().then((allRooms) => {
const rooms = allRooms
.map(
(room) =>
new Immutable.Map({
storyCount: room.get('stories').size,
userCount: room.get('users').size,
userCountDisconnected: room.get('users').filter((user) => user.get('disconnected'))
.size,
lastActivity: room.get('lastActivity'),
markedForDeletion: room.get('markedForDeletion'),
created: room.get('created')
})
)
.toList()
.toJS();

return {
rooms,
roomCount: rooms.length,
uptime: Math.floor(process.uptime())
};
});
return {
rooms,
roomCount: rooms.length,
uptime: Math.floor(process.uptime())
};
}

export async function buildRoomExportObject(store, roomId) {
const room = await store.getRoomById(roomId);
if (!room) {
return undefined;
}

const users = room.get('users').toJS();

return {
roomId: room.get('id'),
stories: Object.values(room.get('stories').toJS()).map((story) =>
buildStoryExportObject(story, users)
)
};
}

export default {init};
const buildStoryExportObject = (story, users) => ({
title: story.title,
description: story.description,
estimations: Object.entries(story.estimations).map((entry) => {
const matchingUser = users[entry[0]];
return {username: matchingUser ? matchingUser.username : entry[0], value: entry[1]};
})
});
22 changes: 21 additions & 1 deletion server/test/integration/serverIntegrationTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ describe('websocket endpoint', () => {
});

describe('REST endpoint', () => {
test('should return all rooms ', (done) => {
test('should return backend status', (done) => {
httpGetJSON(
{
host: 'localhost',
Expand All @@ -111,6 +111,26 @@ describe('REST endpoint', () => {
);
});

test('should return 404 if room does not exist', (done) => {
httpGetJSON(
{
host: 'localhost',
port: 3000,
path: '/api/room/1234',
method: 'GET',
headers: {
'Content-Type': 'application/json'
}
},
(err, statusCode, body) => {
expect(err).toBeFalsy();
expect(statusCode).toBe(404);
expect(body.message).toBeDefined();
done();
}
);
});

/**
* helper method to send HTTP GET requests to the backend under test
* @param options
Expand Down
102 changes: 102 additions & 0 deletions server/test/unit/restTest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import {buildRoomExportObject, buildStatusObject} from '../../src/rest';
import {newMockRoomsStore} from './testUtils';

test('buildStatusObject', async () => {
const roomsStore = newMockRoomsStore({
id: 'super-room',
stories: [{}],
users: [{id: '1'}, {id: '2', disconnected: true}]
});

const statusObject = await buildStatusObject(roomsStore);

expect(statusObject).toMatchObject({
rooms: [{storyCount: 1, userCount: 2, userCountDisconnected: 1}],
roomCount: 1,
uptime: expect.any(Number)
});
});

test('buildRoomExportObject', async () => {
const roomId = '1b370339-a8f9-411c-8a42-540609a2bcdb';
const roomsStore = newMockRoomsStore({
id: roomId,
users: {
'8d85c095-87bf-4e8f-9957-1e2b621f83de': {
id: '8d85c095-87bf-4e8f-9957-1e2b621f83de',
username: 'Sergio',
email: '[email protected]',
avatar: 1
},
'0afab6a7-2b26-4bbc-bb46-294ce255729c': {
id: '0afab6a7-2b26-4bbc-bb46-294ce255729c',
username: 'Foxy',
avatar: 2
}
},
stories: {
'just-some-id': {
title: 'second',
description: 's2 description',
id: 'just-some-id',
estimations: {
'0afab6a7-2b26-4bbc-bb46-294ce255729c': 3,
'8d85c095-87bf-4e8f-9957-1e2b621f83de': 3
},
createdAt: 1599237099010,
revealed: true
},
'a4ed287c-1cfd-49d4-b237-577b7190e76e': {
title: 'first',
description: 's1 descr',
id: 'a4ed287c-1cfd-49d4-b237-577b7190e76e',
estimations: {
'0afab6a7-2b26-4bbc-bb46-294ce255729c': 13,
'8d85c095-87bf-4e8f-9957-1e2b621f83de': 5
},
createdAt: 1599237066010,
revealed: true
}
},
created: 1599237063876,
lastActivity: 1599237085043,
markedForDeletion: false,
selectedStory: 'a4ed287c-1cfd-49d4-b237-577b7190e76e'
});

const roomExport = await buildRoomExportObject(roomsStore, roomId);

expect(roomExport).toMatchObject({
roomId: '1b370339-a8f9-411c-8a42-540609a2bcdb',
stories: [
{
title: 'second',
description: 's2 description',
estimations: [
{
username: 'Foxy',
value: 3
},
{
username: 'Sergio',
value: 3
}
]
},
{
title: 'first',
description: 's1 descr',
estimations: [
{
username: 'Foxy',
value: 13
},
{
username: 'Sergio',
value: 5
}
]
}
]
});
});
8 changes: 8 additions & 0 deletions server/test/unit/testUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ export function newMockRoomsStore(initialRoom) {
room = rm;
return Promise.resolve();
},
getAllRooms: () => {
const allRooms = new Immutable.Map();
if (!room) {
return Promise.resolve(allRooms);
}

return Promise.resolve(allRooms.set(room.get('id'), room));
},
manipulate: (fn) => (room = fn(room))
};
}
Expand Down

0 comments on commit a719040

Please sign in to comment.