Skip to content

Timeouts/Stack Overflow when testing components that uses the Fluid component #56

@j--w

Description

@j--w

Problem

When writing an integration test for a component that contains a chart making use of the Fluid component the test seems to consistently timeout in GHA. It seems to be something to do with the ResizeObserver being used.

Workarounds

In general we've been able to work around it with using setTimeout to allow the ResizeObserver to do it's thing. Eg:

const wait = (ms) => new Promise((res) => setTimeout(res, ms));
....
await render(
      hbs`<MyChart @data={{this.data}} />`
    );
await wait(100);
assert.dom(selectors.container).exists({ count: 1 });

We've had one particularly stubborn test where the wait solution hasn't been consistent. In the end I stubbed the chart component as I wasn't actually testing any chart behavior.

It seems mocking the ResizeObserver would be a good path to follow, I did take a stab at it and the mock did seem to work to a degree but I still ended up with timeouts in Github Actions so I think I was probably missing something important.

My quick and dirty mock attempt:

class MockResizeObserver {
  static instances = [];

  constructor(callback) {
    this.callback = callback;
    this._watchedElements = emberArray();
    MockResizeObserver.instances.push(this);
  }

  observe(element) {
    this._watchedElements.addObject(element);
  }

  unobserve(element) {
    this._watchedElements.removeObject(element);
  }

  disconnect() {
    this._watchedElements = [];
  }

  static triggerResize(
    el,
    state = { contentRect: { width: 1440, height: 900 } }
  ) {
    return MockResizeObserver.forceElement(find(el), state);
  }
  static async forceElement(el, state) {
    MockResizeObserver.instances.forEach((instance) => {
      if (instance._watchedElements.includes(el)) {
        instance.callback([
          {
            target: el,
            ...state,
          },
        ]);
      }
    });
    await settled();
    await wait(0);
  }
}

export default function mockDidResize(sinon) {
  sinon.replace(MockResizeObserver, 'instances', []);
  sinon.replace(window, 'ResizeObserver', MockResizeObserver);
  return MockResizeObserver;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions