Skip to content

Commit 24a5f7b

Browse files
committed
Merge branch 'bugfix/ARTESCA-17433-exclude-crr-location-from-lifecycle-transition' into q/4
2 parents 52ef1a3 + bf75020 commit 24a5f7b

3 files changed

Lines changed: 82 additions & 2 deletions

File tree

src/react/databrowser/buckets/StorageClassSelector.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ import type { StorageClassSelectorProps } from '@scality/data-browser-library';
44
import type { LocationInfo } from '../../next-architecture/adapters/accounts-locations/ILocationsAdapter';
55
import { useLocationsAndEndpoints } from '../../next-architecture/domain/business/accounts';
66
import { useLocationsEndpointsAdapter } from '../../next-architecture/ui/LocationsEndpointsAdapterProvider';
7-
import { getLocationTypeShort, isHdclientV2, isReplicationTarget } from '../../utils/storageOptions';
7+
import { getLocationTypeShort, isCRRLocation, isHdclientV2, isReplicationTarget } from '../../utils/storageOptions';
88

99
const locationFilter: Record<string, (l: LocationInfo) => boolean> = {
1010
replication: isReplicationTarget,
11-
lifecycle: (l) => !isHdclientV2(l),
11+
// CRR locations are replication-only targets: transitions towards them are
12+
// rejected by the backend, so they must not be offered for lifecycle rules.
13+
lifecycle: (l) => !isHdclientV2(l) && !isCRRLocation(l),
1214
};
1315

1416
export function StorageClassSelector({ value, onChange, context }: StorageClassSelectorProps) {
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { render, screen } from '@testing-library/react';
2+
import userEvent from '@testing-library/user-event';
3+
import { ThemeProvider } from 'styled-components';
4+
import { LocationType } from '../../../../js/managementClient/api';
5+
import type { LocationInfo } from '../../../next-architecture/adapters/accounts-locations/ILocationsAdapter';
6+
import { theme } from '../../../utils/testUtil';
7+
import { StorageClassSelector } from '../StorageClassSelector';
8+
9+
const mockUseLocationsAndEndpoints = jest.fn();
10+
jest.mock('../../../next-architecture/domain/business/accounts', () => ({
11+
useLocationsAndEndpoints: () => mockUseLocationsAndEndpoints(),
12+
}));
13+
14+
jest.mock('../../../next-architecture/ui/LocationsEndpointsAdapterProvider', () => ({
15+
useLocationsEndpointsAdapter: () => ({}),
16+
}));
17+
18+
const locations: LocationInfo[] = [
19+
{
20+
id: '1',
21+
name: 'artesca-s3-location',
22+
type: LocationType.ScalityArtescaS3V1,
23+
details: {},
24+
},
25+
{
26+
id: '2',
27+
name: 'crr-location',
28+
type: LocationType.ScalityCrrV1,
29+
details: {},
30+
},
31+
{
32+
id: '3',
33+
name: 'storage-service',
34+
type: LocationType.ScalityHdclientV2,
35+
details: {},
36+
},
37+
];
38+
39+
const renderSelector = (context: 'replication' | 'lifecycle') =>
40+
render(
41+
<ThemeProvider theme={theme}>
42+
<StorageClassSelector value="" onChange={jest.fn()} context={context} />
43+
</ThemeProvider>,
44+
);
45+
46+
describe('StorageClassSelector', () => {
47+
beforeEach(() => {
48+
jest.clearAllMocks();
49+
mockUseLocationsAndEndpoints.mockReturnValue({
50+
locationsAndEndpoints: { locations },
51+
status: 'success',
52+
});
53+
});
54+
55+
it('should not offer CRR nor storage service locations for lifecycle transitions', async () => {
56+
renderSelector('lifecycle');
57+
58+
await userEvent.click(screen.getByRole('textbox'));
59+
60+
expect(screen.getByRole('option', { name: 'artesca-s3-location (ARTESCA)' })).toBeInTheDocument();
61+
expect(screen.queryByRole('option', { name: /crr-location/ })).not.toBeInTheDocument();
62+
expect(screen.queryByRole('option', { name: /storage-service/ })).not.toBeInTheDocument();
63+
});
64+
65+
it('should offer CRR locations as replication destinations', async () => {
66+
renderSelector('replication');
67+
68+
await userEvent.click(screen.getByRole('textbox'));
69+
70+
expect(screen.getByRole('option', { name: 'crr-location (CRR)' })).toBeInTheDocument();
71+
expect(screen.getByRole('option', { name: 'artesca-s3-location (ARTESCA)' })).toBeInTheDocument();
72+
expect(screen.queryByRole('option', { name: /storage-service/ })).not.toBeInTheDocument();
73+
});
74+
});

src/react/utils/storageOptions.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ export function isReplicationTarget(location: LocationInfo): boolean {
3636
export function isHdclientV2(location: LocationInfo): boolean {
3737
return (location.type as unknown as string) === 'location-scality-hdclient-v2';
3838
}
39+
40+
export function isCRRLocation(location: LocationInfo): boolean {
41+
return (location.type as unknown as string) === 'location-scality-crr-v1';
42+
}
3943
export function checkIfExternalLocation(locations: LocationInfo[]): boolean {
4044
return locations.some((l) => l.type !== LocationType.FileV1);
4145
}

0 commit comments

Comments
 (0)