/*-
 * ============LICENSE_START=======================================================
 * ONAP CLAMP
 * ================================================================================
 * Copyright (C) 2019 AT&T Intellectual Property. All rights
 *                             reserved.
 * ================================================================================
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * ============LICENSE_END============================================
 * ===================================================================
 *
 */
import React from 'react';
import { shallow } from 'enzyme';
import LoopUI from './LoopUI';
import OnapConstants from './utils/OnapConstants';

import LoopCache from './api/LoopCache';
import LoopActionService from './api/LoopActionService';
import LoopService from './api/LoopService';

describe('Verify LoopUI', () => {
	beforeEach(() => {
		fetch.resetMocks();
		fetch.mockImplementation(() => {
			return Promise.resolve({
				ok: true,
				status: 200,
				text: () => "testUser"

			});
		});
	})

	const loopCache = new LoopCache({
		"name": "LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca",
		"components": {
			"POLICY": {
				"componentState": {
					"stateName": "UNKNOWN",
					"description": "The policies defined have NOT yet been created on the policy engine"
				}
			},
			"DCAE": {
				"componentState": {
					"stateName": "BLUEPRINT_DEPLOYED",
					"description": "The DCAE blueprint has been found in the DCAE inventory but not yet instancianted for this loop"
				}
			}
		}
	});

	it('Test the render method', async () => {
		const flushPromises = () => new Promise(setImmediate);

		const component = shallow(<LoopUI />)
		component.setState({
			loopName: "testLoopName",
			showAlert: false 
		});
		await flushPromises();
		expect(component).toMatchSnapshot();
	});

	test('Test closeLoop method', () => {
		const historyMock = { push: jest.fn() };
		const component = shallow(<LoopUI history={historyMock}/>)
		const instance = component.instance();
		instance.closeLoop();
			
		expect(component.state('loopName')).toEqual(OnapConstants.defaultLoopName);
		expect(historyMock.push.mock.calls[0]).toEqual([ '/']);
	})

	test('Test logout method', async () => {
		const flushPromises = () => new Promise(setImmediate);
		const component = shallow(<LoopUI />)
		const instance = component.instance();
		instance.logout();
		await flushPromises();
		expect(component.state('userName')).toEqual("testUser");
	})

	test('Test loadLoop method refresh suc', async () => {
		const historyMock = { push: jest.fn() };
		LoopService.getLoop = jest.fn().mockImplementation(() => {
			return Promise.resolve({
				ok: true,
				status: 200,
				text: () => {}
			});
		});

		LoopActionService.refreshStatus = jest.fn().mockImplementation(() => {
			return Promise.resolve({name: "LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca"});
		});

		const flushPromises = () => new Promise(setImmediate);
		const component = shallow(<LoopUI history={historyMock}/>)
		const instance = component.instance();
		instance.loadLoop("LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca");

		await flushPromises();

		const resLoopCache = instance.getLoopCache();
			
		expect(resLoopCache.getComponentStates()).toBeUndefined();
		expect(component.state('loopName')).toEqual("LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca");
	})

	test('Test loadLoop method refresh fail', async () => {
		const historyMock = { push: jest.fn() };
		LoopService.getLoop = jest.fn().mockImplementation(() => {
			return Promise.resolve({
			name: "LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca",
			"components": {
				"POLICY": {
					"componentState": {
						"stateName": "UNKNOWN",
						"description": "The policies defined have NOT yet been created on the policy engine"
					}
				},
				"DCAE": {
					"componentState": {
						"stateName": "BLUEPRINT_DEPLOYED",
						"description": "The DCAE blueprint has been found in the DCAE inventory but not yet instancianted for this loop"
					}
				}
			}});
		});

		LoopActionService.refreshStatus = jest.fn().mockImplementation(() => {
			return Promise.reject({error: "whatever"});
		});

		const flushPromises = () => new Promise(setImmediate);
		const component = shallow(<LoopUI history={historyMock}/>)
		const instance = component.instance();
		instance.loadLoop("LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca");

		await flushPromises();

		const resLoopCache = instance.getLoopCache();
			
		expect(resLoopCache).toEqual(loopCache);
		expect(component.state('loopName')).toEqual("LOOP_Jbv1z_v1_0_ResourceInstanceName1_tca");
	})

	test('Test alert methods', () => {
		const component = shallow(<LoopUI />)
		expect(component.state('showAlert')).toEqual(false);

		const instance = component.instance();
		instance.showAlert("testAlert");
		expect(component.state('showAlert')).toEqual(true);
		expect(component.state('showMessage')).toEqual("testAlert");

		instance.disableAlert();
			
		expect(component.state('showAlert')).toEqual(false);
	})
});
