Skip to content

Commit

Permalink
feat(pci-common): add 3AZ chip condition (#14716)
Browse files Browse the repository at this point in the history
Signed-off-by: tsiorifamonjena <[email protected]>
Signed-off-by: Simon Chaumet <[email protected]>
Co-authored-by: Simon Chaumet <[email protected]>
  • Loading branch information
Tsiorifamonjena and SimonChaumet committed Jan 8, 2025
1 parent 24b6611 commit 0afc18d
Show file tree
Hide file tree
Showing 9 changed files with 247 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
} from './RegionGlobalzoneChip.component';
import { wrapper } from '@/wrapperRenders';
import { URL_INFO } from '@/components/region-selector/constants';
import { useHas3AZ } from '@/hooks/useHas3AZ/useHas3AZ';

vi.mock('@ovh-ux/manager-react-components', async (importOriginal) => {
const module = await importOriginal<
Expand All @@ -18,6 +19,8 @@ vi.mock('@ovh-ux/manager-react-components', async (importOriginal) => {
return { ...module, useFeatureAvailability: vi.fn() };
});

vi.mock('@/hooks/useHas3AZ/useHas3AZ');

enum ExpectedType {
GLOBAL_REGIONS = 'GLOBAL_REGIONS',
'1AZ_REGIONS' = '1AZ_REGIONS',
Expand Down Expand Up @@ -87,4 +90,40 @@ describe('RegionGlobalzoneChip', () => {
}
},
);

it.each([
['render', true, true],
['not render', true, undefined],
['not render', false, true],
])(
'should %s 3AZ tooltip text when feature availability is %s and 3AZ availability is %s',
(expected: string, show1AZ: boolean, has3AZ: boolean) => {
vi.mocked(useFeatureAvailability).mockImplementationOnce(
(features) =>
({
data: {
...Object.fromEntries(
features.map((feature) => [feature, false]),
),
[FEATURE_REGION_1AZ]: show1AZ,
},
isLoading: false,
} as UseFeatureAvailabilityResult),
);

vi.mocked(useHas3AZ).mockReturnValue(has3AZ);

render(<RegionGlobalzoneChip />, { wrapper });

if (expected === 'render') {
expect(
screen.getByText('pci_project_flavors_zone_1AZ_with_3AZ_tooltip'),
).toBeInTheDocument();
} else {
expect(
screen.queryByText('pci_project_flavors_zone_1AZ_with_3AZ_tooltip'),
).not.toBeInTheDocument();
}
},
);
});
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
import { OdsHTMLAnchorElementTarget } from '@ovhcloud/ods-common-core';
import { useTranslation } from 'react-i18next';
import { URL_INFO } from './constants';
import { useHas3AZ } from '../../hooks/useHas3AZ/useHas3AZ';

export const FEATURE_REGION_1AZ = 'public-cloud:region-1AZ';

