1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-12-09 20:04:11 +01:00
unleash.unleash/frontend/src/component/feature/FeatureView/FeatureOverview/FeatureOverviewMetaData/FeatureOverviewMetaData.test.tsx
Jaanus Sellin 3acb3ad2c2
feat: upgrade from react v17 to v18 (#7265)
**Upgrade to React v18 for Unleash v6. Here's why I think it's a good
time to do it:**
- Command Bar project: We've begun work on the command bar project, and
there's a fantastic library we want to use. However, it requires React
v18 support.
- Straightforward Upgrade: I took a look at the upgrade guide
https://react.dev/blog/2022/03/08/react-18-upgrade-guide and it seems
fairly straightforward. In fact, I was able to get React v18 running
with minimal changes in just 10 minutes!
- Dropping IE Support: React v18 no longer supports Internet Explorer
(IE), which is no longer supported by Microsoft as of June 15, 2022.
Upgrading to v18 in v6 would be a good way to align with this change.

TS updates:
* FC children has to be explicit:
https://stackoverflow.com/questions/71788254/react-18-typescript-children-fc
* forcing version 18 types in resolutions:
https://sentry.io/answers/type-is-not-assignable-to-type-reactnode/

Test updates:
* fixing SWR issue that we have always had but it manifests more in new
React (https://github.com/vercel/swr/issues/2373)

---------

Co-authored-by: kwasniew <kwasniewski.mateusz@gmail.com>
2024-06-11 13:59:52 +03:00

372 lines
9.5 KiB
TypeScript

import { fireEvent, screen } from '@testing-library/react';
import { render } from 'utils/testRenderer';
import FeatureOverviewMetaData from './FeatureOverviewMetaData';
import { testServerRoute, testServerSetup } from 'utils/testServer';
import { Route, Routes } from 'react-router-dom';
import type { IDependency, IFeatureToggle } from 'interfaces/featureToggle';
import ToastRenderer from 'component/common/ToastRenderer/ToastRenderer';
import userEvent from '@testing-library/user-event';
const server = testServerSetup();
const setupApi = () => {
testServerRoute(server, '/api/admin/ui-config', {
versionInfo: {
current: { oss: 'irrelevant', enterprise: 'some value' },
},
});
testServerRoute(
server,
'/api/admin/projects/default/features/feature/parents',
['some_parent'],
);
testServerRoute(
server,
'/api/admin/projects/default/features/feature/dependencies',
{},
'delete',
200,
);
testServerRoute(server, '/api/admin/projects/default/dependencies', false);
};
const setupOssWithExistingDependencies = () => {
testServerRoute(server, '/api/admin/ui-config', {
versionInfo: {
current: { oss: 'some value' },
},
});
testServerRoute(server, '/api/admin/projects/default/dependencies', true);
};
const setupChangeRequestApi = () => {
testServerRoute(
server,
'/api/admin/projects/default/change-requests/config',
[
{
environment: 'development',
type: 'development',
requiredApprovals: null,
changeRequestEnabled: true,
},
],
);
testServerRoute(
server,
'/api/admin/projects/default/change-requests/pending',
[],
);
testServerRoute(
server,
'/api/admin/projects/default/environments/development/change-requests',
{},
'post',
200,
);
};
const setupFeatureApi = (feature: IFeatureToggle) => {
testServerRoute(
server,
'/api/admin/projects/default/features/feature',
feature,
);
};
beforeEach(() => {
setupApi();
});
const route = '/projects/default/features/feature';
test('show dependency dialogue', async () => {
setupFeatureApi(feature);
render(
<Routes>
<Route
path={'/projects/:projectId/features/:featureId'}
element={<FeatureOverviewMetaData />}
/>
</Routes>,
{
route,
permissions: [
{ permission: 'UPDATE_FEATURE_DEPENDENCY', project: 'default' },
],
},
);
const addParentButton = await screen.findByText('Add parent feature');
addParentButton.click();
await screen.findByText('Add parent feature dependency');
});
test('show dependency dialogue for OSS with dependencies', async () => {
setupOssWithExistingDependencies();
setupFeatureApi({
name: 'feature',
project: 'default',
dependencies: [] as Array<{ feature: string }>,
children: [] as string[],
} as IFeatureToggle);
render(
<Routes>
<Route
path={'/projects/:projectId/features/:featureId'}
element={<FeatureOverviewMetaData />}
/>
</Routes>,
{
route,
permissions: [
{ permission: 'UPDATE_FEATURE_DEPENDENCY', project: 'default' },
],
},
);
const addParentButton = await screen.findByText('Add parent feature');
addParentButton.click();
await screen.findByText('Add parent feature dependency');
});
test('show child', async () => {
setupFeatureApi({
name: 'feature',
project: 'default',
dependencies: [] as Array<{ feature: string }>,
children: ['some_child'],
} as IFeatureToggle);
render(
<Routes>
<Route
path={'/projects/:projectId/features/:featureId'}
element={<FeatureOverviewMetaData />}
/>
</Routes>,
{ route },
);
await screen.findByText('Children:');
await screen.findByText('1 feature');
});
test('show children', async () => {
setupFeatureApi({
name: 'feature',
project: 'default',
dependencies: [] as Array<{ feature: string }>,
children: ['some_child', 'some_other_child'],
} as IFeatureToggle);
render(
<Routes>
<Route
path={'/projects/:projectId/features/:featureId'}
element={<FeatureOverviewMetaData />}
/>
</Routes>,
{ route },
);
await screen.findByText('Children:');
await screen.findByText('2 features');
});
const feature = {
name: 'feature',
project: 'default',
dependencies: [] as IDependency[],
children: [] as string[],
} as IFeatureToggle;
test('delete dependency', async () => {
setupFeatureApi({
...feature,
dependencies: [{ feature: 'some_parent' }],
});
render(
<>
<ToastRenderer />
<Routes>
<Route
path={'/projects/:projectId/features/:featureId'}
element={<FeatureOverviewMetaData />}
/>
</Routes>
</>,
{
route,
permissions: [
{ permission: 'UPDATE_FEATURE_DEPENDENCY', project: 'default' },
],
},
);
await screen.findByText('Dependency:');
await screen.findByText('some_parent');
const actionsButton = screen.getByRole('button', {
name: /Dependency actions/i,
});
fireEvent.click(actionsButton);
const deleteButton = await screen.findByText('Delete');
fireEvent.click(deleteButton);
await screen.findByText('Dependency removed');
});
test('delete dependency with change request', async () => {
setupChangeRequestApi();
setupFeatureApi({
...feature,
dependencies: [{ feature: 'some_parent' }],
});
render(
<>
<ToastRenderer />
<Routes>
<Route
path={'/projects/:projectId/features/:featureId'}
element={<FeatureOverviewMetaData />}
/>
</Routes>
</>,
{
route,
permissions: [
/* deliberately no permissions */
],
},
);
await screen.findByText('Dependency:');
await screen.findByText('some_parent');
const actionsButton = await screen.findByRole('button', {
name: /Dependency actions/i,
});
fireEvent.click(actionsButton);
const deleteButton = await screen.findByText('Delete');
fireEvent.click(deleteButton);
await screen.findByText('Change added to a draft');
});
test('edit dependency', async () => {
setupFeatureApi({
...feature,
dependencies: [{ feature: 'some_parent', enabled: false }],
});
render(
<Routes>
<Route
path={'/projects/:projectId/features/:featureId'}
element={<FeatureOverviewMetaData />}
/>
</Routes>,
{
route,
permissions: [
{ permission: 'UPDATE_FEATURE_DEPENDENCY', project: 'default' },
],
},
);
await screen.findByText('Dependency:');
await screen.findByText('some_parent');
await screen.findByText('Dependency value:');
await screen.findByText('disabled');
const actionsButton = await screen.findByRole('button', {
name: /Dependency actions/i,
});
fireEvent.click(actionsButton);
const editButton = await screen.findByText('Edit');
fireEvent.click(editButton);
await screen.findByText('Add parent feature dependency');
});
test('show variant dependencies', async () => {
setupFeatureApi({
...feature,
dependencies: [
{
feature: 'some_parent',
enabled: true,
variants: ['variantA', 'variantB'],
},
],
});
render(
<Routes>
<Route
path={'/projects/:projectId/features/:featureId'}
element={<FeatureOverviewMetaData />}
/>
</Routes>,
{ route },
);
const variants = await screen.findByText('2 variants');
await userEvent.hover(variants);
await screen.findByText('variantA');
await screen.findByText('variantB');
});
test('show variant dependency', async () => {
setupFeatureApi({
...feature,
dependencies: [
{
feature: 'some_parent',
enabled: true,
variants: ['variantA'],
},
],
});
render(
<Routes>
<Route
path={'/projects/:projectId/features/:featureId'}
element={<FeatureOverviewMetaData />}
/>
</Routes>,
{ route },
);
await screen.findByText('variantA');
});
test('show disabled dependency', async () => {
setupFeatureApi({
...feature,
dependencies: [
{
feature: 'some_parent',
enabled: false,
},
],
});
render(
<Routes>
<Route
path={'/projects/:projectId/features/:featureId'}
element={<FeatureOverviewMetaData />}
/>
</Routes>,
{ route },
);
await screen.findByText('disabled');
});