/*
 * Copyright © 2016-2018 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 } from 'sdc-app/onboarding/licenseModel/creation/LicenseModelCreation.js';
import LicenseModelCreationView from 'sdc-app/onboarding/licenseModel/creation/LicenseModelCreationView.jsx';
import {LicenseModelCreationFactory} from 'test-utils/factories/licenseModel/LicenseModelFactories.js';

describe('License Model Creation Module Tests', function() {
	it ('mapStateToProps mapper exists', () => {
		expect(mapStateToProps).toBeTruthy();
	});

	it ('should return empty data', () => {
		let state = {
			licenseModelList: [],
			licenseModel: {
				licenseModelCreation: {
					data: {}
				}
			},
			users: {
				usersList: []
			}
		};
		let props = mapStateToProps(state);
		expect(props.data).toEqual({});
	});

	it ('should return vlm names list', () => {
		let state = {
			licenseModelList: [{
				name: 'vlm1',
				id: 'vlm1_id'
			}, {
				name: 'vlm2',
				id: 'vlm2_id'
			}],
			licenseModel: {
				licenseModelCreation: {
					data: {}
				}
			},
			users: {
				usersList: []
			}
		};
		let props = mapStateToProps(state);
		expect(props.data).toEqual({});
		expect(props.VLMNames).toEqual({vlm1: 'vlm1_id', vlm2: 'vlm2_id'});
	});

	it('simple jsx test', () => {
		let data = LicenseModelCreationFactory.build();
		const renderer = new ShallowRenderer();
		renderer.render(
			<LicenseModelCreationView
				data={data}
				onDataChanged={() => {}}
				onValidateForm={() => {}}
				onSubmit={() => {}}
				onCancel={() => {}}/>
			);
		var renderedOutput = renderer.getRenderOutput();
		expect(renderedOutput).toBeTruthy();
	});
});