Expand All @@ -42,6 +43,8 @@ export function RegionGlobalzoneChip({
const tooltipUrl =
URL_INFO[linkType][ovhSubsidiary] || URL_INFO[linkType].DEFAULT;

const has3AZ = useHas3AZ();

const chip = (
<OsdsChip
class="chip-1AZ"
Expand Down Expand Up @@ -75,11 +78,13 @@ export function RegionGlobalzoneChip({
color={ODS_THEME_COLOR_INTENT.text}
level={ODS_TEXT_LEVEL.body}
>
{t(
`pci_project_flavors_zone_${
data?.[FEATURE_REGION_1AZ] ? '1AZ' : 'globalregions'
}_tooltip`,
)}
{has3AZ && data?.[FEATURE_REGION_1AZ]
? t('pci_project_flavors_zone_1AZ_with_3AZ_tooltip')
: t(
`pci_project_flavors_zone_${
data?.[FEATURE_REGION_1AZ] ? '1AZ' : 'globalregions'
}_tooltip`,
)}
</OsdsText>
&nbsp;
<Links
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { createContext } from 'react';

export interface InternalMeta {
has3AZ?: boolean;
}

/**
* This type is only used to add completion with LSP
*/
export type PCICommonMetaType =
| InternalMeta
| Record<string, unknown>
| undefined;

/**
* Use {usePCICommonContextFactory} for general usage.
*
* Use this to override previously set properties
*/
export const PCICommonContext = createContext<PCICommonMetaType>(undefined);
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { renderHook } from '@testing-library/react';
import { useHas3AZ } from './useHas3AZ';
import { PCICommonContext } from '../../contexts/PCICommonContext/PCICommonContext';
import { usePCICommonContextFactory } from '../usePCICommonContextFactory/usePCICommonContextFactory';

describe('useHas3AZ', () => {
it.each([
[false, undefined],
[false, {}],
[false, { has3AZ: false }],
[false, { has3AZ: 'whatever' }],
[false, { has3AZ: null }],
[true, { has3AZ: true }],
])(
'should return %s when meta is %o',
(expected: boolean, meta: { has3AZ: boolean | string } | undefined) => {
const { result } = renderHook(() => useHas3AZ(), {
wrapper: ({ children }) => {
const pciCommonContext = usePCICommonContextFactory(meta);

return (
<PCICommonContext.Provider value={pciCommonContext}>
{children}
</PCICommonContext.Provider>
);
},
});

expect(result.current).toBe(expected);
},
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { useContext } from 'react';
import { PCICommonContext } from '../../contexts/PCICommonContext/PCICommonContext';

export const useHas3AZ = (): boolean => {
const meta = useContext(PCICommonContext);

return meta && 'has3AZ' in meta && typeof meta.has3AZ === 'boolean'
? meta.has3AZ
: false;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import { renderHook } from '@testing-library/react';
import { PropsWithChildren, useContext } from 'react';
import { PCICommonContext } from '@/contexts/PCICommonContext/PCICommonContext';
import { usePCICommonContextFactory } from './usePCICommonContextFactory';

const myVarChildren = {
myVar: 'children',
};

const TestChildrenMerge = ({ children }: PropsWithChildren) => {
const pciCommonContext = usePCICommonContextFactory(myVarChildren);

return (
<PCICommonContext.Provider value={pciCommonContext}>
{children}
</PCICommonContext.Provider>
);
};

const TestChildrenOverride = ({ children }: PropsWithChildren) => (
<PCICommonContext.Provider value={myVarChildren}>
{children}
</PCICommonContext.Provider>
);

const ParentWithoutProvider = ({ children }: PropsWithChildren) => (
<TestChildrenMerge>{children}</TestChildrenMerge>
);

const myVarParent = {
myVar: 'parent',
};

const ParentWithMyVar = ({ children }: PropsWithChildren) => {
const pciCommonContext = usePCICommonContextFactory(myVarParent);

return (
<PCICommonContext.Provider value={pciCommonContext}>
<TestChildrenMerge>{children}</TestChildrenMerge>
</PCICommonContext.Provider>
);
};

const myVar2Parent = {
myVar2: 'parent',
};

const ParentWithMyVar2 = ({ children }: PropsWithChildren) => {
const pciCommonContext = usePCICommonContextFactory(myVar2Parent);

return (
<PCICommonContext.Provider value={pciCommonContext}>
{children}
</PCICommonContext.Provider>
);
};

const ParentWithEmptyFactory = ({ children }: PropsWithChildren) => {
const pciCommonContext = usePCICommonContextFactory();

return (
<PCICommonContext.Provider value={pciCommonContext}>
{children}
</PCICommonContext.Provider>
);
};

describe('usePCICommonContextFactory', () => {
it('should set value', () => {
const { result } = renderHook(() => useContext(PCICommonContext), {
wrapper: ParentWithoutProvider,
});

expect(result.current).toEqual({ myVar: 'children' });
});

it('should override previously set value', () => {
const { result } = renderHook(() => useContext(PCICommonContext), {
wrapper: ParentWithMyVar,
});

expect(result.current).toEqual({ myVar: 'children' });
});

it('should merge with old value', () => {
const { result } = renderHook(() => useContext(PCICommonContext), {
wrapper: ({ children }) => (
<ParentWithMyVar2>
<TestChildrenMerge>{children}</TestChildrenMerge>
</ParentWithMyVar2>
),
});

expect(result.current).toEqual({ myVar: 'children', myVar2: 'parent' });
});

it('should override old value', () => {
const { result } = renderHook(() => useContext(PCICommonContext), {
wrapper: ({ children }) => (
<ParentWithMyVar2>
<TestChildrenOverride>{children}</TestChildrenOverride>
</ParentWithMyVar2>
),
});

expect(result.current).toEqual({ myVar: 'children' });
});

it('should work with no values', () => {
const { result } = renderHook(() => useContext(PCICommonContext), {
wrapper: ParentWithEmptyFactory,
});

expect(result.current).toEqual({});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useContext, useMemo } from 'react';
import {
PCICommonContext,
PCICommonMetaType,
} from '../../contexts/PCICommonContext/PCICommonContext';

/**
* Use this to merge meta properties with previously set properties (merge is only on level 1)
*
* To override all properties use the provider directly
* @param meta Be sure to create it outside your component or memoize it to avoid performance issues
*/
export function usePCICommonContextFactory(meta?: PCICommonMetaType) {
const base = useContext(PCICommonContext);

return useMemo(() => ({ ...(base || {}), ...(meta || {}) }), [base, meta]);
}
2 changes: 2 additions & 0 deletions packages/manager/modules/manager-pci-common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export * from './components/region-selector/RegionLocalzoneChip.component';
export * from './components/region-selector/Region3AZChip.component';
export * from './hooks';
export * from './constants';
export { PCICommonContext } from './contexts/PCICommonContext/PCICommonContext';
export { usePCICommonContextFactory } from './hooks/usePCICommonContextFactory/usePCICommonContextFactory';
export * from './components/quantity-selector';
export * from './components/Pricing';
export * from './components/shape-input/ShapeInput.component';
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"pci_project_flavors_zone_localzone_tooltip": "Les Local Zones sont un nouveau type de localisation, qui prennent en charge une partie de notre portefeuille de produits Public Cloud. Nous allons progressivement augmenter le nombre total de Local Zones dans le monde au cours des prochaines années.",
"pci_project_flavors_zone_localzone_1AZ_tooltip": "Une Local Zone correspond à un mode de déploiement des produits Public Cloud d’OVHcloud dans des datacenters situés au plus près des utilisateurs finaux.",
"pci_project_flavors_zone_globalregions_tooltip": "Les Régions sont supportées par un ou plusieurs datacenters gérés par OVHCloud. Chaque région fournit une ou plusieurs Availability Zone avec le portefeuille complet de services OVHCloud.",
"pci_project_flavors_zone_1AZ_with_3AZ_tooltip": "Avec l'arrivée prochaine des régions 3-AZ, le type de déploiement 'Régions' change de nom ! Une région 1-AZ (zone de disponibilité) regroupe un ou plusieurs datacenters localisés sur un même site.",
"pci_project_flavors_zone_1AZ_tooltip": "Une région 1-AZ (zone de disponibilité) regroupe un ou plusieurs datacenters localisés sur un même site.",
"pci_project_flavors_zone_3AZ_tooltip": "Une région 3-AZ comprend trois zones de disponibilités situées dans une même aire métropolitaine, séparées par quelques kilomètres. Elle répond aux exigences les plus élevées en matière de résilience tout en garantissant une latence extrêmement faible entre les AZ.",
"pci_project_flavors_zone_tooltip_link": "En savoir plus"
Expand Down

0 comments on commit 0afc18d

Please sign in to comment.