import { NgModule } from '@angular/core';
import { TestBed } from '@angular/core/testing';
import { readFirst } from '@nrwl/angular/testing';

import { EffectsModule } from '@ngrx/effects';
import { StoreModule, Store } from '@ngrx/store';

import { NxModule } from '@nrwl/angular';

import { <%= className %>Entity } from './<%= fileName %>.models';
import { <%= className %>Effects } from './<%= fileName %>.effects';
import { <%= className %>Facade } from './<%= fileName %>.facade';

import * as <%= className %>Selectors from './<%= fileName %>.selectors';
import * as <%= className %>Actions from './<%= fileName %>.actions';
import {
  <%= constantName %>_FEATURE_KEY,
  State,
  initialState,
  reducer
} from './<%= fileName %>.reducer';

interface TestSchema {
  '<%= propertyName %>' : State
}

describe('<%= className %>Facade', () => {
  let facade: <%= className %>Facade;
  let store: Store<TestSchema>;
  const create<%= className %>Entity = (id: string, name = '' ) => ({
    id,
    name: name || `name-${id}`
  } as <%= className %>Entity);

  beforeEach(() => {
    
  });

  describe('used in NgModule', () => {

    beforeEach(() => {
      @NgModule({
        imports: [
          StoreModule.forFeature(<%= constantName %>_FEATURE_KEY, reducer),
          EffectsModule.forFeature([<%= className %>Effects])
        ],
        providers: [<%= className %>Facade]
      })
      class CustomFeatureModule {}

      @NgModule({
        imports: [
          NxModule.forRoot(),
          StoreModule.forRoot({}),
          EffectsModule.forRoot([]),
          CustomFeatureModule,
        ]
      })
      class RootModule {}
      TestBed.configureTestingModule({ imports: [RootModule] });

      store = TestBed.inject(Store);
      facade = TestBed.inject(<%= className %>Facade);
    });

    /**
     * The initially generated facade::loadAll() returns empty array
     */
    it('loadAll() should return empty list with loaded == true', async (done) => {
      try {
        let list = await readFirst(facade.all<%= className %>$);
        let isLoaded = await readFirst(facade.loaded$);

        expect(list.length).toBe(0);
        expect(isLoaded).toBe(false);

        facade.init();

        list = await readFirst(facade.all<%= className %>$);
        isLoaded = await readFirst(facade.loaded$);

        expect(list.length).toBe(0);
        expect(isLoaded).toBe(true);

        done();
      } catch (err) {
        done.fail(err);
      }
    });

    /**
     * Use `load<%= className %>Success` to manually update list
     */
    it('all<%= className %>$ should return the loaded list; and loaded flag == true', async (done) => {
      try {
        let list = await readFirst(facade.all<%= className %>$);
        let isLoaded = await readFirst(facade.loaded$);

        expect(list.length).toBe(0);
        expect(isLoaded).toBe(false);

        store.dispatch(<%= className %>Actions.load<%= className %>Success({
          <%= propertyName %>: [
            create<%= className %>Entity('AAA'),
            create<%= className %>Entity('BBB')
          ]})
        );

        list = await readFirst(facade.all<%= className %>$);
        isLoaded = await readFirst(facade.loaded$);

        expect(list.length).toBe(2);
        expect(isLoaded).toBe(true);

        done();
      } catch (err) {
        done.fail(err);
      }
    });
  });

});
