import { Observable, Subject } from 'rxjs';

import { services } from 'typescript-angular-utilities';
import __object = services.object;
import __array = services.array;
import __guid = services.guid;

import { UserRatingComponent } from './userRating';

describe('UserRatingComponent', () => {
	let userRating: UserRatingComponent;
	let setValue: sinon.SinonSpy;
	let control: any;

	beforeEach(() => {
		const validator = {
			validate: sinon.spy(() => Observable.empty()),
			initValidator: sinon.spy(),
		};
		userRating = new UserRatingComponent(<any>{}, null, <any>validator, __object.objectUtility, __array.arrayUtility, __guid.guid);

		control = { valueChanges: new Subject() };
		userRating.control = <any>control;
		setValue = sinon.spy(value => control.valueChanges.next(value));
		userRating.setValue = setValue;
	});

	it('should create a list of stars with values 5 to 1', (): void => {
		userRating.ngOnInit();

		expect(userRating.stars.length).to.equal(5);
		expect(userRating.stars[0].value).to.equal(5);
		expect(userRating.stars[1].value).to.equal(4);
		expect(userRating.stars[2].value).to.equal(3);
		expect(userRating.stars[3].value).to.equal(2);
		expect(userRating.stars[4].value).to.equal(1);
	});

	it('should set all stars less than or equal to the rating to filled', (): void => {
		userRating.ngOnInit();

		userRating.setRating(3);

		sinon.assert.calledOnce(setValue);
		sinon.assert.calledWith(setValue, 3);

		expect(userRating.stars[0].filled).to.be.false;
		expect(userRating.stars[1].filled).to.be.false;
		expect(userRating.stars[2].filled).to.be.true;
		expect(userRating.stars[3].filled).to.be.true;
		expect(userRating.stars[4].filled).to.be.true;
	});

	it('should set the initial view state based on the initial view value', (): void => {
		userRating.value = 2;
		userRating.ngOnInit();

		expect(userRating.stars[0].filled).to.be.false;
		expect(userRating.stars[1].filled).to.be.false;
		expect(userRating.stars[2].filled).to.be.false;
		expect(userRating.stars[3].filled).to.be.true;
		expect(userRating.stars[4].filled).to.be.true;
	});

	it('should update the view state with external changes', () => {
		userRating.ngOnInit();

		control.valueChanges.next(2);

		expect(userRating.stars[0].filled).to.be.false;
		expect(userRating.stars[1].filled).to.be.false;
		expect(userRating.stars[2].filled).to.be.false;
		expect(userRating.stars[3].filled).to.be.true;
		expect(userRating.stars[4].filled).to.be.true;
	});
});
