Skip to content

Commit

Permalink
Fixed Jest Backend Tests
Browse files Browse the repository at this point in the history
  • Loading branch information
R1c4rdCo5t4 committed Mar 23, 2024
1 parent c232b30 commit 6a7dfce
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 71 deletions.
15 changes: 10 additions & 5 deletions code/server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,13 @@ app.use('/', api);

io.on('connection', onConnection(service, events));

server.listen(PORT, () => {
console.log(`listening on http://localhost:${PORT}`);
});

export default app;
// do not start the server if this file is being imported
if (require.main === module) {
server.listen(PORT, () => {
console.log(`listening on http://localhost:${PORT}`);
});
}
export default {
app,
onConnection: onConnection(service, events),
};
100 changes: 51 additions & 49 deletions code/server/tests/conflict-resolution/crdt.test.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,41 @@
import { Server } from 'socket.io';
import * as http from 'http';
import { io, Socket } from 'socket.io-client';
import { InsertOperation, DeleteOperation } from '@notespace/shared/crdt/types/operations';
import { Node } from '@notespace/shared/crdt/types/nodes';
import { FugueTree } from '@notespace/shared/crdt/FugueTree';
import request = require('supertest');
import { getApp, treeToString } from '../utils';
import { Express } from 'express';

const baseURL = `http://localhost:${process.env.PORT}`;
let app: Express;
import { treeToString } from '../utils';
import { Server } from 'socket.io';
import server from '../../src/server';

const { app, onConnection } = server;
const PORT = process.env.PORT || 8080;
const BASE_URL = `http://localhost:${PORT}`;
let ioServer: Server;
let clientSocket1: Socket;
let clientSocket2: Socket;
let httpServer: http.Server;
let client1: Socket;
let client2: Socket;

beforeAll(done => {
app = getApp();
const httpServer = http.createServer(app);
httpServer = http.createServer(app);
ioServer = new Server(httpServer);
clientSocket1 = io(baseURL);
clientSocket2 = io(baseURL);
done();

ioServer.on('connection', onConnection);
httpServer.listen(PORT, () => {
client1 = io(BASE_URL);
client2 = io(BASE_URL);
done();
});
});

afterAll(() => {
ioServer.close();
clientSocket1.close();
clientSocket2.close();
afterAll(done => {
ioServer.off('connection', onConnection);
ioServer.close(() => {
client1.close();
client2.close();
httpServer.close();
done();
});
});

describe('Operations must be commutative', () => {
Expand All @@ -37,82 +45,76 @@ describe('Operations must be commutative', () => {
});

test('insert operations should be commutative', async () => {
const insertMessage1: InsertOperation = {
const insert1: InsertOperation = {
type: 'insert',
id: { sender: 'A', counter: 0 },
value: 'a',
parent: { sender: 'root', counter: 0 },
side: 'R',
};
const insertMessage2: InsertOperation = {
const insert2: InsertOperation = {
type: 'insert',
id: { sender: 'B', counter: 0 },
value: 'b',
parent: { sender: 'root', counter: 0 },
side: 'R',
};
// client 1 inserts 'a' and client 2 inserts 'b'
client1.emit('operation', insert1);
client2.emit('operation', insert2);

const responsePromises = [
new Promise(resolve => {
clientSocket1.emit('operation', insertMessage1, resolve);
}),
new Promise(resolve => {
clientSocket2.emit('operation', insertMessage2, resolve);
})
];

await Promise.all(responsePromises);

await new Promise(resolve => setTimeout(resolve, 500));
const response = await request(app).get('/document');
expect(response.status).toBe(200);
const nodes = response.body as Record<string, Node<string>[]>;
const tree = new FugueTree<string>();
tree.setTree(new Map(Object.entries(nodes)));
const result = treeToString(tree);
expect(result).toBe('ab');
}, 10000);
});
});

describe('Operations must be idempotent', () => {
beforeEach(async () => {
const response = await request(app).delete('/document');
expect(response.status).toBe(200);
const insertMessage: InsertOperation = {
const insert1: InsertOperation = {
type: 'insert',
id: { sender: 'A', counter: 0 },
value: 'a',
parent: { sender: 'root', counter: 0 },
side: 'R',
};
const insertMessage2: InsertOperation = {
const insert2: InsertOperation = {
type: 'insert',
id: { sender: 'B', counter: 0 },
value: 'a',
parent: { sender: 'root', counter: 0 },
side: 'R',
};
// both clients insert 'a'
clientSocket1.emit('operation', insertMessage);
clientSocket2.emit('operation', insertMessage2);
await new Promise(resolve => setTimeout(resolve, 100)); // Ensure inserts are processed
client1.emit('operation', insert1);
client2.emit('operation', insert2);
await new Promise(resolve => setTimeout(resolve, 100));
});

test('delete operations should be idempotent', async () => {
const deleteMessage: DeleteOperation = {
test('delete operations should be idempotent', done => {
const delete1: DeleteOperation = {
type: 'delete',
id: { sender: 'A', counter: 0 },
id: { sender: 'B', counter: 0 },
};
// both clients want to delete the same 'a'
clientSocket1.emit('operation', deleteMessage);
clientSocket2.emit('operation', deleteMessage);

await new Promise(resolve => setTimeout(resolve, 100)); // Ensure deletes are processed
client1.emit('operation', delete1);
client2.emit('operation', delete1);

const response = await request(app).get('/document');
const nodes = response.body as Record<string, Node<string>[]>;
const tree = new FugueTree();
tree.setTree(new Map(Object.entries(nodes)));
const result = treeToString(tree);
expect(result).toBe('a');
setTimeout(async () => {
const response = await request(app).get('/document');
const nodes = response.body as Record<string, Node<string>[]>;
const tree = new FugueTree();
tree.setTree(new Map(Object.entries(nodes)));
const result = treeToString(tree);
expect(result).toBe('a');
done();
}, 500);
});
});
17 changes: 0 additions & 17 deletions code/server/tests/utils.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
import { FugueTree } from '@notespace/shared/crdt/FugueTree';
import express, { Express } from 'express';
import serviceInit from '../src/services/documentService';
import database from '../src/database/memory/operations';
import eventsInit from '../src/controllers/socket/events';
import router from '../src/controllers/http/router';
import cors from 'cors';
import app from '../src/server';

export function treeToString<T>(tree: FugueTree<T>): string {
let result = '';
Expand All @@ -14,13 +7,3 @@ export function treeToString<T>(tree: FugueTree<T>): string {
}
return result;
}

export function getApp(): Express {
const service = serviceInit(database);
const api = router(service);
const app = express();

app.use(cors({ origin: '*' }));
app.use('/', api);
return app;
}

0 comments on commit 6a7dfce

Please sign in to comment.