export context for testing,

added tests for indicator icons,
use wrapped indicator icon for backward compatibility.
This commit is contained in:
Annika Hannig 2023-04-14 13:01:14 +02:00
parent 56a8fd65cc
commit 44a67c1f89
10 changed files with 255 additions and 25 deletions

View File

@ -0,0 +1,21 @@
import { FontAwesomeIcon }
from '@fortawesome/react-fontawesome';
/**
* Display a route flag icon indicator with a tooltip.
*
* @param icon - The icon to display.
* @param tooltip - The tooltip to display.
*/
const FlagIcon = ({icon, tooltip}) => {
return (
<>
<i><FontAwesomeIcon icon={icon} /></i>
<div>{tooltip}</div>
</>
);
}
export default FlagIcon;

View File

@ -0,0 +1,23 @@
import { render, screen }
from '@testing-library/react';
import { faCircle }
from '@fortawesome/free-solid-svg-icons';
import FlagIcon
from './FlagIcon';
/**
* Test rendering of the flag icon component.
*/
test('renders flag icon', () => {
render(
<div data-testid="icon">
<FlagIcon icon={faCircle} tooltip="A flag icon" />
</div>
);
// Check that the tooltip is in the document.
expect(screen.getByText('A flag icon')).toBeInTheDocument();
});

View File

@ -1,6 +1,4 @@
import { FontAwesomeIcon }
from '@fortawesome/react-fontawesome';
import { faCircle }
from '@fortawesome/free-solid-svg-icons';
@ -11,7 +9,13 @@ import { matchCommunityRange
}
from 'app/context/bgp';
import FlagIcon
from 'app/components/routes/FlagIcon';
/**
* BlackholeIndicator
* Displays a blackhole indicator if the route is a blackhole.
*/
const BlackholeIndicator = ({route}) => {
const routeServer = useRouteServer(); // blackholes are store per RS
const blackholeCommunities = useBlackholeCommunities();
@ -56,8 +60,7 @@ const BlackholeIndicator = ({route}) => {
if (isBlackhole) {
return(
<span className="route-prefix-flag blackhole-route is-blackhole-route">
<FontAwesomeIcon icon={faCircle} />
<div>Blackhole</div>
<FlagIcon icon={faCircle} tooltip="Blackhole" />
</span>
);
}

View File

@ -1,15 +1,20 @@
import { FontAwesomeIcon }
from '@fortawesome/react-fontawesome';
import { faStar }
from '@fortawesome/free-solid-svg-icons';
import FlagIcon
from 'app/components/routes/FlagIcon';
/**
* Show a primary route indicator icon
*
* @param route - The route object
*/
const PrimaryIndicator = ({route}) => {
if (route.primary) {
return(
<span className="route-prefix-flag primary-route is-primary-route">
<FontAwesomeIcon icon={faStar} />
<div>Best Route</div>
<FlagIcon icon={faStar} tooltip="Best Route" />
</span>
);
}

View File

@ -0,0 +1,28 @@
import { render, screen }
from '@testing-library/react';
import PrimaryIndicator
from './PrimaryIndicator';
/**
* Test rendering the primary indicator
*/
test('renders primary indicator', () => {
// Routes for testing: primary and not primary
const primaryRoute = {
primary: true,
};
const notPrimaryRoute = {
primary: false,
};
// Render the non primary route indicator
render(<PrimaryIndicator route={notPrimaryRoute} />);
expect(screen.queryByText('Best Route')).not.toBeInTheDocument();
// Render the primary indicator
render(<PrimaryIndicator route={primaryRoute} />);
expect(screen.getByText('Best Route')).toBeInTheDocument();
});

View File

@ -1,24 +1,28 @@
import { FontAwesomeIcon }
from '@fortawesome/react-fontawesome';
import { faCircleExclamation }
from '@fortawesome/free-solid-svg-icons';
import { useRejectCandidate }
from 'app/context/bgp';
import FlagIcon
from 'app/components/routes/FlagIcon';
/**
* RejectCandidateIndicator
* Displays a flag if the route is a reject candidate.
*
* @param route - The route to check
*/
const RejectCandidateIndicator = ({route}) => {
const isRejectCandidate = useRejectCandidate(route);
if (!isRejectCandidate) {
return null;
}
const cls = `route-prefix-flag reject-candidate-route`;
return (
<span className={cls}>
<FontAwesomeIcon icon={faCircleExclamation} />
<div>Reject Candidate</div>
<span className="route-prefix-flag reject-candidate-route">
<FlagIcon icon={faCircleExclamation} tooltip="Reject Candidate" />
</span>
);
}

View File

@ -0,0 +1,46 @@
import { render, screen }
from '@testing-library/react';
import RejectCandidateIndicator
from './RejectCandidateIndicator';
import { ConfigContext }
from 'app/context/config';
// Mock config with reject candidate community
const config = {
reject_candidates: {
communities: {
1111: {
1234: {
1: "reject-candidate-2",
},
},
},
},
};
/**
* Test the RejectCandidateIndicator component with
*/
test('renders reject candidate indicator' , () => {
const route = {
bgp: {
large_communities: [
[1111, 1234, 1],
],
},
};
// Render the component
render(
<ConfigContext.Provider value={config}>
<RejectCandidateIndicator route={route} />
</ConfigContext.Provider>
);
// Check that the indicator is rendered
expect(screen.getByText('Reject Candidate')).toBeInTheDocument();
});

View File

@ -1,6 +1,4 @@
import { FontAwesomeIcon }
from '@fortawesome/react-fontawesome';
import { faCircleCheck
, faCircleMinus
, faCircleQuestion
@ -12,6 +10,9 @@ import { faCircle }
import { useConfig }
from 'app/context/config';
import FlagIcon
from 'app/components/routes/FlagIcon';
const RpkiIndicator = ({route}) => {
const { rpki } = useConfig();
@ -19,6 +20,7 @@ const RpkiIndicator = ({route}) => {
if (rpki.enabled === false) { return null; }
// Check for BGP large communities as configured in the alice.conf
// FIXME: why are we using strings here?! ['1234', '123', '1'].
const rpkiValid = rpki.valid;
const rpkiUnknown = rpki.unknown;
const rpkiNotChecked = rpki.not_checked;
@ -32,8 +34,7 @@ const RpkiIndicator = ({route}) => {
com[2].toFixed() === rpkiValid[2]) {
return (
<span className="route-prefix-flag rpki-route rpki-valid">
<FontAwesomeIcon icon={faCircleCheck} />
<div>RPKI Valid</div>
<FlagIcon icon={faCircleCheck} tooltip="RPKI Valid" />
</span>
);
}
@ -44,8 +45,7 @@ const RpkiIndicator = ({route}) => {
com[2].toFixed() === rpkiUnknown[2]) {
return (
<span className="route-prefix-flag rpki-route rpki-unknown">
<FontAwesomeIcon icon={faCircleQuestion} />
<div>RPKI Unknown</div>
<FlagIcon icon={faCircleQuestion} tooltip="RPKI Unknown" />
</span>
);
}
@ -56,8 +56,7 @@ const RpkiIndicator = ({route}) => {
com[2].toFixed() === rpkiNotChecked[2]) {
return (
<span className="route-prefix-flag rpki-route rpki-not-checked">
<FontAwesomeIcon icon={faCircle} />
<div>RPKI not checked</div>
<FlagIcon icon={faCircle} tooltip="RPKI Not Checked" />
</span>
);
}
@ -88,8 +87,7 @@ const RpkiIndicator = ({route}) => {
const cls = `route-prefix-flag rpki-route rpki-invalid rpki-invalid-${rpkiInvalidReason}`
return (
<span className={cls}>
<FontAwesomeIcon icon={faCircleMinus} />
<div>RPKI Invalid</div>
<FlagIcon icon={faCircleMinus} tooltip="RPKI Invalid" />
</span>
);
}

View File

@ -0,0 +1,102 @@
import { render, screen }
from '@testing-library/react';
import { ConfigContext }
from 'app/context/config';
import RpkiIndicator
from './RpkiIndicator';
// Provide config context with rpki settings
const config = {
rpki: {
enabled: true,
valid: ["1234", "1111", "1"],
unknown: ["1234", "1111", "0"],
not_checked: ["1234", "1111", "10"],
invalid: ["1234", "1111", "100"],
},
};
/**
* Test rendering the RpkiIndicator component.
*/
test('renders RpkiIndicator with a valid route', () => {
// Render the RpkiIndicator component for a valid prefix
const route = {
bgp: {
large_communities: [
[1234, 1111, 1],
],
},
};
render(
<ConfigContext.Provider value={config}>
<RpkiIndicator route={route} />
</ConfigContext.Provider>
);
expect(screen.getByText('RPKI Valid')).toBeInTheDocument();
});
/**
* Test rendering the RpkiIndicator component with
* an rpki unknown route.
*/
test('renders RpkiIndicator with an unknown route', () => {
// Render the RpkiIndicator component for an unknown prefix
const route = {
bgp: {
large_communities: [
[1234, 1111, 0],
],
},
};
render(
<ConfigContext.Provider value={config}>
<RpkiIndicator route={route} />
</ConfigContext.Provider>
);
expect(screen.getByText('RPKI Unknown')).toBeInTheDocument();
});
/**
* Test rendering the RpkiIndicator component with
* an rpki not checked route.
*/
test('renders RpkiIndicator with a not checked route', () => {
// Render the RpkiIndicator component for a not checked prefix
const route = {
bgp: {
large_communities: [
[1234, 1111, 10],
],
},
};
render(
<ConfigContext.Provider value={config}>
<RpkiIndicator route={route} />
</ConfigContext.Provider>
);
expect(screen.getByText('RPKI Not Checked')).toBeInTheDocument();
});
/**
* Test rendering the RpkiIndicator component with an
* rpki invalid route.
*/
test('renders RpkiIndicator with an invalid route', () => {
// Render the RpkiIndicator component for an invalid prefix
const route = {
bgp: {
large_communities: [
[1234, 1111, 100],
],
},
};
render(
<ConfigContext.Provider value={config}>
<RpkiIndicator route={route} />
</ConfigContext.Provider>
);
expect(screen.getByText('RPKI Invalid')).toBeInTheDocument();
});

View File

@ -40,7 +40,7 @@ const initialState = {
asns: {}, // Map ASNs to routeservers (for future use)
};
const ConfigContext = createContext(null);
export const ConfigContext = createContext(null);
export const useConfig = () => useContext(ConfigContext);
export const ConfigProvider = ({children}) => {