swimlane/ngx-ui

View on GitHub
projects/swimlane/ngx-ui/src/lib/components/calendar/calender.component.spec.ts

Summary

Maintainability
F
3 days
Test Coverage
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { NO_ERRORS_SCHEMA } from '@angular/core';

import { MomentModule } from 'ngx-moment';
import moment from 'moment-timezone';

import { PipesModule } from '../../pipes/pipes.module';
import { CalendarView } from './calendar-view.enum';
import { CalendarComponent } from './calendar.component';
import { CalendarDay } from './calendar-day.interface';

(moment as any).suppressDeprecationWarnings = true;

describe('CalendarComponent', () => {
  let component: CalendarComponent;
  let fixture: ComponentFixture<CalendarComponent>;

  beforeEach(waitForAsync(() => {
    TestBed.configureTestingModule({
      declarations: [CalendarComponent],
      schemas: [NO_ERRORS_SCHEMA],
      imports: [MomentModule, PipesModule],
      teardown: { destroyAfterEach: false }
    }).compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(CalendarComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  describe('changeViews', () => {
    it('should change view to month if date', () => {
      component.currentView = CalendarView.Date;
      component.changeViews();
      expect(component.currentView).toBe(CalendarView.Month);
    });

    it('should change view to year if month', () => {
      component.currentView = CalendarView.Month;
      component.changeViews();
      expect(component.currentView).toBe(CalendarView.Year);
    });

    it('should change view to min if year', () => {
      component.currentView = CalendarView.Year;
      component.changeViews();
      expect(component.currentView).toBe(component.minView);
    });
  });

  describe('validateView', () => {
    it('should set minView as date if minView is not date, month, or year', () => {
      component.minView = 'test' as any;
      component.validateView();
      expect(component.minView).toBe(CalendarView.Date);
    });

    it('should set defaultView to minView if defaultView is smaller than than minView', () => {
      component.minView = CalendarView.Month;
      component.defaultView = CalendarView.Date;
      component.validateView();
      expect(component.defaultView).toBe(component.minView);
    });
  });

  describe('isDayActive', () => {
    it('should return true if date matches day value', () => {
      component.value = new Date();
      expect(component.isDayActive(moment())).toBe(true);
    });

    it('should return false if date does not match day value', () => {
      const now = new Date();
      now.setFullYear(now.getFullYear() - 1);
      component.value = now;
      expect(component.isDayActive(moment())).toBe(false);
    });
  });

  describe('isMonthActive', () => {
    it('should return true if same month of year', () => {
      component.value = new Date();
      expect(component.isMonthActive(moment().format('MMMM'))).toBe(true);
    });

    it('should return false if not same month of year', () => {
      const now = new Date();
      now.setDate(1);
      now.setMonth(now.getMonth() - 1);
      component.value = now;
      expect(component.isMonthActive(moment().format('MMMM'))).toBe(false);
    });
  });

  describe('isCurrentMonth', () => {
    it('should return true if month is same as current', () => {
      component.value = new Date();
      component.ngOnInit();
      expect(component.isCurrentMonth(moment().format('MMMM'))).toBe(true);
    });

    it('should return false if month is not same as current', () => {
      const now = new Date();
      now.setDate(1);
      now.setMonth(now.getMonth() - 1);
      component.value = now;
      component.ngOnInit();
      expect(component.isCurrentMonth(moment().format('MMMM'))).toBe(false);
    });
  });

  describe('isYearActive', () => {
    it('should return true if year is same as value', () => {
      component.value = new Date();
      expect(component.isYearActive(new Date().getFullYear())).toBe(true);
    });

    it('should return false if year is not same as value', () => {
      const now = new Date();
      now.setFullYear(now.getFullYear() - 1);
      component.value = now;
      expect(component.isYearActive(new Date().getFullYear())).toBe(false);
    });
  });

  describe('isCurrentYear', () => {
    it('should return true if year is same as current', () => {
      component.value = new Date();
      component.ngOnInit();
      expect(component.isCurrentYear(new Date().getFullYear())).toBe(true);
    });

    it('should return false if year is not same as current', () => {
      const now = new Date();
      now.setFullYear(now.getFullYear() - 1);
      component.value = now;
      component.ngOnInit();
      expect(component.isCurrentYear(new Date().getFullYear())).toBe(false);
    });
  });

  describe('isDisabled', () => {
    it('should return true if disabled', () => {
      component.disabled = true;
      expect(component.isDisabled(undefined, undefined)).toBe(true);
    });

    it('should return false if value undefined', () => {
      expect(component.isDisabled(undefined, undefined)).toBe(false);
    });

    it('should return true if date is before min', () => {
      component.minDate = new Date();
      component.minDate.setMonth(2);
      expect(component.isDisabled('January', 'month')).toBe(true);
    });

    it('should return true if date is after max', () => {
      const date = moment().add(1, 'years');
      component.maxDate = new Date();
      expect(component.isDisabled(date.format('YYYY'), 'year')).toBe(true);
    });

    it('should return false if invalid type', () => {
      expect(component.isDisabled(moment().format('YYYY'), 'test')).toBe(false);
    });
  });

  describe('onDayClick', () => {
    beforeEach(() => {
      component.weeks = [];
    });

    it('should set value and set weeks of month', () => {
      component.onDayClick({
        date: moment(),
        nextMonth: true,
        prevMonth: true
      } as any);
      expect(component.weeks.length).toBeGreaterThan(0);
    });

    it('should set value but not set weeks of month', () => {
      component.onDayClick({
        date: moment()
      } as any);
      expect(component.weeks.length).toBe(0);
    });
  });

  describe('onMonthClick', () => {
    beforeEach(() => {
      component.weeks = [];
    });

    it('should set value and set weeks of month', () => {
      component.minView = CalendarView.Year;
      component.onMonthClick(moment().format('MMMM'));
      expect(component.weeks.length).toBeGreaterThan(0);
    });

    it('should set value but not set weeks of month', () => {
      component.minView = CalendarView.Month;
      component.onMonthClick(moment().format('MMMM'));
      expect(component.weeks.length).toBe(0);
    });
  });

  describe('onYearClick', () => {
    beforeEach(() => {
      component.weeks = [];
    });

    it('should set value and set weeks of month', () => {
      component.minView = CalendarView.Month;
      component.onYearClick(new Date().getFullYear());
      expect(component.weeks.length).toBeGreaterThan(0);
    });

    it('should set value but not set weeks of month', () => {
      component.minView = CalendarView.Year;
      component.onYearClick(new Date().getFullYear());
      expect(component.weeks.length).toBe(0);
    });
  });

  describe('pagination', () => {
    beforeEach(() => {
      component.focusDate = moment('5/1/1975');
      component.startYear = new Date().getFullYear();
      component.weeks = [];
    });

    describe('month', () => {
      describe('prevMonth', () => {
        it('should set value to previous month', () => {
          const month = component.focusDate.get('month');
          component.prevMonth();
          expect(component.focusDate.get('month')).toBe(month - 1);
          expect(component.weeks.length).toBeGreaterThan(0);
        });
      });

      describe('nextMonth', () => {
        it('should set value to next month', () => {
          const month = component.focusDate.get('month');
          component.nextMonth();
          expect(component.focusDate.get('month')).toBe(month < 11 ? month + 1 : 0);
          expect(component.weeks.length).toBeGreaterThan(0);
        });
      });
    });

    describe('year', () => {
      describe('prevYear', () => {
        it('should set value to previous year', () => {
          const year = component.focusDate.get('year');
          component.prevYear();
          expect(component.focusDate.get('year')).toBe(year - 1);
        });
      });

      describe('nextYear', () => {
        it('should set value to next year', () => {
          const year = component.focusDate.get('year');
          component.nextYear();
          expect(component.focusDate.get('year')).toBe(year + 1);
        });
      });
    });

    describe('twoDecades', () => {
      describe('prevTwoDecades', () => {
        it('should set startYear to two decades ago', () => {
          const startYear = component.startYear;
          component.prevTwoDecades();
          expect(component.startYear).toBe(startYear - 20);
        });
      });

      describe('nextTwoDecades', () => {
        it('should set startYear to two decades in the future', () => {
          const startYear = component.startYear;
          component.nextTwoDecades();
          expect(component.startYear).toBe(startYear + 20);
        });
      });
    });
  });

  describe('writeValue', () => {
    it('should write to value if valid and different', () => {
      const now = new Date();
      const newDate = new Date();
      now.setDate(now.getDate() - 1);
      component.value = now;
      component.writeValue(newDate);
      expect(component.focusDate.isSame(newDate)).toBe(true);
    });

    it('should not write new value if invalid', () => {
      const date = 'test';
      component.value = new Date();
      component.writeValue(date);
      expect(component.focusDate.isSame(date)).toBe(false);
    });
  });

  describe('registerOnChange', () => {
    it('should register new on change callback fn', done => {
      component.value = new Date();
      component.registerOnChange((v: Date) => {
        expect(v).toEqual(now);
        done();
      });

      const now = new Date();
      now.setDate(now.getDate() + 1);
      component.value = now;
    });
  });

  describe('Time Functions', () => {
    it('should update hour correctly', () => {
      component.range = { startDate: new Date(), endDate: undefined };
      component.startAmPmVal = 'PM';
      component.startHour = 5;
      component.hourChanged(3, 'start');
      expect(component.range?.startDate?.getHours()).toBe(15);
    });

    it('should update minute correctly', () => {
      component.range = { startDate: new Date(), endDate: undefined };
      component.startMinute = 30;
      component.minuteChanged(45, 'start');
      expect(component.range?.startDate?.getMinutes()).toBe(45);
    });

    it('should update AM/PM correctly', () => {
      component.range = { startDate: new Date(), endDate: undefined };
      component.startAmPmVal = 'AM';
      component.range?.startDate?.setHours(2);
      component.onAmPmChange('PM', 'start');
      expect(component.range?.startDate?.getHours()).toBe(14);
    });
  });

  describe('initializeTime', () => {
    it('should initialize time properties based on range start and range end', () => {
      const rangeStart = new Date('2024-04-04T10:30:00');
      const rangeEnd = new Date('2024-04-04T15:45:00');

      component.range = { startDate: rangeStart, endDate: rangeEnd };
      component.initializeTime();

      expect(component.startHour).toBe(10);
      expect(component.startMinute).toBe(30);
      expect(component.startAmPmVal).toBe('AM');

      expect(component.endHour).toBe(3);
      expect(component.endMinute).toBe(45);
      expect(component.endAmPmVal).toBe('PM');
    });

    it('should initialize time properties with default values if range start and rangeEnd are not provided', () => {
      component.initializeTime();

      expect(component.startHour).toBe(0);
      expect(component.endHour).toBe(0);
      expect(component.startMinute).toBe(0);
      expect(component.endMinute).toBe(0);
      expect(component.startAmPmVal).toBe('AM');
      expect(component.endAmPmVal).toBe('AM');
    });
  });

  describe('onDaySelectRange', () => {
    it('should set range start if both range start and range end are undefined', () => {
      const day = { date: moment('2024-04-04'), nextMonth: true, prevMonth: true } as CalendarDay;
      component.focusDate = moment('2024-04-04');
      component.range = { startDate: undefined, endDate: undefined };
      component.startHour = 10;
      component.startMinute = 30;

      component.onDaySelectRange(day);

      expect(component.range?.startDate).toEqual(new Date('2024-04-04T10:30:00'));
      expect(component.range?.endDate).toBeUndefined();
    });

    it('should set range end if range start is set and focusDate is greater than range start', () => {
      const day = { date: moment('2024-04-10'), nextMonth: true, prevMonth: true } as CalendarDay;
      component.focusDate = moment('2024-04-10');
      component.range = { startDate: new Date('2024-04-04T10:30:00'), endDate: undefined };
      component.endHour = 15;
      component.endMinute = 45;

      component.onDaySelectRange(day);

      expect(component.range?.startDate).toEqual(new Date('2024-04-04T10:30:00'));
      expect(component.range?.endDate).toEqual(new Date('2024-04-10T15:45:00'));
    });

    it('should update range start if range start is set and focusDate is less than or equal to range start', () => {
      const day = { date: moment('2024-04-01'), nextMonth: true, prevMonth: true } as CalendarDay;
      component.focusDate = moment('2024-04-01');
      component.range = { startDate: new Date('2024-04-04T10:30:00'), endDate: undefined };
      component.startHour = 8;
      component.startMinute = 15;

      component.onDaySelectRange(day);

      expect(component.range?.startDate).toEqual(new Date('2024-04-01T08:15:00'));
      expect(component.range?.endDate).toBeUndefined();
    });

    it('should reset range start and range end if both are already set', () => {
      const day = { date: moment('2024-04-04'), nextMonth: true, prevMonth: true } as CalendarDay;
      component.focusDate = moment('2024-04-04');
      component.range = { startDate: new Date('2024-04-01T08:15:00'), endDate: new Date('2024-04-10T15:45:00') };
      component.startHour = 12;
      component.startMinute = 0;

      component.onDaySelectRange(day);

      expect(component.range?.startDate).toEqual(new Date('2024-04-04T12:00:00'));
      expect(component.range?.endDate).toBeUndefined();
    });
  });
});