npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

angular-http-raml

v0.0.6

Published

testing library for creating angular 4 Http instances based on a RAML definition

Downloads

2

Readme

Table of Contents generated with DocToc

angular-http-raml

This library provides a RAML RAML-based MockBackend generator for testing Angular 4 applications.

Simply put, you can define your REST API using RAML, and use this definition to create an angular Http object which speaks the same language as the API you defined.

Installation

Install the library with npm install --save-dev angular-http-raml

Then add the following entry to your karma configuration:

files: [
  ...
  {pattern: "**/*.raml", included: false}
  ...
],

Stubbing

Prerequisities:

To understand the below walk-through, you need to have a basic understanding of the followings:

  • Angular 2+
  • RAML
  • Jasmine
  • Test doubles (mocks and stubs)

Quickstart

This library generates stub HTTP backends

Let's assume your application interacts with the API defined by the following RAML file:

person-api.raml:

#%RAML 1.0
title: Endpoints for testing response selection based on status codes
version: v0
baseUri: http://api.example.com
mediaType: application/json
/person/{personId}/emails:
  get:
    responses:
      200:
        queryParameters:
          activeOnly: boolean 
        body:
          example:
            - email: "[email protected]"
              active: true
            - email: "[email protected]"
              active: false
      404:
        body:
          example:
            message: "not found"
  post:
    responses:
      201:

Let's also assume that you want to test the following Angular service:

my-service.ts:


export class MyService {
  
  constructor(private http: Http) {}
  
  public fetchPersonEmails(personId: number): Observable<string[]> {
    return http.get("http://api.example.com/person/" + personId + "/emails")
        .map(response => response.json());
  }
  
}

my-service.spec.ts :

describe("MyService", () => {
  
  it("queries the backend", () => {
    const mockBackend = RAMLBackendConfig.initWithFile("./person-api.raml")
      .stubAll()
      .createBackend();
    const http = new Http(mockBackend, new RequestOptions());
    const subject = new MyService(http);
    
    subject.fetchPersonEmails(123).subscribe(emails => {
      expect(emails).toEqual([
        {email: "[email protected]", active: true},
        {email: "[email protected]", active: false},
      ]);
    });
    
    mockBackend.verifyNoPendingRequests();
  });
  
});

Here is what happens when you run this test:

  • the RAMLBackendConfig.initWithFile("./person-api.raml") call looks up the REST endpoints with their parameters. These are the possible calls to be used on the mock
  • the stubAll() call tells the RAMLBackendConfig instance to stub all requests defined in the RAML file. The responses will be the entities defined in the example node of the RAML definition (if present).
  • then we instantiate a Http object which will use our generated MockBackend.
  • when your MyService method calls the http.get(...) method then the generated stub will know that the GET http://api.example.com/person/123/emails call matches the stubbed GET /person/{personId}/emails endpoint, so it will pick up the example array and return it as the response body. Unless you specify it otherwise it will look for a 2xx response in the listed responses.
  • the MyService instance receives the response (just like if it would be a real HTTP backend service), and publishes the result to the subscriber attached in the test. This subscriber will perform the assertion (if the response of MyService is correct).

This was the quick-start of using the library. To sum up, if you develop a RAML file which includes example responses, then you generate a HTTP stub backend from it in a few lines.

Customizing stubbing

Changing the response by response code

RAML lets you describe responses with multiple response codes. By default, angular-http-raml will choose the response with the lowest 2xx status code, but you can simply override this behavior. Example (using the above listed person-api.raml):

// ...
  const mockBackend = RAMLBackendConfig.initWithFile("./person-api.raml")
   .stubAll()
   .whenGET("/person/123/emails").thenRespondWith(404)
   .createBackend();
// ...

This configuration will override the default stubbing and tell the RAMLBackend to send the 404 response instead of the default 200. The response body will be {"message":"not found"} as it is defined in the RAML file.

Using an other example response body

RAML lets you define multiple example response bodies for a response. angular-http-raml lets you easily switch between them. Let's consider the following RAML definition of an endpoint:

/person/{personId}/emails:
  get:
    responses:
      200:
        body:
          examples:
            hasEmails:
              - email: "[email protected]"
                active: true
              - email: "[email protected]"
                active: false
            emptyList: []

In this RAML definition there are 2 example responses (both with 200 response code). They are called hasEmails and emptyList. By default the RAMLBackend instance would return the first example response it finds (hasEmails), override it by passing emptyList as the 2nd parameter of thenRespondWith():

const mockBackend = RAMLBackendConfig.initWithFile("./person-api.raml")
  .stubAll()
  .whenGET("/person/123/emails").thenRespondWith(404, "emptyList")
  .createBackend();

Passing an entire request

If the above two methods of overriding default responses - eg. because the response body you want to test with is different from the examples available in RAML - then you can explicitly pecify the entire request to be sent back from the server by calling thenRespond() instead of thenRespondWith() :

const mockBackend = RAMLBackendConfig.initWithFile("./person-api.raml")
      .whenGET("/person/123/emails").thenRespond(new Response(new ResponseOptions({
        status: 200,
        body: JSON.stringify([{email:null, active: false}]);
      })))
      .createBackend();

Safety nets while stubbing

One thing that can go wrong while stubbing - or creating any kind of test double - is mimicing false behavior of the stubbed system. As a simple example, if you mistype a request path in your test, then you implement a service that conforms to the test, then your test will pass, but your service still won't be compatible with your backend.

To minimize the risk of such problems, angular-http-raml validates your stubbed requests, so it checks if you properly mimic the behavior of the remote service. In the below example the stub request contains a query parameter called onlyActive, but since this query parameter is not included in the RAML definition, an InvalidStubbingError will be thrown:

const mockBackend = RAMLBackendConfig.initWithFile("./person-api.raml")
 // thow will throw an InvalidStubbingError immediately,
 // since "onlyActive" is not a valid query param
  .whenGET("/person/123/emails?onlyActive=true").thenRespond(200)
  .createBackend();

Similarly, eg. if you try to stub a request which doesn't match any path patterns then an error is thrown.

Does it mean that you can't have any compatibility issues with server-client communication? Of course, not. The library conforms to your RAML documentation and not to your real server. To take a full advantage of RAML, it is recommended to involve the same file in testing your backend, so the contract is verified from both ends. This library can help you with only the half of the job.

Mocking

TODO