/*
 * Copyright © 2016-2017 European Support Limited
 *
 * 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.
 */

import React from 'react';
import ShallowRenderer from 'react-test-renderer/shallow';
import {mapStateToProps, mapActionsToProps} from 'sdc-app/onboarding/versionsPage/creation/VersionsPageCreation.js';
import {VERSION_CREATION_FORM_NAME} from 'sdc-app/onboarding/versionsPage/creation/VersionsPageCreationConstants.js';
import VersionsPageCreationActionHelper from 'sdc-app/onboarding/versionsPage/creation/VersionsPageCreationActionHelper.js';
import VersionsPageCreationView from 'sdc-app/onboarding/versionsPage/creation/VersionsPageCreationView.jsx';
import {VersionsPageCreationFactory,
				VersionsPageCreationFieldInfoFactory} from 'test-utils/factories/versionsPage/VersionsPageCreationFactories.js';
import {VersionsPageAdditionalPropsFactory} from 'test-utils/factories/versionsPage/VersionsPageFactories.js';
import {storeCreator} from 'sdc-app/AppStore.js';

describe('Versions Page Creation Module Tests', function() {

	let versionCreationData, genericFieldInfo;
	let store, dispatch;

	beforeAll(() => {
		store = storeCreator();
		dispatch = store.dispatch;
		versionCreationData = VersionsPageCreationFactory.build();
		genericFieldInfo = VersionsPageCreationFieldInfoFactory.build();
	});

	const additionalProps = VersionsPageAdditionalPropsFactory.build();

	it ('mapStateToProps mapper exists', () => {

		expect(mapStateToProps).toBeTruthy();

	});

	it ('should return empty data', () => {

		const state = {
			versionsPage: {
				versionCreation: {
					data: {},
					genericFieldInfo: {}
				}
			}
		};

		const props = mapStateToProps(state);
		expect(props.data).toEqual({});
		expect(props.isFormValid).toEqual(true);

	});

	it ('should have state in props', () => {

		const state = {
			versionsPage: {
				versionCreation: {
					data: versionCreationData,
					genericFieldInfo
				}
			}
		};

		const props = mapStateToProps(state);
		expect(props.isFormValid).toEqual(true);
		expect(props.data.description).toEqual(versionCreationData.description);
		expect(props.genericFieldInfo).toEqual(genericFieldInfo);

	});

	it('simple jsx test', () => {

		const state = {
			versionsPage: {
				versionCreation: {
					data: versionCreationData,
					genericFieldInfo
				}
			}
		};

		const props = Object.assign({}, mapStateToProps(state), mapActionsToProps(dispatch, additionalProps), additionalProps);
		const renderer = new ShallowRenderer();
		renderer.render(<VersionsPageCreationView {...props} />);

		const renderedOutput = renderer.getRenderOutput();
		expect(renderedOutput).toBeTruthy();

	});

	it('open/close form actions', () => {

		VersionsPageCreationActionHelper.open(dispatch, additionalProps);
		expect(store.getState().versionsPage.versionCreation.formName).toEqual(VERSION_CREATION_FORM_NAME);

		VersionsPageCreationActionHelper.close(dispatch);
		expect(store.getState().versionsPage.versionCreation).toEqual({});

	});

});
