var expect            = require('chai').expect;
var Promise           = require('promise');
var request           = require('request');
var TestCafe          = require('../../lib/');
var BrowserConnection = require('../../lib/browser/connection');
var COMMANDS          = require('../../lib/browser/commands');


var promisedRequest = Promise.denodeify(request);


describe('Browser connection', function () {
    var testCafe   = null;
    var connection = null;

    // Fixture setup/teardown
    before(function () {
        testCafe = new TestCafe(1335, 1336);
    });

    after(function () {
        testCafe.close();
    });

    // Test setup/teardown
    beforeEach(function () {
        connection = testCafe.createBrowserConnection();
    });

    afterEach(function () {
        connection.close();
    });

    // Tests
    it('Should fire "ready" event once established and redirect to idle page', function (done) {
        var eventFired = false;

        connection.on('ready', function () {
            eventFired = true;
        });

        var options = {
            url:            connection.url,
            followRedirect: false,
            headers:        {
                'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 ' +
                              '(KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36'
            }
        };

        request(options, function (err, res) {
            expect(eventFired).to.be.true;
            expect(connection.ready).to.be.true;
            expect(connection.userAgent.toAgent()).eql('Chrome 41.0.2227');
            expect(res.statusCode).eql(302);
            expect(res.headers['location']).eql(connection.idleUrl);

            done();
        });
    });

    it('Should respond with error if connection was established twice', function (done) {
        promisedRequest(connection.url)
            .then(function () {
                return promisedRequest(connection.url);
            })
            .then(function (res) {
                expect(res.statusCode).eql(500);
                expect(res.body).eql('The connection is already established.');
                done();
            })
            .catch(done);
    });

    it('Should fire "error" event on browser disconnection', function (done) {
        var savedHeartbeatTimeout = BrowserConnection.HEARTBEAT_TIMEOUT;

        BrowserConnection.HEARTBEAT_TIMEOUT = 0;

        connection.on('error', function (msg) {
            expect(msg).eql('The Chrome 41.0.2227 / Mac OS X 10.10.1 browser disconnected. This problem may ' +
                            'appear when a browser hangs or is closed, or due to network issues.');
            done();
        });

        var options = {
            url:            connection.url,
            followRedirect: false,
            headers:        {
                'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 ' +
                              '(KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36'
            }
        };

        request(options, function () {
            BrowserConnection.HEARTBEAT_TIMEOUT = savedHeartbeatTimeout;
        });
    });

    it('Should provide status', function (done) {
        function createBrowserJobMock (urls) {
            var doneHandler = null;

            return {
                getNextTestRunUrl: function () {
                    var url = urls.shift();

                    if (!urls.length)
                        doneHandler();

                    return url;
                },

                once: function (event, handler) {
                    if (event === 'done')
                        doneHandler = handler;
                }
            };
        }

        connection.addJob(createBrowserJobMock(['1', '2']));
        connection.addJob(createBrowserJobMock(['3']));

        function queryStatus () {
            return promisedRequest(connection.statusUrl);
        }

        promisedRequest(connection.url)

            .then(queryStatus)
            .then(function (res) {
                expect(JSON.parse(res.body)).eql({ cmd: COMMANDS.run, url: '1' });
            })

            .then(queryStatus)
            .then(function (res) {
                expect(JSON.parse(res.body)).eql({ cmd: COMMANDS.run, url: '2' });
            })

            .then(queryStatus)
            .then(function (res) {
                expect(JSON.parse(res.body)).eql({ cmd: COMMANDS.run, url: '3' });
            })

            .then(queryStatus)
            .then(function (res) {
                expect(JSON.parse(res.body)).eql({ cmd: COMMANDS.idle });
                done();
            })

            .catch(done);
    });

    it('Should respond with error on queries if not ready', function (done) {
        var testCases = [
            connection.heartbeatUrl,
            connection.idleUrl,
            connection.statusUrl
        ];

        testCases = testCases.map(function (url) {
            return promisedRequest(url).then(function (res) {
                expect(res.statusCode).eql(500);
                expect(res.body).eql('The connection is not ready yet.');
            });
        });

        Promise.all(testCases)
            .then(function () {
                done();
            })
            .catch(done);
    });
});


@@ -864,25 +864,8 @@
 ent 
-once established 
 and 
@@ -885,16 +885,33 @@
 dle page
+ once established
 ', funct
@@ -4769,29 +4769,41 @@
 ond 
-with error on queries
+to the service queries with error
  if 

Fix spelling in test names