mirror of
https://github.com/Unleash/unleash.git
synced 2025-10-18 11:14:57 +02:00
This PR takes two steps towards better constraint handling: ## New type: `IConstraintWithId` Introduces a new type, `IConstraintWithId`. This is the same as an `IConstraint`, except the constraint id property is required. The idea is that the list of editable constraints should move towards using this instead of just `IConstraint`. That should prevent us (on a type-level) from seeing more of the same kind of errors we saw with the segment constraints yesterday. I don't want to go ahead and update all the upstream uses of this to IConstraintWithId in this PR, so I'll look at that separately. ## API payload constraint replacer Introduces an api payload constraint "replacer", which we can use for [JSON.stringify's `replacer` parameter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#the_replacer_parameter). The current implementation works both for strategies and for segments and has been added to edit + create forms for both of these resources. This has a couple benefits: 1. We can clearly state exactly how we want them to be rendered, including property order. I've decided to go with context -> operator -> value(s) as the main one (check the screenie), as I believe this is the most logical reading order. 2. We can exclude value/values (whichever one doesn't work with the operator) 3. It doesn't matter how we treat constraints internally, we can still present the payload how we want 4. Importantly: this only affects the stringification for the user-facing API payload, so it's very low risk. It does not affect anything that we actually send to the api. Here's what it can look like with ordered properties: <img width="392" alt="image" src="https://github.com/user-attachments/assets/f46f77c8-0b5a-4ded-b13a-bb567df60bd3" />
66 lines
1.9 KiB
TypeScript
66 lines
1.9 KiB
TypeScript
import { render } from 'utils/testRenderer';
|
|
import { screen, waitFor } from '@testing-library/react';
|
|
import userEvent from '@testing-library/user-event';
|
|
import { testServerRoute, testServerSetup } from 'utils/testServer';
|
|
import { SegmentFormStepTwo } from './SegmentFormStepTwo.tsx';
|
|
import { vi } from 'vitest';
|
|
import {
|
|
CREATE_SEGMENT,
|
|
UPDATE_PROJECT_SEGMENT,
|
|
} from 'component/providers/AccessProvider/permissions';
|
|
import type { IConstraintWithId } from 'interfaces/strategy.ts';
|
|
|
|
const server = testServerSetup();
|
|
|
|
const setupRoutes = () => {
|
|
testServerRoute(server, '/api/admin/context', [
|
|
{ name: 'userId' },
|
|
{ name: 'appName' },
|
|
{ name: 'environment' },
|
|
]);
|
|
|
|
testServerRoute(server, '/api/admin/ui-config', {
|
|
flags: {},
|
|
});
|
|
};
|
|
|
|
const defaultProps = {
|
|
project: undefined,
|
|
constraints: [] as IConstraintWithId[],
|
|
setConstraints: vi.fn(),
|
|
setCurrentStep: vi.fn(),
|
|
mode: 'create' as const,
|
|
};
|
|
|
|
describe('SegmentFormStepTwo', () => {
|
|
beforeEach(() => {
|
|
setupRoutes();
|
|
defaultProps.setConstraints.mockClear();
|
|
});
|
|
|
|
test('adding context field through autocomplete updates constraints list', async () => {
|
|
const user = userEvent.setup();
|
|
render(<SegmentFormStepTwo {...defaultProps} />, {
|
|
permissions: [
|
|
{ permission: CREATE_SEGMENT },
|
|
{ permission: UPDATE_PROJECT_SEGMENT },
|
|
],
|
|
});
|
|
|
|
const autocomplete =
|
|
await screen.findByPlaceholderText('Select a context');
|
|
|
|
await user.click(autocomplete);
|
|
|
|
await waitFor(() => {
|
|
expect(screen.getByText('userId')).toBeInTheDocument();
|
|
});
|
|
|
|
await user.click(screen.getByText('userId'));
|
|
|
|
await waitFor(() => {
|
|
expect(defaultProps.setConstraints).toHaveBeenCalled();
|
|
});
|
|
});
|
|
});
|