Giter VIP home page Giter VIP logo

cypress-typed-stubs's Introduction

Cypress typed stubs

A Criteo npm package to define typed Cypress stubs with automatic URL patterns, based on clients generated with Swagger.

License

criteo/cypress-typed-stubs introspects your typescript (Angular) clients generated by nswag and helps you define your own Cypress stubs very easily, where:

  • HTTP method
  • URL pattern
  • name

...are automatically generated.

And the fixture used to stub your API is type checked.

Installation

Compatibility table:

Angular version Cypress version cypress-typed-stubs version
11 <9 2
11 9 3.0.0-beta.4
13 9 4.0.0-beta.7
15 9 5.0.0
npm install --save-dev cypress-typed-stubs

Usage

Have a look at the example-app code in this repository.

Let's assume that you have an AdSetsClient that was generated by nswag, which contains a getById endpoint and returns a GetAdSetDetailsResponse object, or null.

export class AdSetsClient extends GeneratedClient {
  getById(adSetId: number): Observable<GetAdSetDetailsResponse | null> {
    let url_ = this.baseUrl + '/campaign-api/ad-sets/{adSetId}';
    // ...
  }
}

Without cypress-typed-stubs 😕

If you want to stub this endpoint in your Cypress tests, you might want to do something like:

cy.intercept(
  'GET', // Need to know the HTTP method
  /.*\/campaign-api\/ad-sets\/.*/, // Need to "guess" the appropriate URL regex
  {
    // Need to maintain a JSON object that matches the proper interface
    adSet: {
      id: 5,
      // ...
      // No type checking!
      audienceType: 'invalid type',
    },
  }
).as('getAdSet'); // Need to define a name that makes sense and that is reused throughout the tests

// Can't easily reuse stubs

and wait on the call with:

cy.wait('@getAdSet');

👎 Issues

  • the HTTP method and URL pattern have to be "guessed" and maintained if they happen to change in the generated client
  • the provided fixture is not type checked
  • a name has to be chosen and duplicated in the tests (prepended with @). No naming convention

With cypress-typed-stubs 🤩

Create stubs

Define

  • a stub that matches the generated client (ex: AdSetsStub)
  • stub endpoints that match the generated client endpoint
    • the provided fixture is type checked
    • URL pattern and HTTP method are provided automatically
export class AdSetsStub extends ClientStub<AdSetsClient> {
  constructor() {
    super(AdSetsClient);
  }

  endpoints = {
    getById: this.createEndpoint(
      this.client.getById,
      200,
      // Everything is typed!
      {
        adSet: {
          id: 5,
          // ... other properties
          audienceType: AudienceType.Custom,
        },
      }
    ),
  };
}

Instead of a fixture, you can provide a fixture builder: it is a function that takes a cypress request object (CyHttpMessages.IncomingHttpRequest) as parameter and returns a fixture. It is useful to adapt the fixture depending on the request (for example, request body or query parameters):

export class AdSetsStub extends ClientStub<AdSetsClient> {
  constructor() {
    super(AdSetsClient);
  }

  endpoints = {
    getById: this.createEndpoint(
      this.client.getById,
      200,
      // Fixture builder function -> builds the fixture depending on the request
      // (here depending on 'language' query parameter). The function is typed.
      (req) => (req.query['language'] === 'fr-FR' ?
        {
          adSet: {
            name: "Ceci est mon ensemble d'annonce",
            // ... other properties
          },
        } :
        {
          adSet: {
            name: 'This is my ad set',
            // ... other properties
          },
        }
      )
    ),
  };
}

Intercept

These endpoints can then be used in any Cypress test for intercept.

// Create the stub _and initialize it_
const stub = new AdSetsStub().init();

// Endpoints
const getById = stub.endpoints.getById;

// Stub default config
EndpointHelper.stub(getById.defaultConfig());

Note that the usage of EndpointHelper is optional, you can use cy.intercept directly

The endpoint is now stubbed by Cypress with a name automatically generated (prefixed with client name for consistency):

routes

Adjust

The stub can be adapted based on the default configuration:

  • change HTTP status:
EndpointHelper.stub(getById.defaultConfig().withStatusCode(500));
  • adapt the fixture (mapping is type checked):
EndpointHelper.stub(
  getById.defaultConfig().mappingFixture((fixture) => ({
    adSet: {
      ...fixture.adSet,
      id: 7, // Simply change the id
    },
  }))
);

If the endpoint was initially stubbed with a fixture builder, the provided mapping function is applied to the result of the fixture builder function.

  • replace the fixture entirely (override object is type checked):
EndpointHelper.stub(
  getById.defaultConfig().withOverride({
    // Everything is typed!
    adSet: {
      id: 6,
      // ... other properties
      audienceType: AudienceType.Commerce,
    },
  })
);

If the endpoint was initially stubbed with a fixture builder, the provided object overrides the result of the fixture builder function.

  • set HTTP headers:
EndpointHelper.stub(
  getById.defaultConfig().withHeaders({
    myHeader: 'myValue',
  })
);
  • adaptations can be combined with fluent syntax:
EndpointHelper.stub(getById.defaultConfig().withStatusCode(500).withOverride({}).withHeaders({ traceId: '12345' }));

Wait

Endpoints have a default alias that can be used to wait calls:

cy.wait(getById.alias);

👍 Advantages

  • stub name, HTTP method, URL pattern are provided automatically
  • stub alias is a property
  • fixture is type checked (which enables code assistance)
  • helper methods

Contributions

Please use Node v16 and npm v8.

Testing within a "host" project

From this project:

npm run prepare
# This will break the local build, but don't worry this is temporary
npm uninstall @angular/common
npm link

It is useful to temporarily uninstall @angular/common peer dependency to avoid incompatible errors in the "host" project.

From the project using the library:

npm link cypress-typed-stubs

After you are done with your tests, make sure to not commit your changes to package.json (the removal of dev dependencies)

cypress-typed-stubs's People

Contributors

olivierchirouze avatar xavierdupessey avatar tnodet avatar jmauro avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.