From b2e6e3cf04497f2d44cb12c46b77f45d5bb0de3f Mon Sep 17 00:00:00 2001 From: lucasgarfield Date: Wed, 12 Apr 2023 16:31:10 +0200 Subject: [PATCH] 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. --- .../CreateImageWizard/CreateImageWizard.js | 31 +++++++++++++------ .../formComponents/Packages.js | 3 +- .../formComponents/Repositories.js | 7 +++-- .../CreateImageWizard/steps/packages.js | 5 ++- src/Components/ImagesTable/ImageLink.js | 14 +++------ src/Components/ImagesTable/RegionsPopover.js | 3 +- src/Components/LandingPage/LandingPage.js | 3 +- src/Utilities/isBeta.js | 7 ----- src/Utilities/useGetEnvironment.js | 10 ++++++ .../CreateImageWizard.azure.beta.test.js | 17 +++++----- .../CreateImageWizard.beta.test.js | 14 +++++---- .../CreateImageWizard.test.js | 8 +++++ .../ImagesTable/ImagesTable.test.js | 22 +++++-------- .../LandingPage/LandingPage.test.js | 14 +++++---- .../ShareImageModal/ShareImageModal.test.js | 22 +++++-------- 15 files changed, 95 insertions(+), 85 deletions(-) delete mode 100644 src/Utilities/isBeta.js create mode 100644 src/Utilities/useGetEnvironment.js diff --git a/src/Components/CreateImageWizard/CreateImageWizard.js b/src/Components/CreateImageWizard/CreateImageWizard.js index 640a3977..939f1c28 100644 --- a/src/Components/CreateImageWizard/CreateImageWizard.js +++ b/src/Components/CreateImageWizard/CreateImageWizard.js @@ -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('')); diff --git a/src/Components/CreateImageWizard/formComponents/Packages.js b/src/Components/CreateImageWizard/formComponents/Packages.js index 725c307d..7622b405 100644 --- a/src/Components/CreateImageWizard/formComponents/Packages.js +++ b/src/Components/CreateImageWizard/formComponents/Packages.js @@ -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' ); diff --git a/src/Components/CreateImageWizard/formComponents/Repositories.js b/src/Components/CreateImageWizard/formComponents/Repositories.js index e35e5b09..d581431b 100644 --- a/src/Components/CreateImageWizard/formComponents/Repositories.js +++ b/src/Components/CreateImageWizard/formComponents/Repositories.js @@ -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) => { diff --git a/src/Components/CreateImageWizard/steps/packages.js b/src/Components/CreateImageWizard/steps/packages.js index 047d82ec..b296900f 100644 --- a/src/Components/CreateImageWizard/steps/packages.js +++ b/src/Components/CreateImageWizard/steps/packages.js @@ -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'; diff --git a/src/Components/ImagesTable/ImageLink.js b/src/Components/ImagesTable/ImageLink.js index a618a5be..ebb5fd88 100644 --- a/src/Components/ImagesTable/ImageLink.js +++ b/src/Components/ImagesTable/ImageLink.js @@ -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; diff --git a/src/Components/ImagesTable/RegionsPopover.js b/src/Components/ImagesTable/RegionsPopover.js index 9fdef7b6..a0c7c225 100644 --- a/src/Components/ImagesTable/RegionsPopover.js +++ b/src/Components/ImagesTable/RegionsPopover.js @@ -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(() => { diff --git a/src/Components/LandingPage/LandingPage.js b/src/Components/LandingPage/LandingPage.js index d8c6ed64..f231e31d 100644 --- a/src/Components/LandingPage/LandingPage.js +++ b/src/Components/LandingPage/LandingPage.js @@ -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(() => { diff --git a/src/Utilities/isBeta.js b/src/Utilities/isBeta.js deleted file mode 100644 index 2abecbc4..00000000 --- a/src/Utilities/isBeta.js +++ /dev/null @@ -1,7 +0,0 @@ -function isBeta() { - return insights.chrome.isBeta() || insights.chrome.getEnvironment() === 'qa' - ? true - : false; -} - -export default isBeta; diff --git a/src/Utilities/useGetEnvironment.js b/src/Utilities/useGetEnvironment.js new file mode 100644 index 00000000..70bb3dfd --- /dev/null +++ b/src/Utilities/useGetEnvironment.js @@ -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 }; +}; diff --git a/src/test/Components/CreateImageWizard/CreateImageWizard.azure.beta.test.js b/src/test/Components/CreateImageWizard/CreateImageWizard.azure.beta.test.js index 6eb1696d..ebbcda46 100644 --- a/src/test/Components/CreateImageWizard/CreateImageWizard.azure.beta.test.js +++ b/src/test/Components/CreateImageWizard/CreateImageWizard.azure.beta.test.js @@ -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'; - }, }, }; }); diff --git a/src/test/Components/CreateImageWizard/CreateImageWizard.beta.test.js b/src/test/Components/CreateImageWizard/CreateImageWizard.beta.test.js index ed13eca9..1b7c80f9 100644 --- a/src/test/Components/CreateImageWizard/CreateImageWizard.beta.test.js +++ b/src/test/Components/CreateImageWizard/CreateImageWizard.beta.test.js @@ -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'; - }, }, }; }); diff --git a/src/test/Components/CreateImageWizard/CreateImageWizard.test.js b/src/test/Components/CreateImageWizard/CreateImageWizard.test.js index 80bef69e..5ad7945e 100644 --- a/src/test/Components/CreateImageWizard/CreateImageWizard.test.js +++ b/src/test/Components/CreateImageWizard/CreateImageWizard.test.js @@ -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; diff --git a/src/test/Components/ImagesTable/ImagesTable.test.js b/src/test/Components/ImagesTable/ImagesTable.test.js index 5806d9c8..9c3a66e6 100644 --- a/src/test/Components/ImagesTable/ImagesTable.test.js +++ b/src/test/Components/ImagesTable/ImagesTable.test.js @@ -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') diff --git a/src/test/Components/LandingPage/LandingPage.test.js b/src/test/Components/LandingPage/LandingPage.test.js index e4484e5c..32e32344 100644 --- a/src/test/Components/LandingPage/LandingPage.test.js +++ b/src/test/Components/LandingPage/LandingPage.test.js @@ -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'; - }, }, }; }); diff --git a/src/test/Components/ShareImageModal/ShareImageModal.test.js b/src/test/Components/ShareImageModal/ShareImageModal.test.js index c86150be..17cafc02 100644 --- a/src/test/Components/ShareImageModal/ShareImageModal.test.js +++ b/src/test/Components/ShareImageModal/ShareImageModal.test.js @@ -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,