The open and composable observability and data visualization platform. Visualize metrics, logs, and traces from multiple sources like Prometheus, Loki, Elasticsearch, InfluxDB, Postgres and many more.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
grafana/public/app/core/components/NavBar/utils.test.ts

265 lines
7.3 KiB

import { Location } from 'history';
import { GrafanaConfig, locationUtil, NavModelItem } from '@grafana/data';
import { ContextSrv, setContextSrv } from 'app/core/services/context_srv';
import { enrichConfigItems, getActiveItem, isMatchOrChildMatch, isSearchActive } from './utils';
jest.mock('../../app_events', () => ({
publish: jest.fn(),
}));
describe('enrichConfigItems', () => {
let mockItems: NavModelItem[];
const mockLocation: Location<unknown> = {
hash: '',
pathname: '/',
search: '',
state: '',
};
beforeEach(() => {
mockItems = [
{
id: 'profile',
text: 'Profile',
hideFromMenu: true,
},
{
id: 'help',
text: 'Help',
hideFromMenu: true,
},
];
});
it('does not add a sign in item if a user signed in', () => {
const contextSrv = new ContextSrv();
contextSrv.user.isSignedIn = false;
setContextSrv(contextSrv);
const enrichedConfigItems = enrichConfigItems(mockItems, mockLocation);
const signInNode = enrichedConfigItems.find((item) => item.id === 'sign-in');
expect(signInNode).toBeDefined();
});
it('adds a sign in item if a user is not signed in', () => {
const contextSrv = new ContextSrv();
contextSrv.user.isSignedIn = true;
setContextSrv(contextSrv);
const enrichedConfigItems = enrichConfigItems(mockItems, mockLocation);
const signInNode = enrichedConfigItems.find((item) => item.id === 'sign-in');
expect(signInNode).toBeDefined();
});
it('does not add an org switcher to the profile node if there is 1 org', () => {
const contextSrv = new ContextSrv();
contextSrv.user.orgCount = 1;
setContextSrv(contextSrv);
const enrichedConfigItems = enrichConfigItems(mockItems, mockLocation);
const profileNode = enrichedConfigItems.find((item) => item.id === 'profile');
expect(profileNode!.children).toBeUndefined();
});
it('adds an org switcher to the profile node if there is more than 1 org', () => {
const contextSrv = new ContextSrv();
contextSrv.user.orgCount = 2;
setContextSrv(contextSrv);
const enrichedConfigItems = enrichConfigItems(mockItems, mockLocation);
const profileNode = enrichedConfigItems.find((item) => item.id === 'profile');
expect(profileNode!.children).toContainEqual(
expect.objectContaining({
text: 'Switch organization',
})
);
});
it('enhances the help node with extra child links', () => {
const contextSrv = new ContextSrv();
setContextSrv(contextSrv);
const enrichedConfigItems = enrichConfigItems(mockItems, mockLocation);
const helpNode = enrichedConfigItems.find((item) => item.id === 'help');
expect(helpNode!.children).toContainEqual(
expect.objectContaining({
text: 'Documentation',
})
);
expect(helpNode!.children).toContainEqual(
expect.objectContaining({
text: 'Support',
})
);
expect(helpNode!.children).toContainEqual(
expect.objectContaining({
text: 'Community',
})
);
expect(helpNode!.children).toContainEqual(
expect.objectContaining({
text: 'Keyboard shortcuts',
})
);
});
});
describe('isMatchOrChildMatch', () => {
const mockChild: NavModelItem = {
text: 'Child',
url: '/dashboards/child',
};
const mockItemToCheck: NavModelItem = {
text: 'Dashboards',
url: '/dashboards',
children: [mockChild],
};
it('returns true if the itemToCheck is an exact match with the searchItem', () => {
const searchItem = mockItemToCheck;
expect(isMatchOrChildMatch(mockItemToCheck, searchItem)).toBe(true);
});
it('returns true if the itemToCheck has a child that matches the searchItem', () => {
const searchItem = mockChild;
expect(isMatchOrChildMatch(mockItemToCheck, searchItem)).toBe(true);
});
it('returns false otherwise', () => {
const searchItem: NavModelItem = {
text: 'No match',
url: '/noMatch',
};
expect(isMatchOrChildMatch(mockItemToCheck, searchItem)).toBe(false);
});
});
describe('getActiveItem', () => {
const mockNavTree: NavModelItem[] = [
{
text: 'Item',
url: '/item',
},
{
text: 'Item with query param',
url: '/itemWithQueryParam?foo=bar',
},
{
text: 'Item after subpath',
url: '/subUrl/itemAfterSubpath',
},
{
text: 'Item with children',
url: '/itemWithChildren',
children: [
{
text: 'Child',
url: '/child',
},
],
},
{
text: 'Alerting item',
url: '/alerting/list',
},
{
text: 'Base',
url: '/',
},
{
text: 'Starred',
url: '/dashboards?starred',
id: 'starred',
},
{
text: 'Dashboards',
url: '/dashboards',
},
{
text: 'More specific dashboard',
url: '/d/moreSpecificDashboard',
},
];
beforeEach(() => {
locationUtil.initialize({
config: { appSubUrl: '/subUrl' } as GrafanaConfig,
getVariablesUrlParams: () => ({}),
getTimeRangeForUrl: () => ({ from: 'now-7d', to: 'now' }),
});
});
it('returns an exact match at the top level', () => {
const mockPathName = '/item';
expect(getActiveItem(mockNavTree, mockPathName)).toEqual({
text: 'Item',
url: '/item',
});
});
it('returns an exact match ignoring root subpath', () => {
const mockPathName = '/itemAfterSubpath';
expect(getActiveItem(mockNavTree, mockPathName)).toEqual({
text: 'Item after subpath',
url: '/subUrl/itemAfterSubpath',
});
});
it('returns an exact match ignoring query params', () => {
const mockPathName = '/itemWithQueryParam?bar=baz';
expect(getActiveItem(mockNavTree, mockPathName)).toEqual({
text: 'Item with query param',
url: '/itemWithQueryParam?foo=bar',
});
});
it('returns an exact child match', () => {
const mockPathName = '/child';
expect(getActiveItem(mockNavTree, mockPathName)).toEqual({
text: 'Child',
url: '/child',
});
});
it('returns the alerting link if the pathname is an alert notification', () => {
const mockPathName = '/alerting/notification/foo';
expect(getActiveItem(mockNavTree, mockPathName)).toEqual({
text: 'Alerting item',
url: '/alerting/list',
});
});
it('returns the dashboards route link if the pathname starts with /d/', () => {
const mockPathName = '/d/foo';
expect(getActiveItem(mockNavTree, mockPathName)).toEqual({
text: 'Dashboards',
url: '/dashboards',
});
});
it('returns a more specific link if one exists', () => {
const mockPathName = '/d/moreSpecificDashboard';
expect(getActiveItem(mockNavTree, mockPathName)).toEqual({
text: 'More specific dashboard',
url: '/d/moreSpecificDashboard',
});
});
});
describe('isSearchActive', () => {
it('returns true if the search query parameter is "open"', () => {
const mockLocation = {
hash: '',
pathname: '/',
search: '?search=open',
state: '',
};
expect(isSearchActive(mockLocation)).toBe(true);
});
it('returns false if the search query parameter is missing', () => {
const mockLocation = {
hash: '',
pathname: '/',
search: '',
state: '',
};
expect(isSearchActive(mockLocation)).toBe(false);
});
});