@angular/common/http/testing#TestRequest TypeScript Examples

The following examples show how to use @angular/common/http/testing#TestRequest. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: sl-test-request.ts    From s-libs with MIT License 5 votes vote down vote up
/**
   * Resolve the request with the given body and options, like [TestRequest.flush()]{@linkcode https://angular.io/api/common/http/testing/TestRequest#flush}.
   */
  flush(body: Body, opts?: Parameters<TestRequest['flush']>[1]): void {
    this.req.flush(body, opts);
    this.tickIfPossible();
  }
Example #2
Source File: sl-test-request.ts    From s-libs with MIT License 5 votes vote down vote up
constructor(private req: TestRequest) {}
Example #3
Source File: auth.interceptor.spec.ts    From auth0-angular with MIT License 4 votes vote down vote up
// NOTE: Read Async testing: https://github.com/angular/angular/issues/25733#issuecomment-636154553

describe('The Auth HTTP Interceptor', () => {
  let httpClient: HttpClient;
  let httpTestingController: HttpTestingController;
  let auth0Client: Auth0Client;
  let req: TestRequest;
  let authState: AuthState;
  const testData: Data = { message: 'Hello, world' };

  const assertAuthorizedApiCallTo = (
    url: string,
    done: () => void,
    method = 'get'
  ) => {
    httpClient.request(method, url).subscribe(done);
    flush();
    req = httpTestingController.expectOne(url);

    expect(req.request.headers.get('Authorization')).toBe(
      'Bearer access-token'
    );
  };

  const assertPassThruApiCallTo = (url: string, done: () => void) => {
    httpClient.get<Data>(url).subscribe(done);
    flush();
    req = httpTestingController.expectOne(url);
    expect(req.request.headers.get('Authorization')).toBeFalsy();
  };

  let config: Partial<AuthConfig>;

  beforeEach(() => {
    req = undefined as any;

    auth0Client = new Auth0Client({
      domain: '',
      client_id: '',
    });

    spyOn(auth0Client, 'getTokenSilently').and.resolveTo('access-token');

    config = {
      httpInterceptor: {
        allowedList: [
          '',
          'https://my-api.com/api/photos',
          'https://my-api.com/api/people*',
          'https://my-api.com/orders',
          {
            uri: 'https://my-api.com/api/orders',
            allowAnonymous: true,
          },
          {
            uri: 'https://my-api.com/api/addresses',
            tokenOptions: {
              audience: 'audience',
              scope: 'scope',
            },
          },
          {
            uri: 'https://my-api.com/api/calendar*',
          },
          {
            uri: 'https://my-api.com/api/register',
            httpMethod: HttpMethod.Post,
          },
          {
            uriMatcher: (uri) => uri.indexOf('/api/contact') !== -1,
            httpMethod: HttpMethod.Post,
            tokenOptions: {
              audience: 'audience',
              scope: 'scope',
            },
          },
        ],
      },
    };

    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      providers: [
        {
          provide: HTTP_INTERCEPTORS,
          useClass: AuthHttpInterceptor,
          multi: true,
        },
        {
          provide: Auth0ClientService,
          useValue: auth0Client,
        },
        {
          provide: AuthClientConfig,
          useValue: { get: () => config },
        },
      ],
    });

    httpClient = TestBed.inject(HttpClient);
    httpTestingController = TestBed.inject(HttpTestingController);
    authState = TestBed.inject(AuthState);

    spyOn(authState, 'setError').and.callThrough();
  });

  afterEach(() => {
    httpTestingController.verify();
    if (req) {
      req.flush(testData);
    }
  });

  describe('When no httpInterceptor is configured', () => {
    it('pass through and do not have access tokens attached', fakeAsync((
      done: () => void
    ) => {
      config.httpInterceptor = (null as unknown) as HttpInterceptorConfig;
      assertPassThruApiCallTo('https://my-api.com/api/public', done);
    }));
  });

  describe('Requests that do not require authentication', () => {
    it('pass through and do not have access tokens attached', fakeAsync((
      done: () => void
    ) => {
      assertPassThruApiCallTo('https://my-api.com/api/public', done);
    }));
  });

  describe('Requests that are configured using a primitive', () => {
    it('attach the access token when the configuration uri is a string', fakeAsync((
      done: () => void
    ) => {
      // Testing /api/photos (exact match)
      assertAuthorizedApiCallTo('https://my-api.com/api/photos', done);
    }));

    it('attach the access token when the configuration uri is a string with a wildcard', fakeAsync((
      done: () => void
    ) => {
      // Testing /api/people* (wildcard match)
      assertAuthorizedApiCallTo('https://my-api.com/api/people/profile', done);
    }));

    it('matches a full url to an API', fakeAsync((done: () => void) => {
      // Testing 'https://my-api.com/orders' (exact)
      assertAuthorizedApiCallTo('https://my-api.com/orders', done);
    }));

    it('matches a URL that contains a query string', fakeAsync((
      done: () => void
    ) => {
      assertAuthorizedApiCallTo(
        'https://my-api.com/api/people?name=test',
        done
      );
    }));

    it('matches a URL that contains a hash fragment', fakeAsync((
      done: () => void
    ) => {
      assertAuthorizedApiCallTo(
        'https://my-api.com/api/people#hash-fragment',
        done
      );
    }));
  });

  describe('Requests that are configured using a complex object', () => {
    it('attach the access token when the uri is configured using a string', fakeAsync((
      done: () => void
    ) => {
      // Testing { uri: /api/orders } (exact match)
      assertAuthorizedApiCallTo('https://my-api.com/api/orders', done);
    }));

    it('pass through the route options to getTokenSilently, without additional properties', fakeAsync((
      done: () => void
    ) => {
      // Testing { uri: /api/addresses } (exact match)
      assertAuthorizedApiCallTo('https://my-api.com/api/addresses', done);

      expect(auth0Client.getTokenSilently).toHaveBeenCalledWith({
        audience: 'audience',
        scope: 'scope',
      });
    }));

    it('attach the access token when the configuration uri is a string with a wildcard', fakeAsync((
      done: () => void
    ) => {
      // Testing { uri: /api/calendar* } (wildcard match)
      assertAuthorizedApiCallTo('https://my-api.com/api/calendar/events', done);
    }));

    it('attaches the access token when the HTTP method matches', fakeAsync((
      done: () => void
    ) => {
      // Testing { uri: /api/register } (wildcard match)
      assertAuthorizedApiCallTo(
        'https://my-api.com/api/register',
        done,
        'post'
      );
    }));

    it('does not attach the access token if the HTTP method does not match', fakeAsync((
      done: () => void
    ) => {
      assertPassThruApiCallTo('https://my-api.com/api/public', done);
    }));

    it('does not execute HTTP call when not able to retrieve a token', fakeAsync((
      done: () => void
    ) => {
      (auth0Client.getTokenSilently as jasmine.Spy).and.returnValue(
        throwError({ error: 'login_required' })
      );

      httpClient.request('get', 'https://my-api.com/api/calendar').subscribe({
        error: (err) => expect(err).toEqual({ error: 'login_required' }),
      });

      httpTestingController.expectNone('https://my-api.com/api/calendar');
      flush();
    }));

    it('does execute HTTP call when not able to retrieve a token but allowAnonymous is set to true', fakeAsync((
      done: () => void
    ) => {
      (auth0Client.getTokenSilently as jasmine.Spy).and.returnValue(
        throwError({ error: 'login_required' })
      );

      assertPassThruApiCallTo('https://my-api.com/api/orders', done);
    }));

    it('emit error when not able to retrieve a token but allowAnonymous is set to false', fakeAsync((
      done: () => void
    ) => {
      (auth0Client.getTokenSilently as jasmine.Spy).and.callFake(() => {
        return Promise.reject({ error: 'login_required' });
      });

      httpClient.request('get', 'https://my-api.com/api/calendar').subscribe({
        error: (err) => expect(err).toEqual({ error: 'login_required' }),
      });

      httpTestingController.expectNone('https://my-api.com/api/calendar');
      flush();

      expect(authState.setError).toHaveBeenCalled();
    }));

    it('does not emit error when not able to retrieve a token but allowAnonymous is set to true', fakeAsync(() => {
      (auth0Client.getTokenSilently as jasmine.Spy).and.callFake(() => {
        return Promise.reject({ error: 'login_required' });
      });

      assertPassThruApiCallTo('https://my-api.com/api/orders', () => {
        expect(authState.setError).not.toHaveBeenCalled();
      });
    }));
  });

  describe('Requests that are configured using an uri matcher', () => {
    it('attach the access token when the matcher returns true', fakeAsync((
      done: () => void
    ) => {
      // Testing { uriMatcher: (uri) => uri.indexOf('/api/contact') !== -1 }
      assertAuthorizedApiCallTo('https://my-api.com/api/contact', done, 'post');
    }));

    it('pass through the route options to getTokenSilently, without additional properties', fakeAsync((
      done: () => void
    ) => {
      // Testing { uriMatcher: (uri) => uri.indexOf('/api/contact') !== -1 }
      assertAuthorizedApiCallTo('https://my-api.com/api/contact', done, 'post');

      expect(auth0Client.getTokenSilently).toHaveBeenCalledWith({
        audience: 'audience',
        scope: 'scope',
      });
    }));

    it('does not attach the access token when the HTTP method does not match', fakeAsync((
      done: () => void
    ) => {
      // Testing { uriMatcher: (uri) => uri.indexOf('/api/contact') !== -1 }
      assertAuthorizedApiCallTo('https://my-api.com/api/contact', done, 'post');
      assertPassThruApiCallTo('https://my-api.com/api/contact', done);
    }));
  });
});
Example #4
Source File: sl-test-request.spec.ts    From s-libs with MIT License 4 votes vote down vote up
describe('SlTestRequest', () => {
  describe('.request', () => {
    it('is available', () => {
      const httpRequest = new HttpRequest('GET', 'url');
      const req = new SlTestRequest(
        new TestRequest(httpRequest, new Subject()),
      );
      expect(req.request).toBe(httpRequest);
    });
  });

  describe('.flush()', () => {
    it('resolves the request with the given body and options', () => {
      const ctx = new AngularContext();
      ctx.run(() => {
        const spy = jasmine.createSpy();
        ctx.inject(HttpClient).get('a url').subscribe(spy);
        const req = expectRequest('GET', 'a url');

        const body = 'the body';
        req.flush(body);

        expectSingleCallAndReset(spy, body);
      });
    });

    it('passes along other arguments', () => {
      const ctx = new AngularContext();
      ctx.run(() => {
        const spy = jasmine.createSpy();
        ctx
          .inject(HttpClient)
          .request('GET', 'a url', { observe: 'response' })
          .subscribe(spy);
        const req = expectRequest('GET', 'a url');

        req.flush('', { status: 249, statusText: '' });

        const resp: HttpResponse<unknown> = spy.calls.argsFor(0)[0];

        expect(resp.status).toBe(249);
      });
    });

    it('runs tick if an AngularContext is in use', () => {
      const ctx = new AngularContext();
      const spy = spyOn(ctx, 'tick');
      ctx.run(() => {
        ctx.inject(HttpClient).get('a url').subscribe();
        const req = expectRequest('GET', 'a url');

        req.flush('the body');

        expectSingleCallAndReset(spy);
      });
    });
  });

  describe('.flushError()', () => {
    it('rejects the request with the given args', () => {
      const ctx = new AngularContext();
      ctx.run(() => {
        const spy = jasmine.createSpy();
        ctx.inject(HttpClient).get('a url').subscribe({ error: spy });
        const req = expectRequest('GET', 'a url');

        req.flushError(123, { statusText: 'bad', body: 'stop it' });

        const resp: HttpErrorResponse = spy.calls.argsFor(0)[0];
        expect(resp.status).toBe(123);
        expect(resp.statusText).toBe('bad');
        expect(resp.error).toBe('stop it');
      });
    });

    it('has good default args', () => {
      const ctx = new AngularContext();
      ctx.run(() => {
        const spy = jasmine.createSpy();
        ctx.inject(HttpClient).get('a url').subscribe({ error: spy });
        const req = expectRequest('GET', 'a url');

        req.flushError();

        const resp: HttpErrorResponse = spy.calls.argsFor(0)[0];
        expect(resp.status).toBe(500);
        expect(resp.statusText).toBe('simulated test error');
        expect(resp.error).toBeNull();
      });
    });

    it('runs tick if an AngularContext is in use', () => {
      const ctx = new AngularContext();
      const spy = spyOn(ctx, 'tick');
      ctx.run(() => {
        ctx.inject(HttpClient).get('a url').subscribe({ error: noop });
        const req = expectRequest('GET', 'a url');

        req.flushError();

        expectSingleCallAndReset(spy);
      });
    });
  });

  describe('.isCancelled()', () => {
    it('returns whether the request has been cancelled', () => {
      const ctx = new AngularContext();
      ctx.run(() => {
        const subscription = ctx.inject(HttpClient).get('a url').subscribe();
        const req = expectRequest('GET', 'a url');

        expect(req.isCancelled()).toBe(false);
        subscription.unsubscribe();
        expect(req.isCancelled()).toBe(true);
      });
    });
  });

  describe('.tickIfPossible()', () => {
    it('gracefully handles when there is no AngularContext', () => {
      const httpRequest = new HttpRequest('GET', 'url');
      const req = new SlTestRequest(
        new TestRequest(httpRequest, new Subject()),
      );
      expect(() => {
        req.flush('');
      }).not.toThrowError();
    });
  });
});