Project

General

Profile

« Previous | Next » 

Revision 1b215f65

Added by Maria Agaphontzev about 2 months ago

Fixes #37280 - remove typeAheadSelect

View differences:

webpack/assets/javascripts/bundle.js
import * as configReportsModalDiff from './foreman_config_reports_modal_diff';
import * as dashboard from './dashboard';
import * as spice from './spice';
import * as typeAheadSelect from './foreman_type_ahead_select';
import * as lookupKeys from './foreman_lookup_keys';
import './react_app/common/MountingService';
import './foreman_overrides';
......
document,
componentRegistry,
store,
typeAheadSelect,
lookupKeys,
});
webpack/assets/javascripts/foreman_tools.js
});
}
export function initTypeAheadSelect(input) {
input.select2({
formatNoMatches: __('No matches found'),
ajax: {
url: input.data('url'),
dataType: 'json',
quietMillis: 250,
data: (term, page) => ({
q: term,
scope: input.data('scope'),
}),
results: data => ({
results: data.map(({ id, name }) => ({ id, text: name })),
}),
cache: true,
},
initSelection(element, callback) {
$.ajax(input.data('url'), {
data: {
scope: input.data('scope'),
},
dataType: 'json',
}).done(data => {
if (data.length > 0) {
// eslint-disable-next-line standard/no-callback-literal
callback({ id: data[0].id, text: data[0].name });
}
});
},
width: '400px',
});
}
// generates an absolute, needed in case of running Foreman from a subpath
export { foremanUrl } from './react_app/common/helpers';
webpack/assets/javascripts/foreman_tools.test.js
);
});
});
/* eslint-disable max-statements */
describe('initTypeAheadSelect', () => {
it('initializes select2 on given input field', () => {
document.body.innerHTML =
'<input type="text" id="typeahead" data-url="testurl" data-scope="testscope">';
const field = $('#typeahead');
$.ajax = jest.fn(url => {
const ajaxMock = $.Deferred();
ajaxMock.resolve([
{ id: 1, name: 'testoption' },
{ id: 2, name: 'anotheroption' },
]);
return ajaxMock.promise();
});
tools.initTypeAheadSelect(field);
$('.select2-choice').trigger('mousedown');
$('.select2-choice').trigger('mouseup');
expect(document.body.innerHTML).toContain('select2-container');
expect($('.select2-chosen').text()).toEqual('testoption');
});
});
webpack/assets/javascripts/foreman_type_ahead_select.js
import {
updateOptions as updateTypeAheadSelectOptions,
updateSelected as updateTypeAheadSelectSelected,
} from './react_app/components/common/TypeAheadSelect/TypeAheadSelectActions';
import store from './react_app/redux';
export const updateOptions = (options, id) => {
store.dispatch(updateTypeAheadSelectOptions(options, id));
};
export const updateSelected = (selected, id) => {
store.dispatch(updateTypeAheadSelectSelected(selected, id));
};
webpack/assets/javascripts/react_app/common/testHelpers.js
factChart: {
modalToDisplay: {},
},
typeAheadSelect: {},
settingRecords: {
settings: {},
editing: null,
webpack/assets/javascripts/react_app/components/common/TypeAheadSelect/TypeAheadSelect.fixtures.js
import Immutable from 'seamless-immutable';
export const id = 'test_type_ahead_select';
export const options = ['option1', 'option2'];
export const selected = ['option2'];
export const initialState = Immutable({ typeAheadSelect: {} });
export const populatedState = Immutable({
typeAheadSelect: {
test_type_ahead_select: {
options,
selected,
},
},
});
export const props = {
id,
options,
selected,
};
webpack/assets/javascripts/react_app/components/common/TypeAheadSelect/TypeAheadSelectActions.js
import {
INIT,
UPDATE_OPTIONS,
UPDATE_SELECTED,
} from './TypeAheadSelectConstants';
import { mapSelected } from './TypeAheadSelectSelectors';
export const initialUpdate = (options, selected, id) => ({
type: INIT,
payload: {
id,
options,
selected,
},
});
export const updateOptions = (options, id) => ({
type: UPDATE_OPTIONS,
payload: {
id,
options,
},
});
export const updateSelected = (selected, id) => ({
type: UPDATE_SELECTED,
payload: {
id,
selected: mapSelected(selected),
},
});
webpack/assets/javascripts/react_app/components/common/TypeAheadSelect/TypeAheadSelectConstants.js
export const INIT = 'TYPEAHEAD_INIT';
export const UPDATE_OPTIONS = 'TYPEAHEAD_UPDATE_OPTIONS';
export const UPDATE_SELECTED = 'TYPEAHEAD_UPDATE_SELECTED';
webpack/assets/javascripts/react_app/components/common/TypeAheadSelect/TypeAheadSelectReducer.js
import Immutable from 'seamless-immutable';
import {
INIT,
UPDATE_OPTIONS,
UPDATE_SELECTED,
} from './TypeAheadSelectConstants';
const initialState = Immutable({});
export default (
state = initialState,
{ type, payload: { id, options, selected } = {} }
) => {
switch (type) {
case INIT:
return state.setIn([id], {
...state[id],
options,
selected,
});
case UPDATE_OPTIONS:
return state.setIn([id], {
...state[id],
options,
});
case UPDATE_SELECTED:
return state.setIn([id], {
...state[id],
selected,
});
default:
return state;
}
};
webpack/assets/javascripts/react_app/components/common/TypeAheadSelect/TypeAheadSelectSelectors.js
import Immutable from 'seamless-immutable';
export const mapSelected = selected => selected.map(item => item.label || item);
const selectTypeAheadSelect = ({ typeAheadSelect }, id) =>
typeAheadSelect[id] || {};
export const selectTypeAheadSelectExists = ({ typeAheadSelect }, id) =>
!!typeAheadSelect[id];
export const selectOptions = (state, id) => {
const typeAhead = selectTypeAheadSelect(state, id);
const options = typeAhead.options || [];
return Immutable.isImmutable(options) ? options.asMutable() : options;
};
export const selectSelected = (state, id) =>
selectTypeAheadSelect(state, id).selected;
webpack/assets/javascripts/react_app/components/common/TypeAheadSelect/__snapshots__/integration.test.js.snap
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`TypeAheadSelect integration test flows: after initialUpdate 1`] = `
Object {
"typeAheadSelect": Object {
"test_type_ahead_select": Object {
"options": Array [
"option1",
"option2",
],
"selected": Array [
"option2",
],
},
},
}
`;
exports[`TypeAheadSelect integration test flows: initial state 1`] = `
Object {
"typeAheadSelect": Object {},
}
`;
exports[`TypeAheadSelect integration test flows: updated options and selections 1`] = `
Object {
"typeAheadSelect": Object {
"test_type_ahead_select": Object {
"options": Array [
"Walrus",
"Bear",
],
"selected": Array [
"Bear",
],
},
},
}
`;
webpack/assets/javascripts/react_app/components/common/TypeAheadSelect/__tests__/TypeAheadSelectActions.test.js
import { testActionSnapshotWithFixtures } from '../../../../common/testHelpers';
import {
initialUpdate,
updateOptions,
updateSelected,
} from '../TypeAheadSelectActions';
import { id, options, selected } from '../TypeAheadSelect.fixtures';
const fixtures = {
'initializes defaults': () => initialUpdate(options, selected, id),
'updates options': () => updateOptions(options, id),
'updates selections': () => updateSelected(selected, id),
};
describe('TypeAheadSelectActions', () =>
testActionSnapshotWithFixtures(fixtures));
webpack/assets/javascripts/react_app/components/common/TypeAheadSelect/__tests__/TypeAheadSelectReducer.test.js
import { testReducerSnapshotWithFixtures } from '../../../../common/testHelpers';
import reducer from '../TypeAheadSelectReducer';
import {
INIT,
UPDATE_OPTIONS,
UPDATE_SELECTED,
} from '../TypeAheadSelectConstants';
import { id, options, selected } from '../TypeAheadSelect.fixtures';
const fixtures = {
'initial state': {},
'initiates defaults': {
action: {
type: INIT,
payload: {
id,
options,
selected,
},
},
},
'updates options': {
action: {
type: UPDATE_OPTIONS,
payload: {
id,
options,
},
},
},
'updates selections': {
action: {
type: UPDATE_SELECTED,
payload: {
id,
selected,
},
},
},
};
describe('TypeAheadSelectReducer', () =>
testReducerSnapshotWithFixtures(reducer, fixtures));
webpack/assets/javascripts/react_app/components/common/TypeAheadSelect/__tests__/TypeAheadSelectSelectors.test.js
import {
selectSelected,
selectOptions,
selectTypeAheadSelectExists,
} from '../TypeAheadSelectSelectors';
import { id, initialState, populatedState } from '../TypeAheadSelect.fixtures';
import { testSelectorsSnapshotWithFixtures } from '../../../../common/testHelpers';
describe('TypeAheadSelectSelectors', () => {
describe('with empty state', () => {
const fixtures = {
'returns an nothing': () => selectSelected(initialState, id),
'returns an empty array of options': () =>
selectOptions(initialState, id),
'returns false': () => selectTypeAheadSelectExists(initialState, id),
};
testSelectorsSnapshotWithFixtures(fixtures);
});
describe('with state', () => {
const fixtures = {
'returns selections array from state': () =>
selectSelected(populatedState, id),
'returns options array from state': () =>
selectOptions(populatedState, id),
'returns true': () => selectTypeAheadSelectExists(populatedState, id),
};
testSelectorsSnapshotWithFixtures(fixtures);
});
});
webpack/assets/javascripts/react_app/components/common/TypeAheadSelect/__tests__/__snapshots__/TypeAheadSelectActions.test.js.snap
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`TypeAheadSelectActions initializes defaults 1`] = `
Object {
"payload": Object {
"id": "test_type_ahead_select",
"options": Array [
"option1",
"option2",
],
"selected": Array [
"option2",
],
},
"type": "TYPEAHEAD_INIT",
}
`;
exports[`TypeAheadSelectActions updates options 1`] = `
Object {
"payload": Object {
"id": "test_type_ahead_select",
"options": Array [
"option1",
"option2",
],
},
"type": "TYPEAHEAD_UPDATE_OPTIONS",
}
`;
exports[`TypeAheadSelectActions updates selections 1`] = `
Object {
"payload": Object {
"id": "test_type_ahead_select",
"selected": Array [
"option2",
],
},
"type": "TYPEAHEAD_UPDATE_SELECTED",
}
`;
webpack/assets/javascripts/react_app/components/common/TypeAheadSelect/__tests__/__snapshots__/TypeAheadSelectReducer.test.js.snap
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`TypeAheadSelectReducer initial state 1`] = `Object {}`;
exports[`TypeAheadSelectReducer initiates defaults 1`] = `
Object {
"test_type_ahead_select": Object {
"options": Array [
"option1",
"option2",
],
"selected": Array [
"option2",
],
},
}
`;
exports[`TypeAheadSelectReducer updates options 1`] = `
Object {
"test_type_ahead_select": Object {
"options": Array [
"option1",
"option2",
],
},
}
`;
exports[`TypeAheadSelectReducer updates selections 1`] = `
Object {
"test_type_ahead_select": Object {
"selected": Array [
"option2",
],
},
}
`;
webpack/assets/javascripts/react_app/components/common/TypeAheadSelect/__tests__/__snapshots__/TypeAheadSelectSelectors.test.js.snap
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`TypeAheadSelectSelectors with empty state returns an empty array of options 1`] = `Array []`;
exports[`TypeAheadSelectSelectors with empty state returns an nothing 1`] = `undefined`;
exports[`TypeAheadSelectSelectors with empty state returns false 1`] = `false`;
exports[`TypeAheadSelectSelectors with state returns options array from state 1`] = `
Array [
"option1",
"option2",
]
`;
exports[`TypeAheadSelectSelectors with state returns selections array from state 1`] = `
Array [
"option2",
]
`;
exports[`TypeAheadSelectSelectors with state returns true 1`] = `true`;
webpack/assets/javascripts/react_app/components/common/TypeAheadSelect/index.js
import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import PropTypes from 'prop-types';
import { TypeAheadSelect } from 'patternfly-react';
import { initialUpdate, updateSelected } from './TypeAheadSelectActions';
import {
selectTypeAheadSelectExists,
selectOptions,
selectSelected,
} from './TypeAheadSelectSelectors';
import reducer from './TypeAheadSelectReducer';
const ConnectedTypeAheadSelect = ({
id,
options,
selected,
allowNew,
multiple,
placeholder,
defaultInputValue,
clearButton,
inputProps,
}) => {
const dispatch = useDispatch();
const exists = useSelector(state => selectTypeAheadSelectExists(state, id));
useEffect(() => {
if (!exists) {
dispatch(initialUpdate(options, selected, id));
}
}, [dispatch, exists, options, selected, id]);
const _selected = useSelector(state => selectSelected(state, id));
const _options = useSelector(state => selectOptions(state, id));
const onChange = items => dispatch(updateSelected(items, id));
return (
<TypeAheadSelect
id={id}
options={_options}
selected={_selected}
allowNew={allowNew}
multiple={multiple}
placeholder={placeholder}
defaultInputValue={defaultInputValue}
clearButton={clearButton}
inputProps={inputProps}
onChange={onChange}
/>
);
};
ConnectedTypeAheadSelect.propTypes = {
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
options: PropTypes.array,
selected: PropTypes.array,
allowNew: PropTypes.bool,
multiple: PropTypes.bool,
placeholder: PropTypes.string,
defaultInputValue: PropTypes.string,
clearButton: PropTypes.bool,
inputProps: PropTypes.object,
};
ConnectedTypeAheadSelect.defaultProps = {
options: [],
selected: [],
allowNew: false,
multiple: false,
placeholder: '',
defaultInputValue: '',
clearButton: false,
inputProps: {},
};
export default ConnectedTypeAheadSelect;
export const reducers = { typeAheadSelect: reducer };
webpack/assets/javascripts/react_app/components/common/TypeAheadSelect/integration.test.js
import React from 'react';
import IntegrationTestHelper from '../../../common/IntegrationTestHelper';
import TypeAheadSelect, { reducers } from './';
import { id, props, options, selected } from './TypeAheadSelect.fixtures';
import { updateOptions, updateSelected } from './TypeAheadSelectActions';
describe('TypeAheadSelect integration test', () => {
it('flows', async () => {
const integrationTestHelper = new IntegrationTestHelper(reducers);
integrationTestHelper.takeStoreSnapshot('initial state');
const component = integrationTestHelper.mount(
<TypeAheadSelect {...props} />
);
const getProps = wrapper =>
wrapper
.find('Typeahead')
.first()
.props();
component.update();
expect(getProps(component).selected).toEqual(selected);
expect(getProps(component).options).toEqual(options);
integrationTestHelper.takeStoreSnapshot('after initialUpdate');
const newOptions = ['Walrus', 'Bear'];
const newSelections = ['Bear'];
integrationTestHelper.store.dispatch(updateOptions(newOptions, id));
integrationTestHelper.store.dispatch(updateSelected(newSelections, id));
component.update();
expect(getProps(component).selected).toEqual(newSelections);
expect(getProps(component).options).toEqual(newOptions);
integrationTestHelper.takeStoreSnapshot('updated options and selections');
});
});
webpack/assets/javascripts/react_app/components/componentRegistry.js
import LoginPage from './LoginPage';
import ExternalLogout from './ExternalLogout';
import Slot from './common/Slot';
import TypeAheadSelect from './common/TypeAheadSelect';
import DatePicker from './common/DateTimePicker/DatePicker';
import RedirectCancelButton from './common/RedirectCancelButton';
import SettingRecords from './SettingRecords';
......
{ name: 'DiffModal', type: DiffModal },
{ name: 'ExternalLogout', type: ExternalLogout },
{ name: 'Slot', type: Slot },
{ name: 'TypeAheadSelect', type: TypeAheadSelect },
{ name: 'DatePicker', type: DatePicker },
{ name: 'RedirectCancelButton', type: RedirectCancelButton },
{ name: 'SettingRecords', type: SettingRecords },
webpack/assets/javascripts/react_app/redux/reducers/index.js
import { reducers as editorReducers } from '../../components/Editor';
import { reducers as templateGenerationReducers } from '../../components/TemplateGenerator';
import { reducers as fillReducers } from '../../components/common/Fill';
import { reducers as typeAheadSelectReducers } from '../../components/common/TypeAheadSelect';
import { reducers as auditsPageReducers } from '../../routes/Audits/AuditsPage';
import { reducers as intervalReducers } from '../middlewares/IntervalMiddleware';
import { reducers as bookmarksPF4Reducers } from '../../components/PF4/Bookmarks';
......
...diffModalReducers,
...editorReducers,
...templateGenerationReducers,
...typeAheadSelectReducers,
...settingRecordsReducers,
...personalAccessTokensReducers,
...confirmModalReducers,

Also available in: Unified diff