Adding Unit Tests for Services in loklak search

In Loklak search, it can be tricky to write tests for services as these services are customizable and not fixed. Therefore, we need to test every query parameter of the URL. Moreover, we need to test if service is parsing data in a correct manner and returns only data of type ApiResponse. In this blog here, we are going to see how to build different components for unit testing services. We will be going to test Search service in loklak search which makes Jsonp request to get the response from the loklak search.json API which are displayed as feeds on loklak search. We need to test if the service handles the response in a correct way and if the request parameters are exactly according to customization. Service to test Search service in loklak search is one of the most important component in the loklak search. SearchService is a class with a method fetchQuery() which takes parameter and sets up URL parameters for the search.json API of loklak. Now, it makes a JSONP request and maps the API response. The Method fetchQuery() can be called from other components with parameters query and lastRecord to get the response from the server based on a certain search query and the last record to implement pagination feature in loklak search. Now as the data is retrieved, a callback function is called to access the response returned by the API. Now, the response received from the server is parsed to JSON format data to extract data from the response easily. @Injectable() export class SearchService { private static readonly apiUrl: URL = new URL('https://api.loklak.org/api/search.json'); private static maximum_records_fetch = 20; private static minified_results = true; private static source = 'all'; private static fields = 'created_at,screen_name,mentions,hashtags'; private static limit = 10; private static timezoneOffset: string = new Date().getTimezoneOffset().toString();constructor( private jsonp: Jsonp ) { }// TODO: make the searchParams as configureable model rather than this approach. public fetchQuery(query: string, lastRecord = 0): Observable<ApiResponse> { const searchParams = new URLSearchParams(); searchParams.set('q', query); searchParams.set('callback', 'JSONP_CALLBACK'); searchParams.set('minified', SearchService.minified_results.toString()); searchParams.set('source', SearchService.source); searchParams.set('maximumRecords', SearchService.maximum_records_fetch.toString()); searchParams.set('timezoneOffset', SearchService.timezoneOffset); searchParams.set('startRecord', (lastRecord + 1).toString()); searchParams.set('fields', SearchService.fields); searchParams.set('limit', SearchService.limit.toString()); return this.jsonp.get(SearchService.apiUrl.toString(), { search: searchParams }) .map(this.extractData)}private extractData(res: Response): ApiResponse { try { return <ApiResponse>res.json(); } catch (error) { console.error(error); } } Testing the service Create a mock backend to assure that we are not making any Jsonp request. We need to use Mock Jsonp provider for this. This provider sets up MockBackend and wires up all the dependencies to override the Request Options used by the JSONP request. const mockJsonpProvider = { provide: Jsonp, deps: [MockBackend, BaseRequestOptions], useFactory: (backend: MockBackend, defaultOptions: BaseRequestOptions) => { return new Jsonp(backend, defaultOptions); } };   Now, we need to configure the testing module to isolate service from other dependencies. With this, we can instantiate services manually. We have to use TestBed for unit testing and provide all necessary imports/providers for creating and testing services in the unit test. describe('Service: Search', () => { let service: SearchService = null; let backend: MockBackend = null;…

Continue ReadingAdding Unit Tests for Services in loklak search

Adding unit tests for effects in Loklak Search

Loklak search uses @ngrx/effects to listen to actions dispatched by the user and sending API request to the loklak server. Loklak search, currently, has seven effects such as Search Effects,  Suggest Effects which runs to make the application reactive. It is important to test these effects to ensure that effects make API calls at the right time and then map the response to send it back to the reducer. I will  explain here how I added unit tests for the effects. Surprisingly, the test coverage increased from 43% to 55% after adding these tests. Effects to test We are going to test effects for user search. This effect listens to the event of type USER_SEARCH and makes a call to the user-search service with the query as a parameter. After a response is received, it maps the response and passes it on the UserSearchCompleteSuccessAction action which performs the later operation. If the service fails to get a response, it makes a call to the UserSearchCompleteFailAction. Code ApiUserSearchEffects is the effect which detects if the USER_SEARCH action is dispatched from some component of the application and consequently, it makes a call to the UserSearchService and handles the JSON response received from the server. The effects then, dispatch the action new UserSearchCompleteSuccessAction if response is received from server or either dispatch the action new UserSearchCompleteFailAction if no response is received. The debounce time is set to 400 so that response can be flushed if a new USER_SEARCH is dispatched within the next 400ms. For this effect, we need to test if the effects actually runs when USER_SEARCH action is made. Further, we need to test if the correct parameters are supplied to the service and response is handled carefully. We also, need to check if the response if really flushed out within the certain debounce time limit. @Injectable() export class ApiUserSearchEffects {@Effect() search$: Observable<Action> = this.actions$ .ofType(userApiAction.ActionTypes.USER_SEARCH) .debounceTime(400) .map((action: userApiAction.UserSearchAction) => action.payload) .switchMap(query => { const nextSearch$ = this.actions$.ofType(userApiAction.ActionTypes.USER_SEARCH).skip(1);const follow_count = 10;return this.apiUserService.fetchQuery(query.screen_name, follow_count) .takeUntil(nextSearch$) .map(response => new userApiAction.UserSearchCompleteSuccessAction(response)) .catch(() => of(new userApiAction.UserSearchCompleteFailAction(''))); });constructor( private actions$: Actions, private apiUserService: UserService ) { } } Unit test for effects Configure the TestBed class before starting the unit test and add all the necessary imports (most important being the EffectsTestingModule) and providers. This step will help to isolate the effects completely from all other components and testing it independently. We also need to create spy object which spies on the method userService.fetchQuery with provider being UserService. beforeEach(() => TestBed.configureTestingModule({ imports: [ EffectsTestingModule, RouterTestingModule ], providers: [ ApiUserSearchEffects, { provide: UserService, useValue: jasmine.createSpyObj('userService', ['fetchQuery']) } ] })); Now, we will be needing a function setup which takes params which are the data to be returned by the Mock User Service. We can now configure the response to returned by the service. Moreover, this function will be initializing EffectsRunner and returning ApiUserSearchEffects so that it can be used for unit testing. function setup(params?: {userApiReturnValue: any}) { const userService = TestBed.get(UserService); if (params) { userService.fetchQuery.and.returnValue(params.userApiReturnValue); }return {…

Continue ReadingAdding unit tests for effects in Loklak Search

Adding Unit Test for Reducer in loklak search

Ngrx/store components are an integral part of the loklak search. All the components are dependent on how the data is received from the reducers. Reducer is like a client-side database which stores up all the data received from the API response. It is responsible for changing the state of the application. Reducers also supplies data to the Angular components from the central Store. If correct data is not received by the components, the application would crash. Therefore, we need to test if the reducer is storing the data in a correct way and changes the state of the application as expected. Reducer also stores the current state properties which are fetched from the APIs. We need to check if reducers store the data in a correct way and if the data is received from the reducer when called from the angular components. In this blog, I would explain how to build up different components for unit testing reducers. Reducer to test This reducer is used for store the data from suggest.json API from the loklak server.The data received from the server is further classified into three properties which can be used by the components to show up auto- suggestions related to current search query. metadata: - This property stores the metadata from API suggestion response. entities: - This property stores the array of suggestions corresponding to the particular query received from the server. valid: - This is a boolean which keeps a check if the suggestions are valid or not. We also have two actions corresponding to this reducer. These actions, when called, changes the state properties which , further, supplies data to the components in a more classified manner. Moreover, state properties also causes change in the UI of the component according to the action dispatched. SUGGEST_COMPLETE_SUCCESS: - This action is called when the data is received successfully from the server. SUGGEST_COMPLETE_FAIL: - This action is called when the retrieving data from the server fails. export interface State { metadata: SuggestMetadata; entities: SuggestResults[]; valid: boolean; }export const initialState: State = { metadata: null, entities: [], valid: true };export function reducer(state: State = initialState, action: suggestAction.Actions): State { switch (action.type) { case suggestAction.ActionTypes.SUGGEST_COMPLETE_SUCCESS: { const suggestResponse = action.payload;return { metadata: suggestResponse.suggest_metadata, entities: suggestResponse.queries, valid: true }; }case suggestAction.ActionTypes.SUGGEST_COMPLETE_FAIL: { return Object.assign({}, state, { valid: false }); }default: { return state; } } } Unit tests for reducers Import all the actions, reducers and mocks import * as fromSuggestionResponse from './suggest-response'; import * as suggestAction from '../actions/suggest'; import { SuggestResponse } from '../models/api-suggest'; import { MockSuggestResponse } from '../shared/mocks/suggestResponse.mock';   Next, we are going to test if the undefined action doesn’t a cause change in the state and returns the initial state properties. We will be creating an action by const action = {} as any;  and call the reducer by const result = fromSuggestionResponse.reducer(undefined, action);. Now we will be making assertions with expect() block to check if the result is equal to initialState and all the initial state properties are…

Continue ReadingAdding Unit Test for Reducer in loklak search

sTeam GSoC 2016 Windup

(ˢᵒᶜⁱᵉᵗʸserver) aims to be a platform for developing collaborative applications. sTeam server project repository: sTeam. sTeam-REST API repository: sTeam-REST An overview of the work done by ajinkya007 during Google Summer of code 2016 with FOSSASIA on its project sTeam. The community bonding period saw the creation of a docker image and a debian package for the sTeam server. The integration of the sTeam shell into vi, improvements in the export and import to git scripts, user and group manipulation commands, sending mails through the commandline, viewing logs and the edit script modifications were done subsequently. The later part of GSOC saw that the sTeam-rest repository was restructured, unit and api-end point tests were performed. The new web interface developed was tested. The code written during this period by me and siddhant was merged and the conflicts were resolved. The merged code was tested thoroughly as no automated test integration tool supports pike programming language. Documentation was generated using Doxygen and deployed in the gh-pages of the sTeam server repository. A trello board was maintained throughout the course of GSOC 2016. Trello Board: sTeam Accomplishments Issues Resolved and Pull Requests Submitted for the same Commits Merged Blog Posts Scrums Further Improvements Issues Reported and Resolved A list of tasks covered and all the Pull requests related to each: Tasks Issue PR Make changes in the Makefile for installation of sTeam. Issue-25 Issue-27 PR-66 PR-67 Edit script modifications Issue-20 Issue-29 Issue-43 PR-44 PR-48 Indentation of output in steal-shell. Issue-24 PR-42 Integrate steam-shell into vim or emacs. Issue-37 Issue-43 Issue-49 PR-41 PR-48 PR-51 Improve the import and export from git scripts. Issue-9 Issue-14 Issue-16 Issue-18 Issue-19 Issue-46 PR-45 PR-54 PR-55 PR-76 Create, Delete and List the user through commandline Issue-58 Issue-69 Issue-72 PR-59 PR-70 PR-78 Sending Mails through commandline Issue-74 PR-85 Generate error logs and display them in CLI Issue-83 PR-86 Create a file of any mime type from command line. Issue-79 PR-82 Add more commands for group operations. Issue-80 PR-84 Add more utility to the steam-shell Issue-56 Issue-71 Issue-73 PR-57 PR-75 PR-81 Restructure the sTeam-rest repository List of Issue's List of PR's Write test cases to test sTeam-rest api List of Issue's List of PR's Create a debian package and a docker image for easy deployment Create docker image Docker Image Document the work done Issue 149 sTeam Server Structure, sTeam Server Documentation Test the web-interface ✓ ✓ Commits Merged During the course of GSOC 2016, work was done on the sTeam and sTeam-rest repositories. 1. The work done on the sTeam repository. We have combined all the work into two branches for the ease of creating a debian package. The commits made by me in each branch can be seen here. gsoc2016-societyserver-devel gsoc2016-source 2. The work done on the sTeam-rest repository The push request's sent for the issue's are yet to be merged in the main repository. The list of PR's for the sTeam-rest repository. sTeam-rest PR's The weekly blogs The blogs summarizing the work done during the week were published…

Continue ReadingsTeam GSoC 2016 Windup

sTeam REST API Unit Testing

(ˢᵒᶜⁱᵉᵗʸserver) aims to be a platform for developing collaborative applications. sTeam server project repository: sTeam. sTeam-REST API repository: sTeam-REST Unit Testing the sTeam REST API The unit testing of the sTeam REST API is done using the karma and the jasmine test runner. The karma and the jasmine test runner are set up in the project repository. The karma test runner : The main goal for Karma is to bring a productive testing environment to developers. The environment being one where they don’t have to set up loads of configurations, but rather a place where developers can just write the code and get instant feedback from their tests. Because getting quick feedback is what makes you productive and creative. The jasmine test runner: Jasmine is a behavior-driven development framework for testing JavaScript code. It does not depend on any other JavaScript frameworks. It does not require a DOM. And it has a clean, obvious syntax so that you can easily write tests. The karma and jasmine test runner were configured for the project and basic tests were ran. The angular js and angular mocks version in the local development repository was different. This had resulted into a new error been incorporated into the project repo. The 'angular.element.cleanData is not a function' error is thrown in the local development repository. This error happens when the local version of the angular.js and angular-mocks.js doesn't match. The testing framework would test you if the versions f the two libraries is not the same. The jasmine test runner can be accessed from the browser. The karma tests can be performed from the command line. To access the jasmine test runner from the web browser, go to the url http://localhost:7000/test/unit/runner.html To run the karma test suite, run the following command $ karma start The unit tests of the sTeam REST service were done using jasmine. The unit tests were written in coffee script. The preprocessor to compile the files from coffee script to javascript is defined in the karma configuration file. Jasmine Test Runner Jasmine Test Failure First a dummy pass case and a fail case is tested to check there are no errors in the test suite during the test execution. The localstoragemodule.js which is used in the steam service is injected in the test module. Then the steam service version is tested. describe 'Check version of sTeam-service', -> it 'should return current version', inject (version) -> expect(version).toEqual('0.1') steam service should be injected in a global variable as the same service functions shall be tested while performing the remaining tests. Then the steam service is injected and checked whether it exists or not. beforeEach inject (_steam_) -> steam= _steam_ describe 'Check sTeam service injection', -> it 'steam service should exist', -> expect(steam).toBeDefined() The sTeam service has both private and public functions. The private functions cannot be accessed from outside. The private functions defined in the sTeam service arehandle_request and headers. describe 'Check sTeam service functions are defined.', -> describe ' Check the sTeam REST API private functions.', ->…

Continue ReadingsTeam REST API Unit Testing

sTeam API Endpoint Testing

(ˢᵒᶜⁱᵉᵗʸserver) aims to be a platform for developing collaborative applications. sTeam server project repository: sTeam. sTeam-REST API repository: sTeam-REST sTeam API Endpoint Testing using Frisby sTeam API endpoint testing is done using Frisby.  Frisby is a REST API testing framework built on node.js and Jasmine that makes testing API endpoints very easy, speedy and joyous. Issue. Github Issue Github PR sTeam-REST Frisby Test for login Issue-38 PR-40 sTeam-REST Frisby Tests Issue-41 PR-42 Write Tests Frisby tests start with frisby.create with a description of the test followed by one of get, post, put, delete, or head, and ending with toss to generate the resulting jasmine spec test. Frisby has many built-in test helpers like expectStatus to easily test HTTP status codes, expectJSON to test expected JSON keys/values, and expectJSONTypes to test JSON value types, among many others. // Registration Tests frisby.create('Testing Registration API calls') .post('http://steam.realss.com/scripts/rest.pike?request=register', { email: "ajinkya007.in@gmail.com", fullname: "Ajinkya Wavare", group: "realss", password: "ajinkya", userid: "aj007" }, {json: true}) .expectStatus(200) .expectJSON({ "request-method": "POST", "request": "register", "me": restTest.testMe, "__version": testRegistrationVersion, "__date": testRegistrationDate }) .toss(); The testMe, testRegistrationVersion and testRegistrationDate are the functions written in the rest_spec.js. The frisby API endpoint tests have been written for testing the user login, accessing the user home directory, user workarea, user container, user document, user created image,  groups and subgroups. The REST API url's used for testing are described below. A payload consists of the user id and password. Check if the user can login. http://steam.realss.com/scripts/rest.pike?request=aj007 Test whether a user workarea exists or not. Here aj workarea has been created by the user. http://steam.realss.com/scripts/rest.pike?request=aj007/aj Test whether a user created container exists or not. http://steam.realss.com/scripts/rest.pike?request=aj007/container Test whether a user created document exists or not. http://steam.realss.com/scripts/rest.pike?request=aj007/abc.pike Test whether a user created image(object of any mime-type) inside a container exists or not. http://steam.realss.com/scripts/rest.pike?request=aj007/container/Image.jpeg Test whether a user created document exists or not. The group name and the subgroups can be queried. eg. GroupName: groups, Subgroup: test. The subgroup should be appended using "." to the groupname. http://steam.realss.com/scripts/rest.pike?request=groups.test Here "groups" is a Groupname and "gsoc" is a subgroup of it. http://ngtg.techgrind.asia/scripts/rest.pike?request=groups.gsoc Unit Testing the sTeam REST API The unit testing of the sTeam REST API is done using the karma and the jasmine test runner. The karma and the jasmine test runner are set up in the project repository. The karma test runner : The main goal for Karma is to bring a productive testing environment to developers. The environment being one where they don't have to set up loads of configurations, but rather a place where developers can just write the code and get instant feedback from their tests. Because getting quick feedback is what makes you productive and creative. The jasmine test runner: Jasmine is a behavior-driven development framework for testing JavaScript code. It does not depend on any other JavaScript frameworks. It does not require a DOM. And it has a clean, obvious syntax so that you can easily write tests. The karma and jasmine test runner were configured for the project and basic tests were…

Continue ReadingsTeam API Endpoint Testing