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

Bug 1797702: remove search button and search status/result for deploy image #4187

Merged
merged 1 commit into from
Feb 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
19 changes: 10 additions & 9 deletions frontend/integration-tests/tests/deploy-image.scenario.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { browser, $, element, by, ExpectedConditions as until } from 'protractor';
import { browser, element, by, ExpectedConditions as until } from 'protractor';

import { appHost, checkLogs, checkErrors, testName } from '../protractor.conf';

Expand Down Expand Up @@ -35,15 +35,16 @@ describe('Deploy Image', () => {

it('can be used to search for an image', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We had an integration test for Deploy Image?

cc @christianvogt

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deploy-image flow existed before dev-console and then it was updated and moved.
old e2e tests were updated.
We should eventually move these to the dev-console integration tests folder and update them further.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of removing the test, can we update it to work with the new ui components.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@christianvogt This test is obsolete now because It was testing the content in SearchResult and SearchStatus component and both of these components are removed now. Even With the new component, there is a test that covers the whole deploy image flow.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fair enough that there's one testing the full deploy.
I just thought that instead of testing the results block, it could similarly test for the validation message.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added test for new search field

// Put the search term in the search field
await element(by.css('[data-test-id="deploy-image-search-term"]')).sendKeys(imageName);
// Click the search button
await element(by.css('[data-test-id="input-search-field-btn"]')).click();
// Wait for the results section to appear
await browser.wait(until.presenceOf($('.co-image-name-results__details')));
await element(by.css('[data-test-id=deploy-image-search-term]')).sendKeys(imageName);

//remove focus form image search field
await element(by.css('[data-test-id=application-form-app-name]')).click();

const helperText = 'form-input-searchTerm-field-helper';
// Wait for the validation
await browser.wait(until.presenceOf(element(by.id(helperText))));
// Confirm the results appeared
expect(
element(by.cssContainingText('.co-image-name-results__heading', imageName)).isPresent(),
).toBe(true);
expect(element(by.id(helperText)).isPresent()).toBe(true);
});

it('should auto fill in the application', async () => {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ export { default as DropdownField } from './DropdownField';
export { default as DroppableFileInputField } from './DroppableFileInputField';
export { default as EnvironmentField } from './EnvironmentField';
export { default as InputField } from './InputField';
export { default as InputSearchField } from './InputSearchField';
export { default as MultiColumnField } from './multi-column-field/MultiColumnField';
export { default as NSDropdownField } from './NSDropdownField';
export { default as NumberSpinnerField } from './NumberSpinnerField';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ describe('Application Launcher Menu', () => {
expect(pageSidebar.getText()).toContain('Topology');
expect(pageSidebar.getText()).toContain('+Add');
expect(pageSidebar.getText()).toContain('Builds');
expect(pageSidebar.getText()).toContain('Advanced');
expect(pageSidebar.getText()).toContain('More');
expect(pageSidebar.getText()).toContain('Project Details');
expect(pageSidebar.getText()).toContain('Project Access');
expect(pageSidebar.getText()).toContain('Search');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,97 +3,124 @@ import * as _ from 'lodash';
import { k8sCreate } from '@console/internal/module/k8s';
import { ImageStreamImportsModel } from '@console/internal/models';
import { useFormikContext, FormikValues } from 'formik';
import { TextInputTypes, Alert, AlertActionCloseButton, Button } from '@patternfly/react-core';
import {
TextInputTypes,
Alert,
AlertActionCloseButton,
Button,
ValidatedOptions,
} from '@patternfly/react-core';
import { SecretTypeAbstraction } from '@console/internal/components/secrets/create-secret';
import { InputSearchField } from '@console/shared';
import { InputField } from '@console/shared';
import { getSuggestedName, getPorts, makePortName } from '../../../utils/imagestream-utils';
import { secretModalLauncher } from '../CreateSecretModal';

const ImageSearch: React.FC = () => {
const { values, setFieldValue, dirty } = useFormikContext<FormikValues>();
const [newImageSecret, setNewImageSecret] = React.useState('');
const [alertVisible, shouldHideAlert] = React.useState(true);
const [validated, setValidated] = React.useState<ValidatedOptions>(ValidatedOptions.default);
const namespace = values.project.name;

const handleSearch = React.useCallback(
(searchTerm: string) => {
const importImage = {
kind: 'ImageStreamImport',
apiVersion: 'image.openshift.io/v1',
metadata: {
name: 'newapp',
namespace: values.project.name,
},
spec: {
import: false,
images: [
{
from: {
kind: 'DockerImage',
name: _.trim(searchTerm),
},
const handleSearch = React.useCallback(() => {
const searchTermImage = values.searchTerm;
setFieldValue('isSearchingForImage', true);
setValidated(ValidatedOptions.default);
const importImage = {
kind: 'ImageStreamImport',
apiVersion: 'image.openshift.io/v1',
metadata: {
name: 'newapp',
namespace: values.project.name,
},
spec: {
import: false,
images: [
{
from: {
kind: 'DockerImage',
name: _.trim(searchTermImage),
},
],
},
status: {},
};
},
],
},
status: {},
};

k8sCreate(ImageStreamImportsModel, importImage)
.then((imageStreamImport) => {
const status = _.get(imageStreamImport, 'status.images[0].status');
if (status.status === 'Success') {
const name = _.get(imageStreamImport, 'spec.images[0].from.name');
const image = _.get(imageStreamImport, 'status.images[0].image');
const tag = _.get(imageStreamImport, 'status.images[0].tag');
const isi = { name, image, tag, status };
const ports = getPorts(isi);
setFieldValue('isSearchingForImage', false);
setFieldValue('isi.name', name);
setFieldValue('isi.image', image);
setFieldValue('isi.tag', tag);
setFieldValue('isi.status', status);
setFieldValue('isi.ports', ports);
setFieldValue('image.ports', ports);
setFieldValue('image.tag', tag);
!values.name && setFieldValue('name', getSuggestedName(name));
!values.application.name &&
setFieldValue('application.name', `${getSuggestedName(name)}-app`);
// set default port value
const targetPort = _.head(ports);
targetPort && setFieldValue('route.targetPort', makePortName(targetPort));
} else {
setFieldValue('isSearchingForImage', false);
setFieldValue('isi', {});
setFieldValue('isi.status', status.message);
setFieldValue('route.targetPort', null);
}
})
.catch((error) => {
setFieldValue('isi', {});
setFieldValue('isi.status', error.message);
k8sCreate(ImageStreamImportsModel, importImage)
.then((imageStreamImport) => {
const status = _.get(imageStreamImport, 'status.images[0].status');
if (status.status === 'Success') {
const name = _.get(imageStreamImport, 'spec.images[0].from.name');
const image = _.get(imageStreamImport, 'status.images[0].image');
const tag = _.get(imageStreamImport, 'status.images[0].tag');
const isi = { name, image, tag, status };
const ports = getPorts(isi);
setFieldValue('isSearchingForImage', false);
});
},
[setFieldValue, values.application.name, values.name, values.project.name],
);
setFieldValue('isi.name', name);
setFieldValue('isi.image', image);
setFieldValue('isi.tag', tag);
setFieldValue('isi.status', status);
setFieldValue('isi.ports', ports);
setFieldValue('image.ports', ports);
setFieldValue('image.tag', tag);
!values.name && setFieldValue('name', getSuggestedName(name));
!values.application.name &&
setFieldValue('application.name', `${getSuggestedName(name)}-app`);
// set default port value
const targetPort = _.head(ports);
targetPort && setFieldValue('route.targetPort', makePortName(targetPort));
setValidated(ValidatedOptions.success);
} else {
setFieldValue('isSearchingForImage', false);
setFieldValue('isi', {});
setFieldValue('isi.status', status.message);
setFieldValue('route.targetPort', null);
setValidated(ValidatedOptions.error);
}
})
.catch((error) => {
setFieldValue('isi', {});
setFieldValue('isi.status', error.message);
setFieldValue('isSearchingForImage', false);
setValidated(ValidatedOptions.error);
});
}, [setFieldValue, values.application.name, values.name, values.project.name, values.searchTerm]);

const handleSave = (name: string) => {
setNewImageSecret(name);
values.searchTerm && handleSearch(values.searchTerm);
values.searchTerm && handleSearch();
};

const getHelpText = () => {
if (values.isSearchingForImage) {
return 'Validating...';
}
if (!values.isSearchingForImage && validated === ValidatedOptions.success) {
return 'Validated';
}
return '';
};

const helpTextInvalid = validated === ValidatedOptions.error && (
<span>{values.searchTerm === '' ? 'Required' : values.isi.status}</span>
);

React.useEffect(() => {
!dirty && values.searchTerm && handleSearch(values.searchTerm);
!dirty && values.searchTerm && handleSearch();
}, [dirty, handleSearch, values.searchTerm]);

return (
<>
<InputSearchField
<InputField
type={TextInputTypes.text}
data-test-id="deploy-image-search-term"
name="searchTerm"
label="Image Name"
onSearch={handleSearch}
placeholder="Enter an image name"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sahil143 seems the removal of data-test-id="deploy-image-search-term" willl impact integration tests

Screenshot 2020-02-13 at 5 09 02 PM

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@invincibleJai added data-test-id

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch @invincibleJai - we need to be careful not to remove data-test-ids.

helpText={getHelpText()}
helpTextInvalid={helpTextInvalid}
validated={validated}
onBlur={handleSearch}
data-test-id="deploy-image-search-term"
required
/>
<div className="help-block" id="image-name-help">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ import FormSection from '../section/FormSection';
import { imageRegistryType } from '../../../utils/imagestream-utils';
import ImageStream from './ImageStream';
import ImageSearch from './ImageSearch';
import SearchStatus from './SearchStatus';
import SearchResults from './SearchResults';

const ImageSearchSection: React.FC = () => {
const { values, setFieldValue, initialValues } = useFormikContext<FormikValues>();
Expand Down Expand Up @@ -49,8 +47,6 @@ const ImageSearchSection: React.FC = () => {
},
]}
/>
<SearchStatus />
<SearchResults />
</FormSection>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react';
import * as _ from 'lodash';
import { Alert } from '@patternfly/react-core';
import { Alert, FormGroup, ValidatedOptions } from '@patternfly/react-core';
import { ExclamationCircleIcon } from '@patternfly/react-icons';
import { useFormikContext, FormikValues } from 'formik';
import { CheckboxField } from '@console/shared';
import { K8sResourceKind } from '@console/internal/module/k8s';
Expand Down Expand Up @@ -45,9 +46,10 @@ export const ImageStreamReducer = (state: ImageStreamState, action: ImageStreamA

const ImageStream: React.FC = () => {
const {
values: { imageStream, project, registry },
values: { imageStream, project, registry, isi },
setFieldValue,
} = useFormikContext<FormikValues>();
const [validated, setValidated] = React.useState<ValidatedOptions>(ValidatedOptions.default);
const [state, dispatch] = React.useReducer(ImageStreamReducer, initialState);
const [hasImageStreams, setHasImageStreams] = React.useState(false);
const {
Expand Down Expand Up @@ -75,23 +77,37 @@ const ImageStream: React.FC = () => {
registry === RegistryType.Internal &&
imageStream.namespace !== BuilderImagesNamespace.Openshift &&
project.name !== imageStream.namespace;
const helperTextInvalid = validated === ValidatedOptions.error && (
<>
<ExclamationCircleIcon />
&nbsp;{isi.status}
</>
);

return (
<>
<ImageStreamContext.Provider value={{ state, dispatch, hasImageStreams, setHasImageStreams }}>
<div className="row">
<div className="col-lg-4 col-md-4 col-sm-4 col-xs-12">
<ImageStreamNsDropdown />
</div>
<div className="col-lg-4 col-md-4 col-sm-4 col-xs-12">
<ImageStreamDropdown />
<div className="odc-imagestream-separator">/</div>
</div>
<div className="col-lg-4 col-md-4 col-sm-4 col-xs-12">
<ImageStreamTagDropdown />
<div className="odc-imagestream-separator">:</div>
<ImageStreamContext.Provider
value={{ state, dispatch, hasImageStreams, setHasImageStreams, setValidated }}
>
<FormGroup
fieldId="image-stream-dropdowns"
validated={validated}
helperTextInvalid={helperTextInvalid}
>
<div className="row">
<div className="col-lg-4 col-md-4 col-sm-4 col-xs-12">
<ImageStreamNsDropdown />
</div>
<div className="col-lg-4 col-md-4 col-sm-4 col-xs-12">
<ImageStreamDropdown />
<div className="odc-imagestream-separator">/</div>
</div>
<div className="col-lg-4 col-md-4 col-sm-4 col-xs-12">
<ImageStreamTagDropdown />
<div className="odc-imagestream-separator">:</div>
</div>
</div>
</div>
</FormGroup>
{isNamespaceSelected && isImageStreamSelected && !isTagsAvailable && hasCreateAccess && (
<div className="odc-imagestream-alert">
<Alert variant="warning" title="No Image streams tags found" isInline>
Expand Down