angulartypescriptunit-testingjestjsbabel-jest

How to test a getter and setter in Jest (Angular)


I am trying to test a getter / setter value after it change. All test are fine except the last one in comments.

What can I do to make this an successful test. Do I need use an Spy or something else to achieve this. Can someone point me in the right direction

Also can must I update the other tests with kind of spy or mockdata.

TS:

 export class component001 {
      isLastRecord = false;
      
      private _records: Records[];
      @Input()
      set records(value: Record[]){
        if(value) {
          this._records = value;
          this.isLastRecord = value.filter(r => r.type === 'type001').length === 1;
        }
      }
      get records(): Record[] {
        return this._records;
      }
    }

Jest:

describe("component001", () => {
  let component: Component001;
  let fixture: ComponentFixture<Component001>;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [Component001, HttpClientTestingModule]
    }).compileComponents();
  });

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

  describe('Component001', () => {     
    it('Should return true when there the count of record changes from 2 to 1 record', () => {
      let mockRecords = [
        { name: 'Barbara Gordon', type: 'type001' },
        { name: 'Cassandra Cain', type: 'type001'}
      ] as unknown as Record [];

      expect(component.isLastRecord).toBe(false);
      component.records = mockRecords;
      expect(component.isLastRecord).toBe(false);
      component.records = [mockRecords.pop()];
      expect(component.isLastRecord).toBe(true);
    });

    // it('Should return true when there the count of record changes from 1 to 2 records', () => {
    //   let mockRecords = [
    //     { name: 'Barbara Gordon', type: 'type001' }
    //   ] as unknown as Record [];

    //   expect(component.isLastRecord).toBe(false);
    //   component.Records = mockRecords;
    //   expect(component.isLastRecord).toBe(true);

    //   const newRecord = {name: 'Cassandra Cain', type: 'type001'} as unknown as Record;
    //   component.records.push(newRecord);
    //   expect(component.isLastRecord).toBe(false);
    // });

  });
})

Also I am using angular 16 with standalone components


Solution

  • We are updating dnsRecords when we should update records which has the getter and the setter.

      it('Should return true when there the count of record changes from 2 to 1 record', () => {
        let mockRecords = [
          { name: 'Barbara Gordon', type: 'type001' },
          { name: 'Cassandra Cain', type: 'type001' },
        ] as unknown as any[];
    
        expect(component.isLastRecord).toBe(false);
        component['records'] = mockRecords;
        expect(component.isLastRecord).toBe(false);
        component['records'] = [mockRecords.pop()];
        expect(component.isLastRecord).toBe(true);
      });
    

    For the second block and last test case, we are pushing an item into the array, but as you know (Arrays and Objects - are stored as memory references in JS). So pushing does not create a new memory reference, thus it is not considered as a update by the @Input, the solution is to do array destructuring and create a new instance.

      it('Should return true when there the count of record changes from 1 to 2 records', () => {
        let mockRecords = [
          { name: 'Barbara Gordon', type: 'type001' },
        ] as unknown as any[];
    
        expect(component.isLastRecord).toBe(false);
        component.records = mockRecords;
        expect(component.isLastRecord).toBe(true);
    
        const newRecord = {
          name: 'Cassandra Cain',
          type: 'type001',
        } as unknown as any;
        component.records = [...component.records, newRecord]; // update the reference of the array only then the setter will work
        expect(component.isLastRecord).toBe(false);
      });
    

    Full Code:

    describe('Component001', () => {
      it('Should return true when there the count of record changes from 2 to 1 record', () => {
        let mockRecords = [
          { name: 'Barbara Gordon', type: 'type001' },
          { name: 'Cassandra Cain', type: 'type001' },
        ] as unknown as any[];
    
        expect(component.isLastRecord).toBe(false);
        component['records'] = mockRecords;
        expect(component.isLastRecord).toBe(false);
        component['records'] = [mockRecords.pop()];
        expect(component.isLastRecord).toBe(true);
      });
    
      it('Should return true when there the count of record changes from 1 to 2 records', () => {
        let mockRecords = [
          { name: 'Barbara Gordon', type: 'type001' },
        ] as unknown as any[];
    
        expect(component.isLastRecord).toBe(false);
        component.records = mockRecords;
        expect(component.isLastRecord).toBe(true);
    
        const newRecord = {
          name: 'Cassandra Cain',
          type: 'type001',
        } as unknown as any;
        component.records = [...component.records, newRecord]; // update the reference of the array only then the setter will work
        expect(component.isLastRecord).toBe(false);
      });
    });
    

    Stackblitz Demo