Documentation
Fuse Components
Libraries

## Mock API

MockAPI is a helper library developed specifically for Fuse to mock API endpoints and provide data to your app without having to create an actual backend application. This way, you can focus on your frontend app and once you finish with the frontend, you can create your backend application to provide real API endpoints with real data.

This not only makes you progress faster and put together your app very quickly but you will also know exactly what you will be needing from your API.

While MockAPI is not suitable for every use case or for every project, there are some cases that using it would make your life easier. These cases are but not limited to:

- If you want to focus on the frontend first
- If you want to create a mockup of your idea to see if it's going to work or not
- If you want to create a small side project for yourself or for your colleagues/company
- If you need to present your idea to your client or to your boss without spending many hours and resources

MockAPI is NOT a database or a backend replacement! It works on memory. As soon as you reload your app, all the changes you have made using Mock API endpoints will go away and replaced with defaults.

## How it works?

MockAPI module provides an HttpInterceptor which intercepts all outgoing http requests to return a mock response based on user provided callback functions. While it intercepts all requests, if the MockAPI module cannot find a callback function for the request type and url, it will let the request to pass through. This way, you can use the MockAPI along with your real API endpoints.

## FuseMockApiService

The `FuseMockApiService` is the core of the MockAPI module. This singleton service is used to register API endpoints and callbacks. This is the only thing you will need to mock API endpoints.

### Methods

All methods return an instance of `FuseMockApiHandler`.

.onGet(url: string, delay?: number): FuseMockApiHandler
Registers a url for GET requests. Delay (milliseconds) can be set to delay the response.
.onPatch(url: string, delay?: number): FuseMockApiHandler
Registers a url for PATCH requests. Delay (milliseconds) can be set to delay the response.
.onPost(url: string, delay?: number): FuseMockApiHandler
Registers a url for POST requests. Delay (milliseconds) can be set to delay the response.
.onPut(url: string, delay?: number): FuseMockApiHandler
Registers a url for PUT requests. Delay (milliseconds) can be set to delay the response.
.onDelete(url: string, delay?: number): FuseMockApiHandler
Registers a url for DELETE requests. Delay (milliseconds) can be set to delay the response.

### FuseMockApiHandler

This is the return type of all methods from the service. This class instance is not directly accessible. It can only be accessed through the `FuseMockApiService` allowing method chaining. It has 2 methods:

.reply(callback: FuseMockApiReplyCallback): void
.replyCount(count: number): void

These methods can be used to register the callback function for the request. The callback has an access to the outgoing HttpRequest which can be used to access anything from the request such as form data and headers.

You can limit the reply by chaining the `.replyCount` and providing the number of times this request should be handled. After the limit has reached, the request handler will throw an error and won't let the request to pass through. It can be useful for creating one-time-use endpoints to test "Reset Password" links or testing an unreachable API endpoints and etc.

The callbacks must return either an array `[number, any | string]` or an observable that returns the said array. The `number` represents the HTTP status code of the response while the `any | string` represents the actual response.

### Basic usage

