describe('factory vnModuleLoader', () => {
    let vnModuleLoader;
    let $rootScope;
    let $window;

    beforeEach(ngModule('vnCore'));

    beforeEach(inject((_vnModuleLoader_, _$rootScope_, $httpBackend, _$window_, $q) => {
        vnModuleLoader = _vnModuleLoader_;
        $rootScope = _$rootScope_;
        $window = _$window_;

        $window.validations = {};
        $window.routes = [
            {
                module: 'myModule',
                dependencies: ['fooModule', 'barModule']
            }, {
                module: 'fooModule',
                dependencies: ['myModule']
            }, {
                module: 'barModule'
            }
        ];

        $httpBackend.whenGET('Schemas/modelInfo')
            .respond({
                FooModel: {
                    properties: {
                        id: {type: 'Number'},
                        email: {type: 'String'},
                        field: {type: 'Boolean'}
                    },
                    validations: {
                        id: [{
                            validation: 'presence'
                        }],
                        email: [{
                            validation: 'format',
                            with: '/@/'
                        }],
                        field: [{
                            validation: 'custom',
                            bindedFunction: '() => true'
                        }]
                    }
                }
            });
        $httpBackend.flush();

        vnModuleLoader.moduleImport = () => $q.resolve();
    }));

    describe('load()', () => {
        it('should throw error if module does not exist', async() => {
            let errorThrown;

            vnModuleLoader.load('unexistentModule')
                .catch(() => errorThrown = true);
            $rootScope.$apply();

            expect(errorThrown).toBeTruthy();
        });

        it('should set module loaded to true when it is loaded', async() => {
            vnModuleLoader.load('barModule');
            $rootScope.$apply();

            expect(vnModuleLoader.loaded['barModule']).toBeTruthy();
        });

        it('should resolve returned promise when module is loaded', async() => {
            let loaded;

            vnModuleLoader.load('barModule')
                .then(() => loaded = true);
            $rootScope.$apply();

            expect(loaded).toBeTruthy();
        });

        it('should load dependencies', async() => {
            vnModuleLoader.load('fooModule');
            $rootScope.$apply();

            expect(vnModuleLoader.loaded['barModule']).toBeTruthy();
        });

        it('should work with circular dependencies', async() => {
            vnModuleLoader.load('myModule');
            $rootScope.$apply();

            expect(vnModuleLoader.loaded['fooModule']).toBeTruthy();
        });

        it('should load models information and parse validations', async() => {
            vnModuleLoader.load('barModule');

            let FooModel = $window.validations.FooModel;
            let validations = FooModel && FooModel.validations;

            expect(FooModel).toBeDefined();
            expect(validations).toBeDefined();
            expect(validations.email[0].with).toBeInstanceOf(RegExp);
            expect(validations.field[0].bindedFunction).toBeInstanceOf(Function);
        });
    });
});