Mo.
Mo.

Reputation: 27513

How to confirm in Cypress that opnseadragon image is loaded?

I am writing Unit Test for openseadragon react component in Cypress. Is there an option in opneseadragon to know the image is loaded.

React component is

const { DEV } = import.meta.env;

interface OpenSeaDragonImageProps {
  tileSourcesUrl: string;
}

const OpenSeaDragonImage = ({ tileSourcesUrl }: OpenSeaDragonImageProps) => {
  const viewerRef = useRef<OpenSeadragon.Viewer | null>(null);

  useEffect(() => {
    viewerRef.current = OpenSeadragon({
      id: "osdviewer",
      tileSources: tileSourcesUrl,
      zoomInButton: "navControlZoomIn",
      zoomOutButton: "navControlZoomOut",
      homeButton: "navControlReset",
    });

    if (window.Cypress && DEV) {
      window.osdViewer = viewerRef.current;
    }

    return () => viewerRef.current?.destroy();
  }, [tileSourcesUrl]);

  return (
    <div className={styles.osd}>
      <div id="osdviewer" className={styles.osdViewer} />

      <Stack spacing={4} className={styles.nav}>
        <ButtonGroup variant="text">
          <Button className={styles.navButton}>
            <NoGrid />
          </Button>
        </ButtonGroup>

        <ButtonGroup variant="text">
          <Button id="navControlReset" className={styles.navButton}>
            <Reset className={styles.navButtonIcon} />
          </Button>
        </ButtonGroup>

        <ButtonGroup id="navControl" orientation="vertical" variant="text">
          <Button id="navControlZoomIn" className={styles.navButton}>
            <ZoomIn className={styles.navButtonIcon} />
          </Button>
          <Button id="navControlZoomOut" className={styles.navButton}>
            <ZoomOut className={styles.navButtonIcon} />
          </Button>
        </ButtonGroup>
      </Stack>
    </div>
  );
};

export default OpenSeaDragonImage;

Here is the current test code.

import { Viewer } from "openseadragon";
import OpenSeaDragonImage from "./OpenSeaDragonImage";

declare global {
  interface Window {
    osdViewer: Viewer;
  }
}

context(OpenSeaDragonImage.name, () => {
  describe("OpenSeaDragon view", () => {
    beforeEach(() => {
      cy.mount(
        <OpenSeaDragonImage tileSourcesUrl="https://openseadragon.github.io/example-images/highsmith/highsmith.dzi" />
      );
      cy.get(".openseadragon-container").should("exist");
    });

    it("Should OSD view zoom-in with custom button", () => {
      cy.window().then((window) => {
        expect(window.osdViewer.viewport.getZoom()).to.equal(1);

        window.osdViewer.addHandler("open", function () {
          cy.get("#navControlZoomIn").as("zoomIn");
          cy.get("@zoomIn").click();
          cy.get("@zoomIn").then(() => {
            expect(window.osdViewer.viewport.getZoom()).to.equal(2);
          });
        });
      });
    });

    it("Should OSD view zoom-out with custom button", () => {
      cy.window().then((window) => {
        cy.get("#navControlZoomIn").dblclick();

        window.osdViewer.addHandler("open", function () {
          cy.get("#navControlZoomOut").as("zoomOut");
          cy.get("@zoomOut").click();
          cy.get("@zoomOut").then(() => {
            expect(window.osdViewer.viewport.getZoom()).to.equal(2);
          });
        });
      });
    });

    it("Should OSD view reset view in custom button", () => {
      cy.window().then((window) => {
        cy.get("#navControlZoomIn").dblclick();

        window.osdViewer.addHandler("open", function () {
          cy.get("#navControlReset").as("viewReset");
          cy.get("@viewReset").click();
          cy.get("@viewReset").then(() => {
            expect(window.osdViewer.viewport.getZoom()).to.equal(1);
          });
        });
      });
    });
  });
});

Images are not loaded while testing zoom button and other tests.

Are there solution for finding image is loaded to call test ?

Upvotes: 0

Views: 72

Answers (1)

iangilman
iangilman

Reputation: 2174

You want the fully-loaded-change event. Something like this:

function whenFullyLoaded(tiledImage, callback) {
  if (tiledImage.getFullyLoaded()) {
    setTimeout(callback, 1); // So both paths are asynchronous
  } else {
    tiledImage.addOnceHandler('fully-loaded-change', function() {
      callback(); // Calling it this way keeps the arguments consistent (if we passed callback into addOnceHandler it would get an event on this path but not on the setTimeout path above)
    });
  }
}

whenFullyLoaded(viewer.world.getItemAt(0), function() {
  // Success!
});

Upvotes: 0

Related Questions