this.fuseMockApiService .onPut('api/navigation') .reply(({request: HttpRequest<any>}) => { // Get the body from the request const body = request.body; // Do something with your data // Return a success code along with some data return [200, { newNavigation }]; }) this.fuseMockApiService .onGet('api/navigation') .reply(() => { // Do something with your data // Return an observable with success code and data return of(someFunctionToCall()).pipe(map((response) => { // Do some stuff with the response from 'someFunctionToCall()' // Return a success code along with some data return [200, { newNavigation }]; }); });

## Step by step guide to start using FuseMockApi

It's pretty easy and straightforward to setup the MockAPI module for mocking API endpoints and their responses. Once you understand the underlying mechanic, you will be able to mock API endpoints in no time.

Please keep in mind that the following step-by-step guide assumes you are doing everything from scratch for the MockAPI like creating directories, adding files, exporting via barrels etc. Majority of these already setup in both Demo and Starter apps for you so it's a bit easier to start working with the MockAPI.

### 1. Prepare the files

Choose a location to store your mocks. By default the Demo app uses `src/app/mock-api/` directory. You can use the same directory or choose another one. For this guide, we will assume you are going to use the default directory.

It's important to keep all mock related files in the same directory because we will create a barrel file that exports all the mock classes and provide that to the `FuseMockApiModule` so it can register and use them.

After choosing the location, create a sub-directory relevant to your endpoint and create 2 files in it; one for the mock class and one for the data json:

src/app/mock-api/
└─ navigation/
└─ data.ts
└─ api.ts

### 2. Create the class

Edit the `api.ts` file and inside create an injectable class.

The `FuseMockApi` requires one public method called `registerHandlers()` and it must be implemented. It also needs to be called within the `constructor` of your mock class:

import { Injectable } from '@angular/core'; import { FuseMockApiService } from '@fuse/lib/mock-api'; @Injectable({ providedIn: 'root' }) export class NavigationMockApi { private _fuseMockApiService = inject(FuseMockApiService); /** * Constructor */ constructor() { // Register Mock API handlers this.registerHandlers(); } /** * Register Mock API handlers */ registerHandlers(): void { } }

### 3. Create the data

Edit the `data.ts` file and add your default data as an exported const value. You can have more than one `const` per file, just remember to export all of them:

// An array of navigation items for compact layout export const compactNavigation = [ ] // An array of navigation items for default layout export const defaultNavigation = [ ]

### 3. Import the data into the Mock class

Return back to `api.ts` file, import your data and set them as class properties so they can be accessible within the class:

import { Injectable } from '@angular/core'; import { FuseMockApiService } from '@fuse/lib/mock-api'; import { compactNavigation, defaultNavigation } from 'app/mock-api/navigation/data'; @Injectable({ providedIn: 'root' }) export class NavigationMockApi { private _fuseMockApiService = inject(FuseMockApiService); private readonly _compactNavigation: any[]; private readonly _defaultNavigation: any[]; /** * Constructor */ constructor() { // Set the data this._compactNavigation = compactNavigation; this._defaultNavigation = defaultNavigation; // Register Mock API handlers this.registerHandlers(); } /** * Register Mock API handlers */ registerHandlers(): void { } }

### 4. Register the endpoints and callbacks

Inside the `registerHandlers()` method, define your endpoints and callbacks to provide data:

import { Injectable } from '@angular/core'; import { cloneDeep } 'lodash-es'; import { FuseMockApiService, FuseMockApiUtils } from '@fuse/lib/mock-api'; import { compactNavigation, defaultNavigation } from 'app/mock-api/navigation/data'; @Injectable({ providedIn: 'root' }) export class NavigationMockApi { ... /** * Register Mock API handlers */ registerHandlers(): void { // Navigation - GET this._fuseMockApiService .onGet('api/navigation') .reply(() => { // Clone the data to preserve the originals const compactNavigation = cloneDeep(this._compactNavigation); const defaultNavigation = cloneDeep(this._defaultNavigation); // Do some stuff with your data // Return return [200, { compact: compactNavigation, default: defaultNavigation, }]; }) // Navigation - PUT this._fuseMockApiService .onPut('api/navigation') .reply(({request}) => { // Save the new navigation item const newNavigationItem = cloneDeep(request.body.navigationItem); newNavigationItem.id = FuseMockApiUtils.guid(); this._defaultNavigation.unshift(newNavigationItem); // Return return [200, newNavigationItem]; }); } }

### 5. Create a barrel file

Navigate back to the root of your mock data directory, by default it's the `src/app/mock-api/` directory, and create an index.ts file.

src/app/mock-api/
└─ auth/
└─ navigation/
└─ user/
└─ index.ts

Edit the `index.ts` file to create a barrel from the services. Only import the services and not the data files, create an array from them and then export that array:

import { AuthMockApi } from 'app/mock-api/auth'; import { NavigationMockApi } from 'app/mock-api/navigation'; import { UserMockApi } from 'app/mock-api/user'; export const mockApiServices = [ AuthMockApi, NavigationMockApi, UserMockApi ];

After that, head to the `app.config.ts` file, provide the array of services you have exported:

... import { provideFuse } from '@fuse'; import { mockApiServices } from 'app/mock-api'; provideFuse({ mockApi: { services: mockApiServices, }, ... })

### 6. (Optional) Set a global delay

You can also set a global delay (ms) to all of your Mock API endpoints to simulate a slow connection, a server that's under attack or failing, some kind of service interruption and etc.

... import { provideFuse } from '@fuse'; import { mockApiServices } from 'app/mock-api'; provideFuse({ mockApi: { delay : 250, services: mockApiServices, }, ... })

### 7. Consume the mock API endpoints

Now you can consume your mock API endpoints anywhere from your app using Angular's HttpClient and the MockAPI module will catch the requests. If there is a matching url and a request type, the MockAPI will provide the response from the provided callback. If there isn't one, then the MockAPI will let the request to pass through allowing you to use a real API endpoints along with the mocked ones.

/** * Get navigation */ getNavigation(): Observable<any> { return this._httpClient.get<any[]>('api/navigation').pipe( tap((response: any) => { this._navigation.next(response); }) ); }