import { mount } from 'enzyme';
import sinon from 'sinon';
import React from 'react';
import lolex from 'lolex';
import { PostalCode } from 'web-foundation';

describe('<PostalCode />', function() {
    it('should not geocode if there is no callback', function() {
        const wrapper = mount(<PostalCode />);

        wrapper.instance().update({ value() { return '94102'; } });

        expect(wrapper.instance().request).to.not.exist;
    });

    it('should not geocode if the format is weird', function() {
        const spy = sinon.spy(),
            wrapper = mount(<PostalCode match={ spy } />);

        wrapper.instance().update({ value() { return 'gibberish'; } });

        expect(spy.callCount).to.equal(0);
    });

    it('should validate a zipcode', function() {
        const spy = sinon.spy(),
            wrapper = mount(<PostalCode match={ spy } />);

        expect(wrapper.instance().constructor.validate('96706')).to.be.true;
    });

    it('should ask the server where a zipcode is', function(done) {
        const server = sinon.fakeServer.create(),
            spy = sinon.spy(),
            wrapper = mount(<PostalCode match={ spy } />),
            response = {
                places: [ {
                    'place name': 'Ewa Beach',
                    'state abbreviation': 'HI'
                } ]
            };

        try {
            server.respondWith(
                [
                    200,
                    { 'Content-Type': 'application/json' },
                    JSON.stringify(response)
                ]
            );

            wrapper.instance().update({
                value() { return '96706'; }
            });
            wrapper.instance().update({
                value() { return '96706'; }
            });

            server.respond();

            expect(spy.callCount).to.equal(1);

            server.restore();
            done();
        } catch (e) {
            server.restore();
            done(e);
        }
    });

    it('should bail if the server sends bad stuff', function(done) {
        const server = sinon.fakeServer.create(),
            spy = sinon.spy(),
            wrapper = mount(<PostalCode match={ spy } />);

        try {
            server.respondWith(
                [
                    200,
                    { 'Content-Type': 'application/json' },
                    '{}'
                ]
            );

            wrapper.instance().update({
                value() { return '96706'; }
            });

            server.respond();

            expect(spy.callCount).to.equal(0);

            server.restore();
            done();
        } catch (e) {
            server.restore();
            done(e);
        }
    });

    it('should call \'failed\' if server sends bad stuff', function(done) {
        const server = sinon.fakeServer.create(),
            goodSpy = sinon.spy(),
            badSpy = sinon.spy(),
            wrapper = mount(
                <PostalCode
                    match={ goodSpy }
                    failed={ badSpy } />);

        try {
            server.respondWith(
                [
                    400,
                    { 'Content-Type': 'application/json'},
                    '{}'
                ]
            );

            wrapper.instance().update({
                value() { return '96706'; }
            });

            server.respond();

            expect(goodSpy.callCount).to.equal(0);
            expect(badSpy.callCount).to.equal(1);

            server.restore();
            done();
        } catch (e) {
            server.restore();
            done();
        }
    });

    it('should call \'failed\' if server does not respond', function(done) {
        const server = sinon.fakeServer.create(),
            goodSpy = sinon.spy(),
            badSpy = sinon.spy(),
            wrapper = mount(<PostalCode
                match={ goodSpy }
                failed={ badSpy } />),
            clock = lolex.install();

        try {
            server.autoRespond = true;
            server.autoRespondAfter = 2000;

            wrapper.instance().update({
                value() { return '96706'; }
            });

            clock.tick(1000);
            expect(goodSpy.called).to.be.false;
            expect(badSpy.callCount).to.equal(1);

            server.restore();
            clock.uninstall();
            done();
        } catch (e) {
            server.restore();
            clock.uninstall();
            done(e);
        }
    });
});
