Iogui
Iogui

Reputation: 1698

Testing ResizeObserver events on Angular 12 with Karma and Jasmine

I'm trying to test code called by a ResizeObserver in an Angular 12 app with karma and jasmine. The code performs very well when I make a manual test by opening the app on a browser, but in my unit tests karma seems to simply ignore the ResizeObserver. Do someone knows if there is some issue on using ResizeObserver in karma/jasmine tests that prevent it from working properly?

Description of the app

I've built a simple app to isolate the problem. The core piece of code is a component that just draws a div which is being observed by a ResizeObserver. The observer stores the new div size when it is resized and the template display this info inside the own div.

The core code of the component:

@ViewChild('aDiv')
aDiv!: ElementRef;

resizeObserver!: ResizeObserver;

dimensions?: Dimensions;

constructor(private zone: NgZone) { }

ngOnInit(): void {
  const that = this;
  this.resizeObserver = new ResizeObserver(entries => {
    for (const entry of entries) {
      if(entry.target.tagName.toLowerCase() === 'div') {
        const div = entry.target as HTMLDivElement;
        that.onResize(div);
      }
    }
  });
}

ngAfterViewInit(): void {
  this.resizeObserver.observe(this.aDiv.nativeElement);
}

ngOnDestroy(): void {
  if(this.resizeObserver) {
    this.resizeObserver.disconnect();
  }
}

onResize(div: HTMLDivElement): void {
  const [width, height] = ResizableComponent.getDimensions(div);
  this.zone.run(() => {
    this.dimensions = {
      width: width,
      height: height
    }
  });
}

The template:

<div #aDiv>
  <p>My dimensions are: ({{dimensions? dimensions.width + 'px' : 'unknown'}}, {{dimensions? dimensions.height + 'px' : 'unknown'}})</p>
</div>

The jasmine/karma test that is not working:

@Component({
  template: `
    <div id="resizeMe">
      <app-resizable></app-resizable>
    </div>
  `
})
class TestResizable {
  @ViewChild(ResizableComponent)
  resizable!: ResizableComponent;
}

describe('ResizableComponent as a nested component', () => {
  let component: TestResizable;
  let fixture: ComponentFixture<TestResizable>;

  let divResizeMe: HTMLDivElement;

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [ TestResizable, ResizableComponent ]
    }).compileComponents();
  });

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

    divResizeMe = fixture.nativeElement.querySelector('#resizeMe');
  });

  it('should resize when external is resized', () => {
    divResizeMe.style.width = '200px';

    expect(component.resizable.dimensions).toBeTruthy();
    expect(component.resizable.dimensions?.width).toBe(200);
  });
});

The question:

Am I doing something wrong? Should this test be working but it isn't working because of some karma issue? Or... Am I missing something obvious and my test code is simply wrong?

If you want to play with the full code:

The code is available and working in this stackblitz (except by the unit test that is also available but not working)

I've also tried this (with no success):

it('should resize when external is resized', (done) => {
  divResizeMe.style.width = '200px';

  setTimeout(()=> {
    expect(component.resizable.dimensions).toBeTruthy();
    expect(component.resizable.dimensions?.width).toBe(200);
    done();
  }, 500);

});

And this:

it('should resize when external is resized', (done) => {
  divResizeMe.style.width = '200px';
  fixture.detectChanges();

  setTimeout(()=> {
    expect(component.resizable.dimensions).toBeTruthy();
    expect(component.resizable.dimensions?.width).toBe(200);
    done();
  }, 500);

});

Upvotes: 7

Views: 1429

Answers (0)

Related Questions