feat: finishing up some other use cases and re-writing some logic with some more tests

Signed-off-by: blam <ben@blam.sh>
This commit is contained in:
blam
2021-06-12 17:41:21 +02:00
parent c92f5dedee
commit 128279fc4f
6 changed files with 158 additions and 68 deletions
+1 -1
View File
@@ -114,7 +114,7 @@ const routes = (
path="/tech-radar"
element={<TechRadarPage width={1500} height={800} />}
/>
<FeatureFlagged flag="show-graphiql-page">
<FeatureFlagged with="show-graphiql-page">
<Route path="/graphiql" element={<GraphiQLPage />} />
</FeatureFlagged>
<Route path="/lighthouse" element={<LighthousePage />} />
@@ -283,7 +283,7 @@ const serviceEntityPage = (
{overviewContent}
</EntityLayout.Route>
<FeatureFlagged flag="show-graphiql-page">
<FeatureFlagged with="show-graphiql-page">
<EntityLayout.Route path="/ci-cd" title="CI/CD">
{cicdContent}
</EntityLayout.Route>
@@ -306,7 +306,7 @@ const serviceEntityPage = (
<EntityLayout.Route path="/dependencies" title="Dependencies">
<Grid container spacing={3} alignItems="stretch">
<FeatureFlagged flag="show-graphiql-page">
<FeatureFlagged with="show-graphiql-page">
<Grid item md={6}>
<EntityDependsOnComponentsCard variant="gridItem" />
</Grid>
@@ -177,8 +177,8 @@ export const featureFlagCollector = createCollector(
() => new Set<string>(),
(acc, node) => {
if (node.type === FeatureFlagged) {
const { flag } = node.props as FeatureFlaggedProps;
acc.add(flag);
const props = node.props as FeatureFlaggedProps;
acc.add('with' in props ? props.with : props.without);
}
},
);
@@ -37,8 +37,11 @@ attachComponentData(InnerComponent, INNER_COMPONENT_KEY, {
});
const MockComponent = (_props: { children: ReactNode }) => null;
const FeatureFlagComponent = (_props: { children: ReactNode; flag: string }) =>
null;
const FeatureFlagComponent = (_props: {
children: ReactNode;
with?: string;
without?: string;
}) => null;
attachComponentData(FeatureFlagComponent, 'core.featureFlagged', true);
const mockFeatureFlagsApi = new LocalStorageFeatureFlags();
const Wrapper = ({ children }: { children?: React.ReactNode }) => (
@@ -151,73 +154,155 @@ describe('useElementFilter', () => {
});
});
it('should not discover deeper than the feature gate if the feature flag is disabled', () => {
jest.spyOn(mockFeatureFlagsApi, 'isActive').mockImplementation(() => false);
const tree = (
<MockComponent>
<FeatureFlagComponent flag="testing-flag">
<WrappingComponent key="first">
describe('FeatureFlags', () => {
describe('with', () => {
it('should not discover deeper than the feature gate if the feature flag is disabled', () => {
jest
.spyOn(mockFeatureFlagsApi, 'isActive')
.mockImplementation(() => false);
const tree = (
<MockComponent>
<FeatureFlagComponent with="testing-flag">
<WrappingComponent key="first">
<InnerComponent />
</WrappingComponent>
</FeatureFlagComponent>
<MockComponent>
<WrappingComponent key="second">
<InnerComponent />
</WrappingComponent>
</MockComponent>
<InnerComponent />
</WrappingComponent>
</FeatureFlagComponent>
<MockComponent>
<WrappingComponent key="second">
</MockComponent>
);
const { result } = renderHook(
props =>
useElementFilter(props.tree, elements =>
elements
.selectByComponentData({ key: WRAPPING_COMPONENT_KEY })
.getElements(),
),
{
initialProps: { tree },
wrapper: Wrapper,
},
);
expect(result.current.length).toBe(1);
expect(result.current[0].key).toContain('second');
});
it('should discover components behind a feature flag if the flag is enabled', () => {
jest
.spyOn(mockFeatureFlagsApi, 'isActive')
.mockImplementation(() => true);
const tree = (
<MockComponent>
<FeatureFlagComponent with="testing-flag">
<WrappingComponent key="first">
<InnerComponent />
</WrappingComponent>
</FeatureFlagComponent>
<MockComponent>
<WrappingComponent key="second">
<InnerComponent />
</WrappingComponent>
</MockComponent>
<InnerComponent />
</WrappingComponent>
</MockComponent>
<InnerComponent />
</MockComponent>
);
</MockComponent>
);
const { result } = renderHook(
props =>
useElementFilter(props.tree, elements =>
elements
.selectByComponentData({ key: WRAPPING_COMPONENT_KEY })
.getElements(),
),
{
initialProps: { tree },
wrapper: Wrapper,
},
);
const { result } = renderHook(
props =>
useElementFilter(props.tree, elements =>
elements
.selectByComponentData({ key: WRAPPING_COMPONENT_KEY })
.getElements(),
),
{
initialProps: { tree },
wrapper: Wrapper,
},
);
expect(result.current.length).toBe(1);
expect(result.current[0].key).toContain('second');
});
expect(result.current.length).toBe(2);
});
});
it('should discover components behind a feature flag if the flag is enabled', () => {
jest.spyOn(mockFeatureFlagsApi, 'isActive').mockImplementation(() => true);
const tree = (
<MockComponent>
<FeatureFlagComponent flag="testing-flag">
<WrappingComponent key="first">
describe('without', () => {
it('should discover deeper than the feature gate if the feature flag is disabled', () => {
jest
.spyOn(mockFeatureFlagsApi, 'isActive')
.mockImplementation(() => false);
const tree = (
<MockComponent>
<FeatureFlagComponent without="testing-flag">
<WrappingComponent key="first">
<InnerComponent />
</WrappingComponent>
</FeatureFlagComponent>
<MockComponent>
<WrappingComponent key="second">
<InnerComponent />
</WrappingComponent>
</MockComponent>
<InnerComponent />
</WrappingComponent>
</FeatureFlagComponent>
<MockComponent>
<WrappingComponent key="second">
</MockComponent>
);
const { result } = renderHook(
props =>
useElementFilter(props.tree, elements =>
elements
.selectByComponentData({ key: WRAPPING_COMPONENT_KEY })
.getElements(),
),
{
initialProps: { tree },
wrapper: Wrapper,
},
);
expect(result.current.length).toBe(2);
});
it('should not discover components behind a feature flag if the flag is enabled', () => {
jest
.spyOn(mockFeatureFlagsApi, 'isActive')
.mockImplementation(() => true);
const tree = (
<MockComponent>
<FeatureFlagComponent without="testing-flag">
<WrappingComponent key="first">
<InnerComponent />
</WrappingComponent>
</FeatureFlagComponent>
<MockComponent>
<WrappingComponent key="second">
<InnerComponent />
</WrappingComponent>
</MockComponent>
<InnerComponent />
</WrappingComponent>
</MockComponent>
<InnerComponent />
</MockComponent>
);
</MockComponent>
);
const { result } = renderHook(
props =>
useElementFilter(props.tree, elements =>
elements
.selectByComponentData({ key: WRAPPING_COMPONENT_KEY })
.getElements(),
),
{
initialProps: { tree },
wrapper: Wrapper,
},
);
const { result } = renderHook(
props =>
useElementFilter(props.tree, elements =>
elements
.selectByComponentData({ key: WRAPPING_COMPONENT_KEY })
.getElements(),
),
{
initialProps: { tree },
wrapper: Wrapper,
},
);
expect(result.current.length).toBe(2);
expect(result.current.length).toBe(1);
});
});
});
it('should reject when strict mode is enabled with the correct string', () => {
@@ -252,7 +337,7 @@ describe('useElementFilter', () => {
<>
<MockComponent>
<>
<FeatureFlagComponent flag="testing-flag">
<FeatureFlagComponent with="testing-flag">
<WrappingComponent key="first">
<InnerComponent />
</WrappingComponent>
@@ -45,8 +45,12 @@ function selectChildren(
}
if (getComponentData(node, 'core.featureFlagged')) {
const { flag } = node.props as { flag: string };
if (featureFlagsApi.isActive(flag)) {
const props = node.props as { with: string } | { without: string };
const isEnabled =
'with' in props
? featureFlagsApi.isActive(props.with)
: !featureFlagsApi.isActive(props.without);
if (isEnabled) {
return selectChildren(
node.props.children,
featureFlagsApi,
@@ -40,6 +40,7 @@ describe('index', () => {
useApi: expect.any(Function),
useApiHolder: expect.any(Function),
useApp: expect.any(Function),
useElementFilter: expect.any(Function),
useRouteRef: expect.any(Function),
useRouteRefParams: expect.any(Function),
withApis: expect.any(Function),