const schema = require('./data/eds-c-select.schema.json');
const exampleJson = require('./data/eds-c-select.example.json');
const hintSchema = require('../eds-c-hint/data/eds-c-hint.schema.json');
const labelSchema = require('../eds-c-label/data/eds-c-label.schema.json');
const errorMessageSchema = require('../eds-c-error-message/data/eds-c-error-message.schema.json');
const handlebars = require('handlebars');

const { findTemplates } = require('../../development/tests/templateLoader.js');
const { validateSchema } = require('../../development/tests/validate-schema');
const dataAttributesSchema = require('../eds-c-data-attributes/data/eds-c-data-attributes.schema.json');
findTemplates([
	'eds-c-select',
	'eds-c-label',
	'eds-c-hint',
	'eds-c-data-attributes',
	'eds-c-error-message'
]).load(handlebars);

const componentTemplate = '{{> eds-c-select}}';
const componentHbs = handlebars.compile(componentTemplate);
const renderedComponent = componentHbs(exampleJson);

describe('Label Schema Validation and Accessibility Test', () => {
	const { configureAxe, toHaveNoViolations } = require('jest-axe');
	expect.extend(toHaveNoViolations);

	const axe = configureAxe({
		rules: {
			region: { enabled: false }
		}
	});

	test('Example data matches schema', () => {
		const valid = validateSchema(schema, exampleJson, [
			{ name: 'eds-c-data-attributes', schema: dataAttributesSchema },
			{ name: 'eds-c-label', schema: labelSchema },
			{ name: 'eds-c-hint', schema: hintSchema },
			{ name: 'eds-c-error-message', schema: errorMessageSchema }
		]);
		expect(valid).toBeTruthy();
	});
	test('Should have the right attributes', () => {
		document.body.innerHTML = renderedComponent;

		const selectElement = document.querySelector('.eds-c-select');
		expect(selectElement.getAttribute('id')).toEqual('eds-select');
		expect(selectElement.getAttribute('name')).toEqual('pets');
		expect(selectElement.hasAttribute('disabled')).toBeFalsy();
	});

	test('Should have the right data attributes', () => {
		document.body.innerHTML = renderedComponent;

		const selectElement = document.querySelector('.eds-c-select');
		expect(selectElement.getAttribute('data-test')).toEqual('select-test');
		expect(selectElement.getAttribute('data-track-context')).toEqual(
			'springer-link'
		);
		expect(selectElement.getAttribute('data-track-content-type')).toEqual(
			'collection'
		);
		expect(selectElement.getAttribute('data-track-label')).toEqual(
			'collection'
		);
	});

	test('Should render disabled attributes', () => {
		const testData = {
			...exampleJson,
			disabled: true
		};
		document.body.innerHTML = componentHbs(testData);

		const selectElement = document.querySelector('.eds-c-select');
		expect(selectElement.hasAttribute('disabled')).toBeTruthy();
	});

	test('Should render a label', () => {
		document.body.innerHTML = renderedComponent;

		const selectElement = document.querySelector('.eds-c-form__field label');
		expect(selectElement).not.toBeNull();
		expect(selectElement.textContent.replace(/\s+/g, ' ').trim()).toContain(
			"What's your fav small animal? (optional)"
		);
	});

	test('Should render a options', () => {
		document.body.innerHTML = renderedComponent;

		const optionElement = document.querySelectorAll('.eds-c-select option');
		expect([...optionElement].length).toBe(4);
	});

	test('Should render optgroup', () => {
		const testData = {
			...exampleJson,
			optgroup: [
				{
					optgroupLabel: 'fruits',
					optgroupId: '1',
					optgroupSeparator: true,
					options: [
						{
							label: 'Banana',
							value: 'Banana'
						},
						{
							label: 'Cherry',
							value: 'Cherry'
						},
						{
							label: 'Lemon',
							value: 'Lemon'
						}
					]
				},
				{
					optgroupLabel: 'Vegetables',
					optgroupId: '2',
					optgroupSeparator: true,
					options: [
						{
							label: 'Carrot',
							value: 'Carrot'
						},
						{
							label: 'Eggplant',
							value: 'Eggplant'
						},
						{
							label: 'Potato',
							value: 'Potato'
						}
					]
				}
			]
		};
		document.body.innerHTML = componentHbs(testData);

		const optgroupElement = document.querySelectorAll('.eds-c-select optgroup');
		expect([...optgroupElement].length).toBe(2);
	});

	test('Should render option', () => {
		const testData = {
			...exampleJson,
			options: [
				{
					label: 'Horse',
					value: 'Horse'
				}
			]
		};
		document.body.innerHTML = componentHbs(testData);

		const optionElement = document.querySelector('.eds-c-select option');
		expect(optionElement.textContent.replace(/\s+/g, ' ').trim()).toBe('Horse');
		expect(optionElement.getAttribute('value')).toBe('Horse');
		expect(optionElement.hasAttribute('selected')).toBeFalsy();
		expect(optionElement.hasAttribute('disabled')).toBeFalsy();
	});

	test('Should render selected option', () => {
		const testData = {
			...exampleJson,
			options: [
				{
					label: 'Horse',
					selected: true,
					value: 'Horse'
				}
			]
		};
		document.body.innerHTML = componentHbs(testData);

		const optionElement = document.querySelector('.eds-c-select option');
		expect(optionElement.hasAttribute('selected')).toBeTruthy();
	});

	test('Should render selected option', () => {
		const testData = {
			...exampleJson,
			options: [
				{
					label: 'Horse',
					disabled: true,
					value: 'Horse'
				}
			]
		};
		document.body.innerHTML = componentHbs(testData);

		const optionElement = document.querySelector('.eds-c-select option');
		expect(optionElement.hasAttribute('disabled')).toBeTruthy();
	});

	test('Should render a hint', () => {
		const testData = {
			...exampleJson,
			hint: {
				hintText: 'Without optgroup.'
			}
		};
		document.body.innerHTML = componentHbs(testData);

		const hintElement = document.querySelector('.eds-c-hint');
		expect(hintElement).not.toBeNull();
		expect(hintElement.textContent.trim()).toBe('Without optgroup.');
	});

	test('Should render error', () => {
		const testData = {
			...exampleJson,
			error: {
				text: 'Error message',
				errorInputId: 'eds-select-one',
				icon: '/img/icons/eds-i-error-filled-medium.svg#eds-i-error-filled-medium'
			}
		};
		document.body.innerHTML = componentHbs(testData);

		const errorElement = document.querySelector('.eds-c-error-message');
		const selectElement = document.querySelector('.eds-c-select');
		expect(errorElement).not.toBeNull();
		expect(errorElement.textContent.trim()).toBe('Error message');
		expect(selectElement.hasAttribute('invalid')).toBeTruthy();
		expect(selectElement.getAttribute('aria-invalid')).toBeTruthy();
		expect(selectElement.getAttribute('aria-describedby')).toBe(
			'error-eds-select-one'
		);
	});

	test('Should render required attribute', () => {
		const testData = { ...exampleJson, required: true };
		document.body.innerHTML = componentHbs(testData);

		const selectElement = document.querySelector('.eds-c-select');
		expect(selectElement.hasAttribute('required')).toBeTruthy();
		expect(selectElement.getAttribute('aria-required')).toBeTruthy();
	});

	test('Should render disabled attribute', () => {
		const testData = { ...exampleJson, disabled: true };
		document.body.innerHTML = componentHbs(testData);

		const selectElement = document.querySelector('.eds-c-select');
		expect(selectElement.hasAttribute('disabled')).toBeTruthy();
	});

	test('Should render multiple attribute', () => {
		const testData = { ...exampleJson, multiple: true };
		document.body.innerHTML = componentHbs(testData);

		const selectElement = document.querySelector('.eds-c-select');
		expect(selectElement.hasAttribute('multiple')).toBeTruthy();
	});

	test('Should render autofocus attribute', () => {
		const testData = { ...exampleJson, autofocus: true };
		document.body.innerHTML = componentHbs(testData);

		const selectElement = document.querySelector('.eds-c-select');
		expect(selectElement.hasAttribute('autofocus')).toBeTruthy();
	});

	test('Should render size attribute', () => {
		const testData = { ...exampleJson, size: 70 };
		document.body.innerHTML = componentHbs(testData);

		const selectElement = document.querySelector('.eds-c-select');
		expect(selectElement.getAttribute('size')).toBe('70');
	});

	test('Should render selected attribute', () => {
		const testData = { ...exampleJson, disabled: true };
		document.body.innerHTML = componentHbs(testData);

		const selectElement = document.querySelector('.eds-c-select');
		expect(selectElement.hasAttribute('disabled')).toBeTruthy();
	});

	test('Template passes basic HTML accessibility', async () => {
		expect(await axe(renderedComponent)).toHaveNoViolations();
	});
});
