const spawn = require('child_process').spawn;
const client = require('socket.io-client');
const express = require('express');
const bodyParser = require('body-parser');

function runServer() {
    server = spawn(
        'node',
        [
            '--harmony',
            'index.js',
            '--port', '9909',
            '--backend-host', 'localhost',
            '--backend-port', '9908'
        ]
    );

    server.stdout.on('data', (data) => {
        console.log(data.toString());
    });
    server.stderr.on('data', (data) => {
        console.log(data.toString());
    });
    server.on('exit', () => {
        console.log('Server terminated');
    });

    return server;
}

function connect() {
    const socket = client('http://localhost:9909');

    socket.on('error', () => {});

    return socket;
}

describe('real-time service', () => {
    let server,
        socket;

    beforeEach(() => {
        server = runServer();
        socket = connect();
    });

    it('listens for websocket connections', (done) => {
        socket.on('connect', done);
    });

    it('exchanges hello messages', function(done) {
        socket.on('connect', () => {
            socket.emit('client-hello', {victim_id: 5});
            socket.on('server-hello', done);
        });
    });

    describe('backend communication', () => {
        let fakeServer;

        function fakeBackend(listenCallback, method, url, getCallback) {
            const app = express();
            app.use(bodyParser.json());
            app[method](url, getCallback);
            fakeServer = app.listen(9908, listenCallback);
        }

        beforeEach((done) => {
            socket.on('connect', () => {
                socket.emit('client-hello', {victim_id: 5});
                done();
            });
        });

        it('requests work from the backend', function(done) {
            fakeBackend(
                () => {
                    socket.emit('get-work');
                },
                'get',
                '/breach/get_work/5',
                done
            );
        });

        it('reports work-completed to the backend', function(done) {
            fakeBackend(
                () => {
                    socket.emit('work-completed', {work: {}, success: true});
                },
                'post',
                '/breach/work_completed/5',
                (request, response) => {
                    expect(request.body.success).toBe(true);
                    done();
                }
            );
        });

        it('reports failed work-completed after a client disconnects', function(done) {
            fakeBackend(
                () => {
                    socket.close();
                },
                'post',
                '/breach/work_completed/5',
                (request, response) => {
                    expect(request.body.success).toBe(false);
                    done();
                }
            );
        });

        afterEach(() => {
            fakeServer.close();
        });
    });

    afterEach(() => {
        server.kill();
        socket.close();
    });
});

@@ -885,16 +885,33 @@
   socket
+,%0A        socket2
 ;%0A%0A    b
@@ -1304,24 +1304,524 @@
 );%0A    %7D);%0A%0A
+    it('does not duplicate clients running', (done) =%3E %7B%0A        socket.on('connect', () =%3E %7B%0A            socket.emit('client-hello', %7Bvictim_id: 5%7D);%0A        %7D);%0A        socket.on('server-hello', () =%3E %7B%0A            socket2 = connect();%0A            socket2.on('connect', () =%3E %7B%0A                socket2.emit('client-hello', %7Bvictim_id: 5%7D);%0A            %7D);%0A            socket2.on('server-nowork', () =%3E %7B%0A                socket2.close();%0A                done();%0A            %7D);%0A        %7D);%0A    %7D);%0A%0A
     describe

Test the avoidance of duplicate clients