172 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			172 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
import {
 | 
						|
  transformStagesForPathNavigation,
 | 
						|
  medianTimeToParsedSeconds,
 | 
						|
  formatMedianValues,
 | 
						|
  filterStagesByHiddenStatus,
 | 
						|
  buildCycleAnalyticsInitialData,
 | 
						|
} from '~/cycle_analytics/utils';
 | 
						|
import {
 | 
						|
  selectedStage,
 | 
						|
  allowedStages,
 | 
						|
  stageMedians,
 | 
						|
  pathNavIssueMetric,
 | 
						|
  rawStageMedians,
 | 
						|
} from './mock_data';
 | 
						|
 | 
						|
describe('Value stream analytics utils', () => {
 | 
						|
  describe('transformStagesForPathNavigation', () => {
 | 
						|
    const stages = allowedStages;
 | 
						|
    const response = transformStagesForPathNavigation({
 | 
						|
      stages,
 | 
						|
      medians: stageMedians,
 | 
						|
      selectedStage,
 | 
						|
    });
 | 
						|
 | 
						|
    describe('transforms the data as expected', () => {
 | 
						|
      it('returns an array of stages', () => {
 | 
						|
        expect(Array.isArray(response)).toBe(true);
 | 
						|
        expect(response.length).toBe(stages.length);
 | 
						|
      });
 | 
						|
 | 
						|
      it('selects the correct stage', () => {
 | 
						|
        const selected = response.filter((stage) => stage.selected === true)[0];
 | 
						|
 | 
						|
        expect(selected.title).toBe(selectedStage.title);
 | 
						|
      });
 | 
						|
 | 
						|
      it('includes the correct metric for the associated stage', () => {
 | 
						|
        const issue = response.filter((stage) => stage.name === 'issue')[0];
 | 
						|
 | 
						|
        expect(issue.metric).toBe(pathNavIssueMetric);
 | 
						|
      });
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  describe('medianTimeToParsedSeconds', () => {
 | 
						|
    it.each`
 | 
						|
      value      | result
 | 
						|
      ${1036800} | ${'1w'}
 | 
						|
      ${259200}  | ${'3d'}
 | 
						|
      ${172800}  | ${'2d'}
 | 
						|
      ${86400}   | ${'1d'}
 | 
						|
      ${1000}    | ${'16m'}
 | 
						|
      ${61}      | ${'1m'}
 | 
						|
      ${59}      | ${'<1m'}
 | 
						|
      ${0}       | ${'-'}
 | 
						|
    `('will correctly parse $value seconds into $result', ({ value, result }) => {
 | 
						|
      expect(medianTimeToParsedSeconds(value)).toBe(result);
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  describe('formatMedianValues', () => {
 | 
						|
    const calculatedMedians = formatMedianValues(rawStageMedians);
 | 
						|
 | 
						|
    it('returns an object with each stage and their median formatted for display', () => {
 | 
						|
      rawStageMedians.forEach(({ id, value }) => {
 | 
						|
        expect(calculatedMedians).toMatchObject({ [id]: medianTimeToParsedSeconds(value) });
 | 
						|
      });
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  describe('filterStagesByHiddenStatus', () => {
 | 
						|
    const hiddenStages = [{ title: 'three', hidden: true }];
 | 
						|
    const visibleStages = [
 | 
						|
      { title: 'one', hidden: false },
 | 
						|
      { title: 'two', hidden: false },
 | 
						|
    ];
 | 
						|
    const mockStages = [...visibleStages, ...hiddenStages];
 | 
						|
 | 
						|
    it.each`
 | 
						|
      isHidden     | result
 | 
						|
      ${false}     | ${visibleStages}
 | 
						|
      ${undefined} | ${hiddenStages}
 | 
						|
      ${true}      | ${hiddenStages}
 | 
						|
    `('with isHidden=$isHidden returns matching stages', ({ isHidden, result }) => {
 | 
						|
      expect(filterStagesByHiddenStatus(mockStages, isHidden)).toEqual(result);
 | 
						|
    });
 | 
						|
  });
 | 
						|
 | 
						|
  describe('buildCycleAnalyticsInitialData', () => {
 | 
						|
    let res = null;
 | 
						|
    const projectId = '5';
 | 
						|
    const createdAfter = '2021-09-01';
 | 
						|
    const createdBefore = '2021-11-06';
 | 
						|
    const groupId = '146';
 | 
						|
    const groupPath = 'fake-group';
 | 
						|
    const fullPath = 'fake-group/fake-project';
 | 
						|
    const labelsPath = '/fake-group/fake-project/-/labels.json';
 | 
						|
    const milestonesPath = '/fake-group/fake-project/-/milestones.json';
 | 
						|
    const requestPath = '/fake-group/fake-project/-/value_stream_analytics';
 | 
						|
 | 
						|
    const rawData = {
 | 
						|
      projectId,
 | 
						|
      createdBefore,
 | 
						|
      createdAfter,
 | 
						|
      fullPath,
 | 
						|
      requestPath,
 | 
						|
      labelsPath,
 | 
						|
      milestonesPath,
 | 
						|
      groupId,
 | 
						|
      groupPath,
 | 
						|
    };
 | 
						|
 | 
						|
    describe('with minimal data', () => {
 | 
						|
      beforeEach(() => {
 | 
						|
        res = buildCycleAnalyticsInitialData(rawData);
 | 
						|
      });
 | 
						|
 | 
						|
      it('sets the projectId', () => {
 | 
						|
        expect(res.projectId).toBe(parseInt(projectId, 10));
 | 
						|
      });
 | 
						|
 | 
						|
      it('sets the date range', () => {
 | 
						|
        expect(res.createdBefore).toEqual(new Date(createdBefore));
 | 
						|
        expect(res.createdAfter).toEqual(new Date(createdAfter));
 | 
						|
      });
 | 
						|
 | 
						|
      it('sets the endpoints', () => {
 | 
						|
        const { endpoints } = res;
 | 
						|
        expect(endpoints.fullPath).toBe(fullPath);
 | 
						|
        expect(endpoints.requestPath).toBe(requestPath);
 | 
						|
        expect(endpoints.labelsPath).toBe(labelsPath);
 | 
						|
        expect(endpoints.milestonesPath).toBe(milestonesPath);
 | 
						|
        expect(endpoints.groupId).toBe(parseInt(groupId, 10));
 | 
						|
        expect(endpoints.groupPath).toBe(groupPath);
 | 
						|
      });
 | 
						|
 | 
						|
      it('returns null when there is no stage', () => {
 | 
						|
        expect(res.selectedStage).toBeNull();
 | 
						|
      });
 | 
						|
 | 
						|
      it('returns false for missing features', () => {
 | 
						|
        expect(res.features.cycleAnalyticsForGroups).toBe(false);
 | 
						|
      });
 | 
						|
    });
 | 
						|
 | 
						|
    describe('with a stage set', () => {
 | 
						|
      const jsonStage = '{"id":"fakeStage","title":"fakeStage"}';
 | 
						|
 | 
						|
      it('parses the selectedStage data', () => {
 | 
						|
        res = buildCycleAnalyticsInitialData({ ...rawData, stage: jsonStage });
 | 
						|
 | 
						|
        const { selectedStage: stage } = res;
 | 
						|
 | 
						|
        expect(stage.id).toBe('fakeStage');
 | 
						|
        expect(stage.title).toBe('fakeStage');
 | 
						|
      });
 | 
						|
    });
 | 
						|
 | 
						|
    describe('with features set', () => {
 | 
						|
      const fakeFeatures = { cycleAnalyticsForGroups: true };
 | 
						|
 | 
						|
      it('sets the feature flags', () => {
 | 
						|
        res = buildCycleAnalyticsInitialData({
 | 
						|
          ...rawData,
 | 
						|
          gon: { licensed_features: fakeFeatures },
 | 
						|
        });
 | 
						|
        expect(res.features).toEqual(fakeFeatures);
 | 
						|
      });
 | 
						|
    });
 | 
						|
  });
 | 
						|
});
 |