Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor add_integration_flyout to break out nested methods #956

Merged
merged 5 commits into from
Sep 7, 2023
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@

exports[`Add Integration Flyout Test Renders add integration flyout with dummy integration name 1`] = `
<AddIntegrationFlyout
http={
Object {
"get": [MockFunction],
"post": [MockFunction],
}
}
integrationName="test"
integrationType="test"
onClose={[Function]}
onCreate={[Function]}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,358 @@
import { configure, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import { waitFor } from '@testing-library/react';
import { AddIntegrationFlyout } from '../add_integration_flyout';
import {
AddIntegrationFlyout,
checkDataSourceName,
doTypeValidation,
doNestedPropertyValidation,
doPropertyValidation,
fetchDataSourceMappings,
fetchIntegrationMappings,
doExistingDataSourceValidation,
} from '../add_integration_flyout';
import * as add_integration_flyout from '../add_integration_flyout';
import React from 'react';
import { HttpSetup } from '../../../../../../../src/core/public';

describe('Add Integration Flyout Test', () => {
configure({ adapter: new Adapter() });

it('Renders add integration flyout with dummy integration name', async () => {
const wrapper = mount(
<AddIntegrationFlyout onClose={jest.fn} onCreate={jest.fn} integrationName="test" />
<AddIntegrationFlyout
onClose={jest.fn}
onCreate={jest.fn}
integrationName="test"
integrationType="test"
http={
({
get: jest.fn(),
post: jest.fn(),
} as Partial<HttpSetup>) as HttpSetup
}
/>
);

await waitFor(() => {
expect(wrapper).toMatchSnapshot();
});
});
});

describe('doTypeValidation', () => {
it('should return true if required type is not specified', () => {
const toCheck = { type: 'string' };
const required = {};

const result = doTypeValidation(toCheck, required);

expect(result.ok).toBe(true);
});

it('should return true if types match', () => {
const toCheck = { type: 'string' };
const required = { type: 'string' };

const result = doTypeValidation(toCheck, required);

expect(result.ok).toBe(true);
});

it('should return true if object has properties', () => {
const toCheck = { properties: { prop1: { type: 'string' } } };
const required = { type: 'object' };

const result = doTypeValidation(toCheck, required);

expect(result.ok).toBe(true);
});

it('should return false if types do not match', () => {
const toCheck = { type: 'string' };
const required = { type: 'number' };

const result = doTypeValidation(toCheck, required);

expect(result.ok).toBe(false);
});
});

describe('doNestedPropertyValidation', () => {
it('should return true if type validation passes and no properties are required', () => {
const toCheck = { type: 'string' };
const required = { type: 'string' };

const result = doNestedPropertyValidation(toCheck, required);

expect(result.ok).toBe(true);
});

it('should return false if type validation fails', () => {
const toCheck = { type: 'string' };
const required = { type: 'number' };

const result = doNestedPropertyValidation(toCheck, required);

expect(result.ok).toBe(false);
});

it('should return false if a required property is missing', () => {
const toCheck = { type: 'object', properties: { prop1: { type: 'string' } } };
const required = {
type: 'object',
properties: { prop1: { type: 'string' }, prop2: { type: 'number' } },
};

const result = doNestedPropertyValidation(toCheck, required);

expect(result.ok).toBe(false);
});

it('should return true if all required properties pass validation', () => {
const toCheck = {
type: 'object',
properties: {
prop1: { type: 'string' },
prop2: { type: 'number' },
},
};
const required = {
type: 'object',
properties: {
prop1: { type: 'string' },
prop2: { type: 'number' },
},
};

const result = doNestedPropertyValidation(toCheck, required);

expect(result.ok).toBe(true);
});
});

describe('doPropertyValidation', () => {
it('should return true if all properties pass validation', () => {
const rootType = 'root';
const dataSourceProps = {
prop1: { type: 'string' },
prop2: { type: 'number' },
};
const requiredMappings = {
root: {
template: {
mappings: {
properties: {
prop1: { type: 'string' },
prop2: { type: 'number' },
},
},
},
},
};

const result = doPropertyValidation(rootType, dataSourceProps as any, requiredMappings);

expect(result.ok).toBe(true);
});

it('should return false if a property fails validation', () => {
const rootType = 'root';
const dataSourceProps = {
prop1: { type: 'string' },
prop2: { type: 'number' },
};
const requiredMappings = {
root: {
template: {
mappings: {
properties: {
prop1: { type: 'string' },
prop2: { type: 'boolean' },
},
},
},
},
};

const result = doPropertyValidation(rootType, dataSourceProps as any, requiredMappings);

expect(result.ok).toBe(false);
});

it('should return false if a required nested property is missing', () => {
const rootType = 'root';
const dataSourceProps = {
prop1: { type: 'string' },
};
const requiredMappings = {
root: {
template: {
mappings: {
properties: {
prop1: { type: 'string' },
prop2: { type: 'number' },
},
},
},
},
};

const result = doPropertyValidation(rootType, dataSourceProps as any, requiredMappings);

expect(result.ok).toBe(false);
});
});

describe('checkDataSourceName', () => {
it('Filters out invalid index names', () => {
const result = checkDataSourceName('ss4o_logs-no-exclams!', 'logs');

expect(result.ok).toBe(false);
});

it('Filters out incorrectly typed indices', () => {
const result = checkDataSourceName('ss4o_metrics-test-test', 'logs');

expect(result.ok).toBe(false);
});

it('Accepts correct indices', () => {
const result = checkDataSourceName('ss4o_logs-test-test', 'logs');

expect(result.ok).toBe(true);
});
});

describe('fetchDataSourceMappings', () => {
it('Retrieves mappings', async () => {
const mockHttp = {
post: jest.fn().mockResolvedValue({
source1: { mappings: { properties: { test: true } } },
source2: { mappings: { properties: { test: true } } },
}),
} as Partial<HttpSetup>;

const result = fetchDataSourceMappings('sample', mockHttp as HttpSetup);

await expect(result).resolves.toMatchObject({
source1: { properties: { test: true } },
source2: { properties: { test: true } },
});
});

it('Catches errors', async () => {
const mockHttp = {
post: jest.fn().mockRejectedValue(new Error('Mock error')),
} as Partial<HttpSetup>;

const result = fetchDataSourceMappings('sample', mockHttp as HttpSetup);

await expect(result).resolves.toBeNull();
});
});

describe('fetchIntegrationMappings', () => {
it('Returns schema mappings', async () => {
const mockHttp = {
get: jest.fn().mockResolvedValue({ data: { mappings: { test: true } }, statusCode: 200 }),
} as Partial<HttpSetup>;

const result = fetchIntegrationMappings('target', mockHttp as HttpSetup);

await expect(result).resolves.toStrictEqual({ test: true });
});

it('Returns null if response fails', async () => {
const mockHttp = {
get: jest.fn().mockResolvedValue({ statusCode: 404 }),
} as Partial<HttpSetup>;

const result = fetchIntegrationMappings('target', mockHttp as HttpSetup);

await expect(result).resolves.toBeNull();
});

it('Catches request error', async () => {
const mockHttp = {
get: jest.fn().mockRejectedValue(new Error('mock error')),
} as Partial<HttpSetup>;

const result = fetchIntegrationMappings('target', mockHttp as HttpSetup);

await expect(result).resolves.toBeNull();
});
});

describe('doExistingDataSourceValidation', () => {
it('Catches and returns checkDataSourceName errors', async () => {
const mockHttp = {} as Partial<HttpSetup>;
jest
.spyOn(add_integration_flyout, 'checkDataSourceName')
.mockReturnValue({ ok: false, errors: ['mock'] });

const result = doExistingDataSourceValidation('target', 'name', 'type', mockHttp as HttpSetup);

await expect(result).resolves.toHaveProperty('ok', false);
});

it('Catches data stream fetch errors', async () => {
const mockHttp = {} as Partial<HttpSetup>;
jest.spyOn(add_integration_flyout, 'checkDataSourceName').mockReturnValue({ ok: true });
jest.spyOn(add_integration_flyout, 'fetchDataSourceMappings').mockResolvedValue(null);
jest
.spyOn(add_integration_flyout, 'fetchIntegrationMappings')
.mockResolvedValue({ test: { template: { mappings: {} } } });

const result = doExistingDataSourceValidation('target', 'name', 'type', mockHttp as HttpSetup);

await expect(result).resolves.toHaveProperty('ok', false);
});

it('Catches integration fetch errors', async () => {
const mockHttp = {} as Partial<HttpSetup>;
jest.spyOn(add_integration_flyout, 'checkDataSourceName').mockReturnValue({ ok: true });
jest
.spyOn(add_integration_flyout, 'fetchDataSourceMappings')
.mockResolvedValue({ test: { properties: {} } });
jest.spyOn(add_integration_flyout, 'fetchIntegrationMappings').mockResolvedValue(null);

const result = doExistingDataSourceValidation('target', 'name', 'type', mockHttp as HttpSetup);

await expect(result).resolves.toHaveProperty('ok', false);
});

it('Catches type validation issues', async () => {
const mockHttp = {} as Partial<HttpSetup>;
jest.spyOn(add_integration_flyout, 'checkDataSourceName').mockReturnValue({ ok: true });
jest
.spyOn(add_integration_flyout, 'fetchDataSourceMappings')
.mockResolvedValue({ test: { properties: {} } });
jest
.spyOn(add_integration_flyout, 'fetchIntegrationMappings')
.mockResolvedValue({ test: { template: { mappings: {} } } });
jest
.spyOn(add_integration_flyout, 'doPropertyValidation')
.mockReturnValue({ ok: false, errors: ['mock'] });

const result = doExistingDataSourceValidation('target', 'name', 'type', mockHttp as HttpSetup);

await expect(result).resolves.toHaveProperty('ok', false);
});

it('Returns no errors if everything passes', async () => {
const mockHttp = {} as Partial<HttpSetup>;
jest.spyOn(add_integration_flyout, 'checkDataSourceName').mockReturnValue({ ok: true });
jest
.spyOn(add_integration_flyout, 'fetchDataSourceMappings')
.mockResolvedValue({ test: { properties: {} } });
jest
.spyOn(add_integration_flyout, 'fetchIntegrationMappings')
.mockResolvedValue({ test: { template: { mappings: {} } } });
jest.spyOn(add_integration_flyout, 'doPropertyValidation').mockReturnValue({ ok: true });

const result = doExistingDataSourceValidation('target', 'name', 'type', mockHttp as HttpSetup);

await expect(result).resolves.toHaveProperty('ok', true);
});
});
Loading