import { TestBed } from '@angular/core/testing';
import { BixiMockModule } from './mock.module';
import { IMockRequest, IMockInfo, IMockConfig, ISafeAny } from './mock.type';
import { MockService } from './mock.service';

const DATA = {
  TESTS: {
    '/users': () => {
      return 'hello';
    },
    '/users/1': () => {
      return { id: 1, 'rank': '★★★' }
    },
    '/users/:id': (req: IMockRequest) => {
      return { id: req.params.id, s: 'detail' };
    },
    '/users/:id/edit': (req: IMockRequest) => {
      return { id: req.params.id, s: 'edit' };
    },
    '/user': {
      get: () => {
        return 'user';
      },
      post: () => {
        return 'post user';
      }
    }
  }
};

describe('mock: service', () => {
  let mockService: MockService;
  function genModule(options: IMockConfig) {
    TestBed.configureTestingModule({
      imports: [BixiMockModule.forRoot(options)]
    });
    mockService = TestBed.inject<MockService>(MockService);
  }

  describe('# base usaging', () => {
    beforeEach(() =>
      genModule({ data: DATA }),
    );

    afterEach(() => mockService.ngOnDestroy());

    it('should be default', () => {
      const collect = mockService.getCollect('', '/users') as IMockInfo;
      expect(collect.url).toBe('/users');
      expect(collect.method).toBe('GET');
    });

    it('should be Post', () => {
      const collect = mockService.getCollect('POST', '/user') as IMockInfo;
      expect(collect.url).toBe('/user');
      expect(collect.method).toBe('POST');
    });

    it('should be invalid url', () => {
      expect(mockService.getCollect('GET', '/org/users/2')).toBeNull();
    });

    it('should mock collect priority', () => {
      const editRule = mockService.getCollect('GET', '/users/1/edit') as IMockInfo;
      const editRes = editRule.value.value(editRule as ISafeAny);
      expect(editRes.s).toBe('edit');
      const detailRule = mockService.getCollect('GET', '/users/1') as IMockInfo;
      expect((detailRule.value.value as ISafeAny)().rank).not.toBeUndefined();
    });
  });

  describe('# apply', () => {
    it('should allow empty data', () => {
      genModule({
        data: null,
      });
      expect(mockService.collects.length).toBe(0);
    });

    it('should be default GET method', () => {
      genModule({
        data: {
          USERS: {
            '/userss': {
              do: () => {
                return 'invalid method'
              }
            },
          },
        },
      });
      const collect = mockService.getCollect('', '/userss') as IMockInfo;
      expect(collect.url).toBe('/userss');
      expect(collect.method).toBe('GET');
    });
  });

  it('# clearCollect', () => {
    genModule({ data: DATA });
    mockService.clearCollect();
    const collect = mockService.getCollect('POST', '/users/1');
    expect(collect).toBeNull();
  });
});
