Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to mock in e2e testing #1017

Closed
brianabaker opened this issue Dec 19, 2023 · 4 comments
Closed

How to mock in e2e testing #1017

brianabaker opened this issue Dec 19, 2023 · 4 comments

Comments

@brianabaker
Copy link

Hello! We're moving off of Segment analytics loaded in our window to this analytics-next library.

For Analytics testing, we do mostly RTL unit testing & also e2e testing with Cypress (e2e only for certain flows). I'm running into some issues modifying our Cypress mocks.

I'm not sure how to mock Segment to consider itself "initialized" like we used to when the code was on our window. I can see the mocked analytics when my code first loads (via console logs), but then they are overwritten (I think when Segment initializes).

This is how we used to mock, is there something i can do to replicate setting window.analytics.initialize to true?

export const stubAnalytics = (win) => {
  win.analytics = win.analytics || [];

  // stops the segment script tag from executing, which would overwrite out stubs
  win.analytics.initialize = true;

  cy.stub(analytics, "track").as("analytics.track");
};

Thanks!

@silesky
Copy link
Contributor

silesky commented Dec 19, 2023

@brianabaker

How do you initialize segment: can you share that code?

@brianabaker
Copy link
Author

brianabaker commented Dec 21, 2023

For sure. Some code is removed from here, but it's the general idea:
@silesky

// Our own Segment Tracker file -- missing a lot of the code but this is enough to get a feel I think

import { AnalyticsBrowser } from "@segment/analytics-next";

export const analytics = new AnalyticsBrowser();

export class SegmentService implements Service {
  track = (event: Event): Event => {

    analytics.track(name, underscorify(getProperties(event)));
    return event;
  };
}

// this gets called in another file 
export const getInstance = (): Tracker => {
  // `instance` here is an instance of SegmentService, our own class above!
  if (!instance) {
    const segmentWriteKey = process.env.KEY;
    const allowAnalytics = window?.doNotTrack !== true;

    analytics
      .load(
        { writeKey: `${segmentWriteKey}` },
          // i added disable: true here temporarily to try and help mock, it didn't assist.
        { integrations: { All: allowAnalytics }, disable: true },
      )
      .catch((e: Error) => console.error("Error loading Segment", e));
    instance = new SegmentService();
  }

  return instance;
};

@silesky
Copy link
Contributor

silesky commented Dec 21, 2023

@brianabaker It sounds like disable is not what you're after, since you're actually attempting to assert that analytics are being sent, correct?

From a testing pyramid perspective, I would generally recommend that you stick to using disable: true with e2e tests and test Segment via mocking the SegmentService in your regular unit tests, rather than attempting to e2e test a library that you don't 'own'. Since you're not using global analytics, there's no easy way to just stub out analytics -- and if something is not easy to mock, IMO it is a sign that something is off with either my app architecture or testing design/ strategy.

If you are determined to test our library in Cypress, I would recommend using Cypress HTTP request interception if you need that level of e2e-'ness' -- our Playwright example (see route.fulfill) should get you started on which endpoints you need to intercept. Like all HTTP Request Interception libs/code, it will probably require some trial and error.

https://github.com/segmentio/analytics-next/blob/master/packages/browser-integration-tests/src/index.test.ts

@brianabaker
Copy link
Author

brianabaker commented Dec 22, 2023

@silesky Okay, thank you! Interestingly I still saw Segment API calls with disable: true. Those should have not taken place in my tests, yeah? I figured out why they were firing, thanks!

@silesky silesky closed this as completed Jan 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants