/* global beforeEach, describe, expect, it */
'use strict';

import { Model } from 'ponyjs/models/base.js';
import { NestedRelatedField, RelationDescriptor } from 'ponyjs/models/fields/related.js';


let Brand = Model('Brand');
let Kit = Model('Kit', {
    brand: new NestedRelatedField(Brand)
});



let generateResponse = function(object, status=200) {
    return [
        status,
        {'Content-type': 'application/json'},
        JSON.stringify(object)
    ];
}


describe('The base relation descriptor', () => {

    it('should throw on getter/setter access', () => {
        let descriptor = new RelationDescriptor(null, null);
        expect(() => descriptor.get(null)).to.throw(Error, 'Not implemented');
        expect(() => descriptor.set(null, null)).to.throw(Error, 'Not implemented');
    });

});


describe('Models with relation fields', () => {

    let server = null;

    beforeEach(() => {
        server = sinon.fakeServer.create();
        server.autoRespond = true;
        server.xhr.useFilters = true;

        server.xhr.addFilter(function (method, uri) {
            let matched = uri.startsWith('http://example.com') || uri.startsWith('http://api.external.com');
            // Sinon FakeXHR filters need to return `false` if the request should be stubbed and
            // `true` if it should be allowed to pass through.
            return !matched;
        });
    });

    afterEach(() => {
        server.restore();
    });

    it('should return null if the nested data is not present', () => {
        let kit = new Kit({id: 1});
        let kit2 = new Kit({id: 2, brand: null});
        expect(kit.brand).to.be.null;
        // check that second access returns the same instance
        let brand = kit.brand;
        expect(kit.brand).to.equal(brand);
        expect(kit2.brand).to.be.null;
    });

    it('should instantiate nested foreign keys', () => {
        let kit = new Kit({
            id: 1,
            brand: {
                id: 2
            }
        });
        expect(kit.brand).to.be.instanceOf(Brand);
        expect(kit.brand).to.deep.equal({id: 2});
    });

    it('should resolve nested foreign keys', () => {
        let rawKit = {
            "id": 1,
            "name": "S100 & Flak 38 Schnellboot",
            "kit_number": "",
            "box_image": {
                "small": null
            },
            "brand": {
                "id": 2,
                "name": "Revell",
                "is_active": true,
                "logo": {
                    "small": "http://example.com/media/image.jpg"
                }
            }
        };
        var okResponse = generateResponse(rawKit);
        server.respondWith('GET', 'http://example.com/api/v1/kit/1/', okResponse);
        let expectedBrand = new Brand({"id": 2,
            "name": "Revell",
            "is_active": true,
            "logo": {
                "small": "http://example.com/media/image.jpg"
            }
        });
        return Kit.objects.get({id: 1}).should
            .eventually.be.an.instanceof(Kit)
            .and.satisfy(kit => {
                return (kit.brand instanceof Brand);
            });
    });
});

@@ -297,180 +297,8 @@
 ;%0A%0A%0A
-%0Alet generateResponse = function(object, status=200) %7B%0A    return %5B%0A        status,%0A        %7B'Content-type': 'application/json'%7D,%0A        JSON.stringify(object)%0A    %5D;%0A%7D%0A%0A%0A
 desc
@@ -691,603 +691,8 @@
  %7B%0A%0A
-    let server = null;%0A%0A    beforeEach(() =%3E %7B%0A        server = sinon.fakeServer.create();%0A        server.autoRespond = true;%0A        server.xhr.useFilters = true;%0A%0A        server.xhr.addFilter(function (method, uri) %7B%0A            let matched = uri.startsWith('http://example.com') %7C%7C uri.startsWith('http://api.external.com');%0A            // Sinon FakeXHR filters need to return %60false%60 if the request should be stubbed and%0A            // %60true%60 if it should be allowed to pass through.%0A            return !matched;%0A        %7D);%0A    %7D);%0A%0A    afterEach(() =%3E %7B%0A        server.restore();%0A    %7D);%0A%0A
     
@@ -1353,1066 +1353,8 @@
 );%0A%0A
-    it('should resolve nested foreign keys', () =%3E %7B%0A        let rawKit = %7B%0A            %22id%22: 1,%0A            %22name%22: %22S100 & Flak 38 Schnellboot%22,%0A            %22kit_number%22: %22%22,%0A            %22box_image%22: %7B%0A                %22small%22: null%0A            %7D,%0A            %22brand%22: %7B%0A                %22id%22: 2,%0A                %22name%22: %22Revell%22,%0A                %22is_active%22: true,%0A                %22logo%22: %7B%0A                    %22small%22: %22http://example.com/media/image.jpg%22%0A                %7D%0A            %7D%0A        %7D;%0A        var okResponse = generateResponse(rawKit);%0A        server.respondWith('GET', 'http://example.com/api/v1/kit/1/', okResponse);%0A        let expectedBrand = new Brand(%7B%22id%22: 2,%0A            %22name%22: %22Revell%22,%0A            %22is_active%22: true,%0A            %22logo%22: %7B%0A                %22small%22: %22http://example.com/media/image.jpg%22%0A            %7D%0A        %7D);%0A        return Kit.objects.get(%7Bid: 1%7D).should%0A            .eventually.be.an.instanceof(Kit)%0A            .and.satisfy(kit =%3E %7B%0A                return (kit.brand instanceof Brand);%0A            %7D);%0A    %7D);%0A
 %7D);%0A

Remove some testing cruft