Skip to content

Commit

Permalink
Guided Tour: add unit tests for components and utils
Browse files Browse the repository at this point in the history
  • Loading branch information
sahil143 committed Jul 22, 2020
1 parent 1d985be commit 8759b1f
Show file tree
Hide file tree
Showing 6 changed files with 217 additions and 2 deletions.
2 changes: 1 addition & 1 deletion frontend/.vscode/settings.json
Expand Up @@ -22,7 +22,7 @@
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact", "json", "graphql"],
"eslint.enable": true,
"javascript.validate.enable": false,
"debug.node.autoAttach": "on",
"debug.node.autoAttach": "off",
"typescript.tsdk": "node_modules/typescript/lib",
"search.exclude": {
"**/node_modules": true,
Expand Down
@@ -0,0 +1,17 @@
import * as React from 'react';
import { shallow } from 'enzyme';
import GuidedTourMastheadTrigger from '../GuidedTourMastheadTrigger';

describe('GuidedTourMastheadTrigger', () => {
it('should render button when tour is available', () => {
spyOn(React, 'useContext').and.returnValue({ tour: { steps: [] } });
const wrapper = shallow(<GuidedTourMastheadTrigger />);
expect(wrapper.find('button').exists()).toBeTruthy();
});

it('should render null when tour is not available', () => {
spyOn(React, 'useContext').and.returnValue({ tour: null });
const wrapper = shallow(<GuidedTourMastheadTrigger />);
expect(wrapper.isEmptyRender()).toBeTruthy();
});
});
@@ -0,0 +1,23 @@
import * as React from 'react';
import { shallow } from 'enzyme';
import TourStepComponent from '../TourStepComponent';
import { Popover } from '@console/shared';
import { Modal } from '@patternfly/react-core';
import { Spotlight } from '../Spotlight';

describe('TourStepComponent', () => {
it('should render Modal if no selector is present', () => {
const wrapper = shallow(<TourStepComponent heading="heading" content="content" />);
expect(wrapper.find(Popover).exists()).toBeFalsy();
expect(wrapper.find(Modal).exists()).toBeTruthy();
});

it('should render Popover with Spotlight id selector is present', () => {
const wrapper = shallow(
<TourStepComponent heading="heading" content="content" selector="a" step={1} />,
);
expect(wrapper.find(Modal).exists()).toBeFalsy();
expect(wrapper.find(Popover).exists()).toBeTruthy();
expect(wrapper.find(Spotlight).exists()).toBeTruthy();
});
});
@@ -0,0 +1,120 @@
import * as redux from 'react-redux';
import * as plugins from '@console/plugin-sdk';
import { testHook } from '@console/shared/src/test-utils/hooks-utils';
import { TourState, tourReducer, useTourValuesForContext } from '../tour-context';
import { TourActions } from '../const';
import { TourDataType } from '../type';

describe('guided-tour-context', () => {
describe('tour-reducer', () => {
let mockState: TourState;
beforeEach(() => {
mockState = { closeTour: false, startTour: false, completedTour: false, stepNumber: 2 };
});

it('should return startTour as true for StartAction', () => {
const result = tourReducer(mockState, TourActions.start);
expect(result).toEqual({
startTour: true,
closeTour: false,
completedTour: false,
stepNumber: 0,
});
});

it('should return increment in stepNumber for next action', () => {
const result = tourReducer(mockState, TourActions.next);
expect(result.stepNumber).toEqual(mockState.stepNumber + 1);
});

it('should return decrease in stepNumber for back action', () => {
const result = tourReducer(mockState, TourActions.back);
expect(result.stepNumber).toEqual(mockState.stepNumber - 1);
});

it('should return closeTour as true for pause action', () => {
const result = tourReducer(mockState, TourActions.pause);
expect(result.closeTour).toBeTruthy();
expect(result.stepNumber).toEqual(mockState.stepNumber);
});

it('should return closeTour as false for resume action', () => {
const result = tourReducer({ ...mockState, closeTour: true }, TourActions.resume);
expect(result.closeTour).toBeFalsy();
expect(result.stepNumber).toEqual(mockState.stepNumber);
});

it('should return completedTour as true for complete action', () => {
const result = tourReducer(mockState, TourActions.complete);
expect(result).toEqual({
startTour: false,
closeTour: false,
completedTour: true,
stepNumber: 0,
});
});
});

describe('guided-tour-context-hook', () => {
let mockTour: TourDataType;
let mockTourExtension;
beforeEach(() => {
mockTour = {
intro: { heading: 'a', content: 'c' },
steps: [
{ flags: ['A', 'B'], heading: 'step1', content: 'step1 content' },
{ flags: ['A'], heading: 'g', content: 'h' },
],
end: { heading: 'b', content: 'd' },
};

mockTourExtension = [
{
type: 'GuidedTour',
properties: {
perspective: 'dev',
tour: mockTour,
},
},
];
});

it('should return context values from the hook', () => {
spyOn(redux, 'useSelector').and.returnValues('dev', { A: true, B: false }, 'dev', {
A: true,
B: false,
});
spyOn(plugins, 'useExtensions').and.returnValue(mockTourExtension);
testHook(() => {
const contextValue = useTourValuesForContext();
const { tourState, tour, totalSteps } = contextValue;
expect(tourState).toEqual({
startTour: true,
completedTour: false,
closeTour: false,
stepNumber: 0,
});
expect(tour).toEqual({
...mockTour,
steps: [{ flags: ['A'], heading: 'g', content: 'h' }],
});
expect(totalSteps).toEqual(1);
});
});

it('should return tour null from the hook', () => {
spyOn(redux, 'useSelector').and.returnValues('dev', { A: true, B: false }, 'dev', {
A: true,
B: false,
});
spyOn(plugins, 'useExtensions').and.returnValue([]);
testHook(() => {
const contextValue = useTourValuesForContext();
const { tourState, tour, totalSteps } = contextValue;
expect(tourState).toEqual(undefined);
expect(tour).toEqual(null);
expect(totalSteps).toEqual(undefined);
});
});
});
});
@@ -0,0 +1,55 @@
import { Step } from '../type';
import { filterTourBasedonPermissionAndFlag } from '../utils';
import { FeatureState } from '@console/internal/reducers/features';

describe('guided-tour-utils', () => {
it('should return steps that has access true', () => {
const steps: Step[] = [
{
access: () => false,
heading: 'heading1',
content: 'content1',
},
{
access: () => true,
heading: 'heading2',
content: 'content2',
},
{
access: () => false,
heading: 'heading2',
content: 'content2',
},
];
const result = filterTourBasedonPermissionAndFlag(steps, {} as FeatureState);
expect(result.length).toBe(1);
expect(result[0].heading).toBe('heading2');
});

it('should filter out even if one of the flags for a step is false', () => {
const steps: Step[] = [
{
flags: ['A', 'B'],
heading: 'heading1',
content: 'content1',
},
{
flags: ['A', 'C'],
heading: 'heading2',
content: 'content2',
},
{
flags: ['B'],
heading: 'heading2',
content: 'content2',
},
];
const result = filterTourBasedonPermissionAndFlag(steps, {
A: true,
B: false,
C: true,
} as any);
expect(result.length).toBe(1);
expect(result[0].heading).toBe('heading2');
});
});
Expand Up @@ -18,7 +18,7 @@ export const tourReducer = (state: TourState, action: TourActions) => {
const { stepNumber } = state;
switch (action) {
case TourActions.start:
return { ...state, startTour: true, completedTour: false };
return { ...state, startTour: true, completedTour: false, stepNumber: 0 };
case TourActions.next:
return {
...state,
Expand Down

0 comments on commit 8759b1f

Please sign in to comment.