Wizard: Use useChrome hook to set beta feature flag

The use of chrome.isBeta is deprecated, the useChrome hook should be
used instead to obtain an isBeta() function. Using the deprecrated
chrome.isBeta pollutes the browser console with warning messages.

This commit replaces the isBeta() helper function with a new custom
hook, useGetEnvironment().

We still sometimes need to know which environment is running outside of
React components, where we cannot call the useChrome() or
useGetEnvironment() hooks. For instance, in the json used to define a
wizard step. Therefore a new isBeta variable has been added to the
form's initialState for use in these cases.
This commit is contained in:
lucasgarfield 2023-04-12 16:31:10 +02:00 committed by Lucas Garfield
parent c9081259a6
commit b2e6e3cf04
15 changed files with 95 additions and 85 deletions

View file

@ -32,9 +32,9 @@ import { UNIT_GIB, UNIT_KIB, UNIT_MIB, MODAL_ANCHOR } from '../../constants';
import { useGetArchitecturesByDistributionQuery } from '../../store/apiSlice';
import { composeAdded } from '../../store/composesSlice';
import { fetchRepositories } from '../../store/repositoriesSlice';
import isBeta from '../../Utilities/isBeta';
import isRhel from '../../Utilities/isRhel';
import { resolveRelPath } from '../../Utilities/path';
import { useGetEnvironment } from '../../Utilities/useGetEnvironment';
import DocumentationButton from '../sharedComponents/DocumentationButton';
const handleKeyDown = (e, handleClose) => {
@ -266,11 +266,17 @@ const getDistributionRepoUrls = (distributionInformation) => {
return mapped;
};
const getPackageDescription = async (release, arch, repoUrls, packageName) => {
const getPackageDescription = async (
release,
arch,
repoUrls,
packageName,
isBeta
) => {
let pack;
// if the env is stage beta then use content-sources api
// else use image-builder api
if (isBeta()) {
if (isBeta) {
const data = await api.getPackagesContentSources(repoUrls, packageName);
pack = data.find((pack) => packageName === pack.name);
} else {
@ -296,7 +302,7 @@ const getPackageDescription = async (release, arch, repoUrls, packageName) => {
};
// map the compose request object to the expected form state
const requestToState = (composeRequest, distroInfo) => {
const requestToState = (composeRequest, distroInfo, isBeta) => {
if (composeRequest) {
const imageRequest = composeRequest.image_requests[0];
const uploadRequest = imageRequest.upload_request;
@ -396,7 +402,8 @@ const requestToState = (composeRequest, distroInfo) => {
distro,
imageRequest?.architecture,
repoUrls,
packName
packName,
isBeta
);
const pack = {
name: packName,
@ -472,7 +479,7 @@ const requestToState = (composeRequest, distroInfo) => {
}
};
const formStepHistory = (composeRequest) => {
const formStepHistory = (composeRequest, isBeta) => {
if (composeRequest) {
const imageRequest = composeRequest.image_requests[0];
const uploadRequest = imageRequest.upload_request;
@ -491,7 +498,7 @@ const formStepHistory = (composeRequest) => {
steps.push('registration');
}
if (isBeta()) {
if (isBeta) {
steps.push('File system configuration', 'packages', 'repositories');
const customRepositories =
@ -537,10 +544,16 @@ const CreateImageWizard = () => {
// This will occur if 'Recreate image' is clicked
const initialStep = compose?.request ? 'review' : undefined;
const { isBeta } = useGetEnvironment();
const awsTarget = isBeta() ? awsTargetBeta : awsTargetStable;
const msAzureTarget = isBeta() ? msAzureTargetBeta : msAzureTargetStable;
const initialState = requestToState(composeRequest, distroInfo);
const stepHistory = formStepHistory(composeRequest);
let initialState = requestToState(composeRequest, distroInfo, isBeta());
const stepHistory = formStepHistory(composeRequest, isBeta());
initialState
? (initialState.isBeta = isBeta())
: (initialState = { isBeta: isBeta() });
const handleClose = () => navigate(resolveRelPath(''));

View file

@ -31,7 +31,6 @@ import PropTypes from 'prop-types';
import api from '../../../api';
import { useGetArchitecturesByDistributionQuery } from '../../../store/apiSlice';
import isBeta from '../../../Utilities/isBeta';
const ExactMatch = ({
pkgList,
@ -67,7 +66,7 @@ export const RedHatPackages = ({ defaultArch }) => {
const getAllPackages = async (packagesSearchName) => {
// if the env is stage beta then use content-sources api
// else use image-builder api
if (isBeta()) {
if (getState()?.values?.isBeta) {
const filteredArchx86_64 = distributionInformation.find(
(info) => info.arch === 'x86_64'
);

View file

@ -35,7 +35,6 @@ import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';
import { selectValidRepositories } from '../../../store/repositoriesSlice';
import isBeta from '../../../Utilities/isBeta';
const BulkSelect = ({
selected,
@ -276,7 +275,11 @@ const Repositories = (props) => {
<Button
variant="primary"
component="a"
href={isBeta() ? '/beta/settings/content' : '/settings/content'}
href={
getState()?.values?.isBeta
? '/beta/settings/content'
: '/settings/content'
}
>
Repositories
</Button>

View file

@ -5,7 +5,6 @@ import { Text } from '@patternfly/react-core';
import StepTemplate from './stepTemplate';
import isBeta from '../../../Utilities/isBeta';
import CustomButtons from '../formComponents/CustomButtons';
export default {
@ -14,8 +13,8 @@ export default {
title: 'Additional Red Hat packages',
name: 'packages',
substepOf: 'Content',
nextStep: () => {
if (isBeta()) {
nextStep: ({ values }) => {
if (values.isBeta) {
return 'repositories';
} else {
return 'image-name';

View file

@ -1,7 +1,7 @@
import React, { Suspense, useState, useMemo } from 'react';
import { Button, Modal, ModalVariant } from '@patternfly/react-core';
import useChrome from '@redhat-cloud-services/frontend-components/useChrome';
import { useChrome } from '@redhat-cloud-services/frontend-components/useChrome';
import { useLoadModule, useScalprum } from '@scalprum/react-core';
import { useFlag } from '@unleash/proxy-client-react';
import PropTypes from 'prop-types';
@ -11,6 +11,7 @@ import ImageLinkDirect from './ImageLinkDirect';
import { MODAL_ANCHOR } from '../../constants';
import { selectImageById } from '../../store/composesSlice';
import { useGetEnvironment } from '../../Utilities/useGetEnvironment';
const getImageProvider = ({ imageType }) => {
switch (imageType) {
@ -91,18 +92,13 @@ const ProvisioningLink = ({ imageId, isExpired, isInClonesTable }) => {
const ImageLink = ({ imageId, isExpired, isInClonesTable }) => {
const image = useSelector((state) => selectImageById(state, imageId));
const uploadStatus = image.uploadStatus;
const {
initialized: chromeInitialized,
isBeta,
getEnvironment,
} = useChrome();
const { initialized: chromeInitialized } = useChrome();
const { isBeta } = useGetEnvironment();
const azureFeatureFlag = useFlag('provisioning.azure');
const scalprum = useScalprum();
const hasProvisioning =
chromeInitialized &&
scalprum.config?.provisioning &&
(isBeta() || getEnvironment() === 'qa');
chromeInitialized && scalprum.config?.provisioning && isBeta();
if (!uploadStatus || image.status !== 'success') return null;

View file

@ -6,7 +6,7 @@ import PropTypes from 'prop-types';
import { useSelector } from 'react-redux';
import { selectComposeById, selectImagesById } from '../../store/composesSlice';
import isBeta from '../../Utilities/isBeta';
import { useGetEnvironment } from '../../Utilities/useGetEnvironment';
import BetaLabel from '../sharedComponents/BetaLabel';
export const selectRegions = createSelector(
@ -57,6 +57,7 @@ const ImageLinkRegion = ({ region, ami }) => {
};
export const RegionsPopover = ({ composeId }) => {
const { isBeta } = useGetEnvironment();
const regions = useSelector((state) => selectRegions(state, composeId));
const listItems = useMemo(() => {

View file

@ -28,7 +28,7 @@ import azureQuickStart from './azurequickstart.json';
import contentQuickStart from './contentquickstart.json';
import './LandingPage.scss';
import isBeta from '../../Utilities/isBeta';
import { useGetEnvironment } from '../../Utilities/useGetEnvironment';
import ImagesTable from '../ImagesTable/ImagesTable';
import DocumentationButton from '../sharedComponents/DocumentationButton';
@ -37,6 +37,7 @@ export const LandingPage = () => {
const [showHint, setShowHint] = useState(true);
const { quickStarts } = useChrome();
const { isBeta } = useGetEnvironment();
const activateQuickstart = (qs) => quickStarts.toggle(qs.metadata.name);
useEffect(() => {

View file

@ -1,7 +0,0 @@
function isBeta() {
return insights.chrome.isBeta() || insights.chrome.getEnvironment() === 'qa'
? true
: false;
}
export default isBeta;

View file

@ -0,0 +1,10 @@
import { useChrome } from '@redhat-cloud-services/frontend-components/useChrome';
export const useGetEnvironment = () => {
const { isBeta, getEnvironment } = useChrome();
// Expose beta features in the ephemeral environment
if (isBeta() || getEnvironment() === 'qa') {
return { isBeta: () => true };
}
return { isBeta: () => false };
};

View file

@ -10,6 +10,14 @@ import { mockRepositoryResults } from '../../fixtures/repositories';
import { server } from '../../mocks/server.js';
import { renderWithReduxRouter } from '../../testUtils';
jest.mock('@redhat-cloud-services/frontend-components/useChrome', () => ({
useChrome: () => ({
isBeta: () => true,
isProd: () => true,
getEnvironment: () => 'prod',
}),
}));
describe('Step Upload to Azure', () => {
const getNextButton = () => {
const next = screen.getByRole('button', { name: /Next/ });
@ -47,15 +55,6 @@ describe('Step Upload to Azure', () => {
};
},
},
isBeta: () => {
return true;
},
isProd: () => {
return true;
},
getEnvironment: () => {
return 'prod';
},
},
};
});

View file

@ -30,6 +30,14 @@ const mockComposes = {
data: [],
};
jest.mock('@redhat-cloud-services/frontend-components/useChrome', () => ({
useChrome: () => ({
isBeta: () => true,
isProd: () => true,
getEnvironment: () => 'prod',
}),
}));
// Mocking getComposes is necessary because in many tests we call navigate()
// to navigate to the images table (via useNavigate hook), which will in turn
// result in a call to getComposes. If it is not mocked, tests fail due to MSW
@ -169,15 +177,9 @@ beforeAll(() => {
};
},
},
isBeta: () => {
return true;
},
isProd: () => {
return true;
},
getEnvironment: () => {
return 'prod';
},
},
};
});

View file

@ -31,6 +31,14 @@ jest
.spyOn(api, 'getComposes')
.mockImplementation(() => Promise.resolve(mockComposes));
jest.mock('@redhat-cloud-services/frontend-components/useChrome', () => ({
useChrome: () => ({
isBeta: () => false,
isProd: () => true,
getEnvironment: () => 'prod',
}),
}));
function getBackButton() {
const back = screen.getByRole('button', { name: /Back/ });
return back;

View file

@ -425,21 +425,13 @@ const mockCloneStatus = {
},
};
beforeAll(() => {
global.insights = {
chrome: {
isBeta: () => {
return false;
},
isProd: () => {
return true;
},
getEnvironment: () => {
return 'prod';
},
},
};
});
jest.mock('@redhat-cloud-services/frontend-components/useChrome', () => ({
useChrome: () => ({
isBeta: () => false,
isProd: () => true,
getEnvironment: () => 'prod',
}),
}));
jest
.spyOn(api, 'getComposes')

View file

@ -10,18 +10,20 @@ jest.mock('../../../store/actions/actions', () => {
};
});
jest.mock('@redhat-cloud-services/frontend-components/useChrome', () => ({
useChrome: () => ({
isBeta: () => false,
isProd: () => true,
getEnvironment: () => 'prod',
}),
}));
beforeAll(() => {
global.insights = {
chrome: {
isBeta: () => {
return false;
},
isProd: () => {
return true;
},
getEnvironment: () => {
return 'prod';
},
},
};
});

View file

@ -6,21 +6,13 @@ import api from '../../../api.js';
import { RHEL_8 } from '../../../constants.js';
import { renderWithReduxRouter } from '../../testUtils';
beforeAll(() => {
global.insights = {
chrome: {
isBeta: () => {
return false;
},
isProd: () => {
return true;
},
getEnvironment: () => {
return 'prod';
},
},
};
});
jest.mock('@redhat-cloud-services/frontend-components/useChrome', () => ({
useChrome: () => ({
isBeta: () => false,
isProd: () => true,
getEnvironment: () => 'prod',
}),
}));
const mockComposes = {
count: 1,