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 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.

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 on my personal website. These can be found on Weekly Blogs
All the blogs can also be found on the Fossasia blog.
The list in reverse chronological order is as follows.

Scrums

Scrum reports were posted on the #steam-devel on irc.freenode.net and sTeam google group. The sTeam trello board also has everyday scrum reports.

Further Improvements

  1. sTeam command line lacks the functionality to read and set the object access permissions. sTeam function analogous to getfacl() to change the sTeam server object permisssions.
  2. sTeam debian package for easy installation of the sTeam server. The debian package is yet to be fully packaged.

Special Thanks

  • I would like to thank my mentors Mario Behling, Hong Phuc Dang, Martin Bahr, Trilok Tourani and my peers for being there to help me and guide me.
  • I would like to thank FOSSASIA, sTeam and Pike Community for giving me this opportunity and guiding me in this endeavour.
  • I would also like to thank Google Summer of Code for this experience.

Feel free to explore the repository. Suggestions for improvements are welcomed.

Checkout the FOSSASIA Idea’s page for more information on projects supported by FOSSASIA.

Writing mime-type handlers in Angular

week15gsoc1

Developing a collaboration platform like sTeam web interface requires careful introspection while rolling out features that involve dealing with media. Any collaboration platform must support as many mime-types as possible, The REST API for sTeam written in pike offers us with the feasibilty of knowing the type of file or mime-type in the response object.
sTeam inbuilt has a mechanism which helps in detecting the mime-type of the file. So the same concept has been extended to the rest api in order to get the mime-type combined in the response object.

The first question that arrives at any user’s mind is what are the mime-types should i support, well basically there are couple of mime-types that can or could be considered in the category of compulsory mime-types that are ought to be supported if you wish to have media content on your application. Let us have a look at the popular or well known mime-types :

  • Text
  • PDF’s
  • Image
  • Audio
  • Video

What if we donot catch the mime-type ?
This is basically a classic question that has the most easiest answer, just ensure that the mime-types which your handler is unable to catch pass them with a flag saying that it is an unknown mime-type. So let us have a look at how it is done :


angular.module('steam')

.controller('workspaceDetailedCtrl', ['$http', '$scope', 'handler', 'localStorageService', 'PDFViewerService', '$sce',
 function ($http, $scope, handler, localStorageService, pdf, $sce) {
  $scope.dataSrc = localStorageService.get('baseurl') + 'home/' + localStorageService.get('currentObjPath')

  $scope.mimeTypeHandler = function () {
    if(localStorageService.get('currentObjMimeType') == 'application/x-unknown-content-type') {
      return 'unknown'
    } else if (localStorageService.get('currentObjMimeType').match(/image\/*/)) {
      return 'image'
    } else if (localStorageService.get('currentObjMimeType') == 'application/pdf') {
      return 'pdf'
    } else if (localStorageService.get('currentObjMimeType').match(/audio\/*/)) {
      return 'audio'
    } else if (localStorageService.get('currentObjMimeType').match(/video\/*/)) {
      return 'video'
    } else if (localStorageService.get('currentObjMimeType').match(/text\/*/) ||
      localStorageService.get('currentObjMimeType') == 'application/x-javascript' ||
      localStorageService.get('currentObjMimeType') == 'application/x-pike') {
      return 'text'
    } else { return 'notfound' }
  }


The best approach for writing a mime-type handler for your application would be :

  • Have a controller that has a function declared for doing the specific operation and pass the mimetype for the object that which you identify, so that the handler can simplify your job in just returning the type of your file
  • Ensure that as many well known mime-types are supported and for the case of new mime-types that depend for specific application just add them to the if...else block
  • Make it a point to catch all the unknown mime-types because when an unknown mime-type is not declared in your handler the browser tends to download the file directly instead of opening the same in your application

NOTE : The service provider localStorageService is very helpful if you have an application that needs to store some data on the user’s/client’s end. So while the user logs into the web interface , localStorageService sets the userpath, objectmimepath and everything else in order to complete the functionality of the application. So gotcha here is that when you have a situation like this localStorageService0 can be useful, since we can both set the data and get the data. Once the user logs out the data is cleared.

Thats it folks,
Happy Hacking !!

 

Managing multiple states with ui.router

week14gsoc1

Most of the angular applications today have an application router for dealing with the routes of the application. So the web interface for sTeam had the usage of ui.router a library for helping people write routers for complex and big applications. So before i contextualize the usage of ui.router and also give an essence of how routing works with ui.router let us just have a look at the syntax :


angular.module('steam', 'ui.router')

.config(['$locationProvider', '$stateProvider', '$urlRouterProvider', '$provide',
  function ($locationProvider, $stateProvider, $urlRouterProvider, $provide) {

.state('state_name', {
  url: '/route_goes_here',
  templateUrl: '/path_to/templates_go_here.html',
  controller: 'controller_comes_here',
  requireLogin: false || true // depending on the requirement
 })

}])

In the above snippet we can see how to initialize a bare minimum router for an angular application. But to use the ui.router for couple of routes is very much not using the router to the fullest of the features.What are states ?
$state is nothing but a service which is part of the ui.router module. So it can be considered as a service that is responsible for transitioning states accordingly from one state to another. There are many types of states that we can deal with while writing a router for a complex application that deals with multiple and nested states.

  • parent State
  • sibling State
  • grand child state

The parent states generally go with the normal implementation, all we have to use is the state name while declaring the state. But things are not same with sibling state and grandchild state. Let us have a look as to how things are different with them :


// sibling state
.state('^.sibling_name_goes_here', {
  url: '^/route_goes_here',
  templateUrl: '/path_to/templates_go_here.html',
  controller: 'controller_comes_here',
  requireLogin: false || true // depending on the requirement
 })

// grand child state
.state('^.sibling_name_goes_here.grandchild_name_goes_here', {
  url: '^/route_goes_here/:path',
  templateUrl: '/path_to/templates_go_here.html',
  controller: 'controller_comes_here',
  requireLogin: false || true // depending on the requirement
 })

How should multiple routes be handled and how should views be added to the config ?
As explained in my previous article there is a way to use the ui-view in order to write reusable components for the angular application. So let us have a look at how views are to be added to the router’s config :


// state with views
.state('state_name_goes_here', {
  url: '/route_goes_here',
  requireLogin: true || false, // depending on the requirement
  views: {
    'view_name_goes_here': {
      templateUrl: '/path_to/templates_go_here.html',
      controller: 'controller_name_goes_here'
    },
    'view_name_goes_here': {
      templateUrl: '/path_to/templates_go_here.html',
      controller: 'controller_name_goes_here'
    },
    'view_name_goes_here': {
      templateUrl: '/path_to/templates_go_here.html',
      controller: 'controller_name_goes_here'
    }
  }
})

NOTE : We can have the possibility of an application that has a silbing route and all the routes of the parent route are inherited to the sibling route. Enabling this to happen is the beauty of ui.routerNow taking the above syntax we can just add more and more states to the config. It is pretty much that easy to write router config for an application dealing with multiple states. Therefore taking this ahead we can write application router’s for applications that need to handle many routes, but the point here is to understand the point of how the ui.router can be leveraged to the maximum in order to take the best of its features.

Thats it folks,
Happy Hacking !!

Nested views and templates in Angular

week13gsoc1

sTeam web interface is a perfect example of an Angular application that has multiple views to deal with. The router for sTeam is built using ui.router, which is a classic library for dealing with applications that might have a combination of both parent and child routes that are ought to be reused.

What is the difference between ui-view and ng-view ?
Generally we often get confused with the concept of view when it is used with a router and when it is used inside for injecting templates. The concept of view is simple, it acts like a small placeholder so that we can co-relate or place particular piece of DOM in a required location.
So to understand this better and clear the confusion we must first know how views and templates work. So the web interface for sTeam uses ui.router as a result the concept of ui-view differs from ng-view.
Both of these afore mentioned have different service provides while ui-view belongs to ui.router, ng-view belongs to the default angular’s ngRouter

How do we implement them ?
We must understand that we have three things involved while writing views using ui.router. Let us look at them carefully

  • router
  • template
  • view

Let us suppose the below is an example of the view that contains the configuration in the router


.state('workarea.list', {
  url: '^/room/:path',
  requireLogin: true,
  views: {
    'options': {
      templateUrl: '/views/options.html',
      controller: 'optionsCtrl'
    },
    'workspaceList': {
      templateUrl: '/views/workspaceList.html',
      controller: 'workspaceListCtrl'
    },
    'comments': {
      templateUrl: '/views/comments.html',
      controller: 'commentsCtrl'
    }
  }
})

Let us now have a look at the html


  div class="row"
    div class="col-lg-2"
    div
    div class="col-lg-10"
      legend class="text-left">Comments
      legend
      form class="form-horizontal"
        div class="form-group"
          div class="col-sm-10"
            input class="form-control" type="text" ng-model="commentContent" required id="searchMe"
            span
            span
          div
          div class="col-sm-2"
            button type="button" class="btn btn-primary" ng-click="addComment();">Submit
            button
          div
          div
            ul id="comments"
          
        ul
      div
    div
  form
div
div

Now since we have the html written, we can use the same in the same state that which we have declared in the router we are ready to use the view. Let us observe how should the route be used :


div ui-view="comments" div

So if we carefully observe the ui-view attribute we can see that the name of the view is being written, so accordingly we must declare the name in that place in order to use that view.

Thats it folks,
Happy Hacking !!

Integrating textAngular to Angular applications

week12gsoc1

In the previous article we have seen how handling different mime types is important, So while extending that discussion one might think what is the case of files that come under a completely different aspect, As in scripts, documents etc have dynamic operations that are performed over them.
sTeam's old web interface gave the user the provision for creating and editing the documents within the interface. So in short the user had complete control over the documents as he didn’t have to go through complex process for altering documents that which are stored in his/her playground.

The sTeam web interface has a controller in the workspace called workspaceDetailedCtrl which basically comprises of a function called mimeTypeHandler that helps in matching the mime-type and performing the required action if it matches a particular mime type. So let us have a look as to how should one design such things;


$scope.mimeTypeHandler = function () {
	if(localStorageService.get('currentObjMimeType') == 'application/x-unknown-content-type') {
		return 'unknown'
	}
	else if (localStorageService.get('currentObjMimeType').match(/image\/*/)) {
		return 'image'
	}
	else if (localStorageService.get('currentObjMimeType') == 'application/pdf') {
		return 'pdf'
	}
	else if (localStorageService.get('currentObjMimeType').match(/audio\/*/)) {
		return 'audio'
	}
	else if (localStorageService.get('currentObjMimeType').match(/video\/*/)) {
		return 'video'
	}
	else if (localStorageService.get('currentObjMimeType').match(/text\/*/) ||
		localStorageService.get('currentObjMimeType') == 'application/x-javascript' ||
		localStorageService.get('currentObjMimeType') == 'application/x-pike') {
		return 'text'
	}
	else { return 'notfound' }
}

So before we go and understand about developing a text editor let us understand the library that is used for developing it. textAngular is the library that which is used for developing the text editor, although there are many options textAngular proves to be a minimal text editing development source that can be easily setup and broadly configured.

We all know that a text editor must have the following things necessarily :

  • It must support basic formatting options and must extend feasibility to make changes to the document in a easier way
  • Enabling live preview in order to see the changes made to the document instantly
  • Supporting indentation options for documents which are identified as scripts

We might feel that the technicalities are important apart from these notions, but it is important to have these in place along with the technicalities.

Let us observe the syntax and usage of text angular.


angular.module('steam')

  .controller('workSpaceEditorCtrl', ['$scope', 'handler', 'localStorageService', 'textAngularManager', '$document',
   function ($scope, handler, localStorageService, textAngularManager, $document) {
    $scope.data = {
      empty: 'Please enter text',
      full: ''
    }
    $scope.editable = true;
    $scope.content = $scope.data.empty;

    $scope.allh1 = function() {
      textAngularManager.updateToolDisplay('h1', {
        buttontext: 'Heading 1'
      });
    }

    $scope.allh2 = function() {
      textAngularManager.updateToolDisplay('h2', {
        buttontext: 'Heading 2'
      });
    }

    $scope.allh3 = function() {
      textAngularManager.updateToolDisplay('h3', {
        buttontext: 'Heading 3'
      });
    }

    $scope.allh4 = function() {
      textAngularManager.updateToolDisplay('h4', {
        buttontext: 'Heading 4'
      });
    }

    $scope.allh5 = function() {
      textAngularManager.updateToolDisplay('h5', {
        buttontext: 'Heading 5'
      });
    }

    $scope.allh6 = function() {
      textAngularManager.updateToolDisplay('h6', {
        buttontext: 'Heading 6'
      });
    }

    $scope.submit = function () {
      console.log("The document has been submitted");
    }
    $scope.clear = function () {
      console.log("The document has been reset");
      $scope.data = {
        orightml: $scope.content
      }
    }
    $scope.resetEditor = function () {
      textAngularManager.resetToolsDisplay();
    }
  }])

So if we observe we can see that there is a service called textAngularManager which is needed for customizing the text editor. There are a few things that are to be looked upon while customizing the editor.

  • We can totally customize the text editor’s options as well as the appearence of the text editor
  • We can give scope for customized functions that could be part of the controller. Observe the above code snippet where functions like resetEditor etc are customized to the needs of the application
  • Finally We can add more options to the text editor using the textAngular service in order to make it better

After all the customizations and changes Here is how it looks:

week12gsoc2

Source : click here

Thats it folks,
Happy Hacking !!

Developing a pdf viewer in AngularJs

week11gsoc1

Handling different mime types and giving support to them is quite important when a collaboration platform is being developed. Previously sTeam web UI had essential components like :

  • image viewer
  • audio player
  • video player

So in the process of developing new components and adding support for different mime types a PDF viewer grew out as a possibility. So the concept of a PDF viewer is quite simple, it just helps you to display, control all the files that come with the mime-type application/pdf.

The process as a whole is quite simple in developing the pdf viewer. Let us have a look at the process;

  • We have to utilize the PDFViewerService in order to build the PDF viewer
  • The configuration variables are pretty much few in number, although it is very necessary to look after what URI is being passed to the pdfURL variable as it is solely responsible for loading the content from the file.
  • Using the pdf viewer instance is pretty much simple as we have to declare the instance viewer first and then use the same $scope.instance for performing operations like :
    1. Going to the next page
    2. Going to the prev page
    3. Going to a particular page
    4. Displaying the total number of pages loaded
    5. Displaying the progress of the loaded files
  • Lastly there is one important thing to be noted, ngPDFViewer is comparitively a light weight library that could be used for development of a PDF viewer although when the application is bloated with large sized PDF’s it takes couple of seconds to load the PDF. A smart move here would be using the $scope.currentPages and $scope.totalPages in order to make a small calculation and display it at the users end as to how much percentage of the file is loaded.

angular.module('steam', [ 'ngPDFViewer' ])
.controller('workspaceDetailedCtrl', [ '$scope', 'PDFViewerService', function($scope, pdf) {
  $scope.pdfURL = "test.pdf"
  $scope.instance = pdf.Instance("viewer")

  $scope.nextPage = function() {
    $scope.instance.nextPage()
  }
  $scope.prevPage = function() {
    $scope.instance.prevPage()
  }
  $scope.gotoPage = function(page) {
    $scope.instance.gotoPage(page)
  }
  $scope.pageLoaded = function(curPage, totalPages) {
    $scope.currentPage = curPage
    $scope.totalPages = totalPages
  }
  $scope.loadProgress = function(loaded, total, state) {
    console.log('loaded =', loaded, 'total =', total, 'state =', state)
  }
}]);

Here is the final outcome of it:

week11gsoc2

week11gsoc3

Source : click here

Thats it folks,
Happy Hacking !!

Unit testing angular applications with jasmine

week10gsoc1

In the previous article i have addressed about writing tests with frisby. Frisby is helpful in writing tests for angular applications that have active communications involving RESTful api’s. So more or less frisby is helpful as an API testing tool.

The sTeam web interface actively talks to a REST api written in pike along with controllers that make the entire application a complete collaboration platform. So in order to test the working ability of individual units of code, it was necessary to have unit tests written for the application.

What is unit testing really ?
In order to validate different segments of the same code base or isolated parts of the code base we have a testing mechanism called Unit testing which extends the afore mentioned idea of having individual or isolated pieces of code that constitute as units that are tested and ensured that they are working properly.
NOTE: It is always a good practice to write unit tests for your code base in order to ensure that all the individual segments as well as the entire code base is working without flaws.

What is jasmine and how is it related ?
Jasmine is a unit testing framework which is helpful in writing unit tests for applications and it is combined with a test runner called Karma in order to run/execute the tests so written. Now to put things in a simpler perspective, jasmine is test framework which we are going to use, but to run these tests so written we must a test runner that shall execute and give us the outcome of the tests so written with the help of the afore mentioned framework.
NOTE: Jasmine has its own syntax and code conventions.

Is it really going to help ?
Yes, let me give an example to illustrate the effect of writing unit tests. Let’s suppose we have an angular application and it involves controllers, directives etc etc. Now in order to quantify that communication is happening between all the components and the process as a whole is not broken we must first ensure that in the chain of communication the previous functionalities are not effecting components that are connected further and also whilst validating that the code is not breaking there has to be some proof to support the quantification which we before established. Therefore writing unit tests will help us to prove all of that.

Syntax and style :


'use strict';

describe('controllers', function(){

  beforeEach(module('sTeam.controllers'));

  it('should ....', inject(function() {
    // here the test specs go
  }));

  it('should ....', inject(function() {
    // here the test specs go
  }));
});

Let’s go ahead and test a real directive


'use strict';

describe('directives', function() {

  beforeEach(module('sTeam.directives'));

  describe('fileModel', function() {
    it('Must give the flag whether the file upload directive is working or not', function() {
      module(function($provide) {
        $provide.value('model', 'attrs.fileModel');
      });
      inject(function($compile, $rootScope) {
        var DOM = $compile("the html goes here")($rootScope);
    	$rootScope.$digest();
    	expect(element.status()).toEqual('something');
      });
    });
  });
});

Basically in the above example we are testing a unit of the sTeam web interface, a file uploader. It is basically a directive written in order to upload files to the web interface.

So the unit test comprises of a function called $inject which is responsible for injected the DOM code which we wish to test, and then compile the HTML. So after compiling the HTML we have a function called expect which is used for checking whether the desired output is obtained in the DOM or not.

Source : fileModel.js

Thats it folks,
Happy Hacking !!

Angular API testing with frisby and jasmine-node

week9gsoc1

sTeam-web-UI is an application written in angular. So the application relies on sTeam's existing REST api which is written in pike. Since there are a lot of API calls and actions involved ensuring that the application is making proper API calls and getting proper responses is crucial. In order to go ahead with the API testing there are two important things to be know about first.

  • frisby
  • jasmine

What is frisby ?

“Frisby is a REST API testing framework built on node.js and Jasmine that makes testing API endpoints easy, fast, and fun. Read below for a quick overview, or check out the API documentation.”

What is Jasmine ?

“Jasmine is a Behavior Driven Development testing framework for JavaScript. It does not rely on browsers, DOM, or any JavaScript framework. Thus it’s suited for websites, Node.js projects, or anywhere that JavaScript can run.”

The api methods present in frisby can be categorized into :

  • Expectations
  • Helpers
  • Headers
  • Inspectors

So let me show couple of tests that are written with the help of frisby for the sTeam's web interface.

Checking the Home directory of the user :


frisby.create('Request `/home` returns proper JSON')
  .get(config.baseurl + 'rest.pike?request=/home')
  .expectStatus(200)
  .expectJSON({
    'request': '/home',
    'request-method': 'GET',
    'me': objUnit.testMeObj,
    'inventory': function (val) {
      val.forEach(function (e) {
        objUnit.testInventoryObj(e)
      })
    }
  })
.toss()

Checking the container of the user :


frisby.create('Request `/home/:user` returns proper JSON')
  .get(config.baseurl + 'rest.pike?request=/home/akhilhector/container')
  .expectStatus(200)
  .expectJSON({
    'request': '/akhilhector',
    'request-method': 'GET',
    'me': objUnit.testMeObj,
    'inventory': function (val) {
      val.forEach(function (e) {
        objUnit.testInventoryObj(e)
      })
    }
  })
.toss()

Accessing the file in the user’s workarea :


frisby.create('Request `/home/:user/:container/:filename` returns proper JSON')
  .get(config.baseurl + 'rest.pike?request=//home/akhilhector/playground-hector/icon1.png')
  .expectStatus(200)
  .expectJSON({
    'request': '/akhilhector/playground-hector/icon1.png',
    'request-method': 'GET',
    'me': objUnit.testMeObj,
    'inventory': function (val) {
      val.forEach(function (e) {
        objUnit.testInventoryObj(e)
      })
    }
  })
.toss()

Observing the above three modules, each of them are different from one another. We have to understand that depending on the API the request payload must be sent. So for suppose the API needs authentication headers to be sent then we need to use the proper helper methods of frisby in order to send the same.
The .get() can be substituted with put, post, delete. Basically all the 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 response.
Apart from the request payload there is an interesting thing with the helper method expectJSON, it is used for testing the given path or full JSON response of the specified length. In order to use expectJSON we must pass the path as the primary argument and the JSON as the second argument.
The expectStatus helper method is pretty straightforward. It helps us in determining the HTTP Status code equivalent of the request so made.

NOTE While writing the tests it is better to put all the config in one place and use that config variable for all the operations.

Thats it folks,
Happy Hacking !!

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: "[email protected]",
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

FrisbyTests

FrisbyTestCount

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.

Angular Unit-Testing: TypeError ‘angular.element.cleanData is not a function’

When angular and angular-mocks are not of the same version, these error occurs while running the tests. If the versions of the two javascript libraries don’t match your tests will be testing to you.

The jasmine test runner can be accessed from the browser. The karma tests can be performed from the command line. These shall be enhanced further during the course of work.

Feel free to explore the repository. Suggestions for improvements are welcomed.

Checkout the FOSSASIA Idea’s page for more information on projects supported by FOSSASIA.

Developing Image Viewer in Angular JS

week8gsoc0

In the previous article i have addressed about developing audio and video players for sTeam. To know more about developing audio and video players, click here. This article is an extension to the previous one, as to how one could develop image viewer in angular.
Since sTeam is a collaboration platform there was the necessity of having an image viewer. So in angular bootstrapLightbox is very useful in building image viewers, galleries, sliders etc.

Implementation Strategy :
There are basically two things involved in developing this;

The Controller

angular.module('steam', [ 'bootstrapLightbox', 'ui.bootstrap' ])
  .controller('steamImageViewer', ['$scope', 'Lightbox', function($scope, Lightbox) {
    $scope.images = [
    {
      'url': 'https://societyserver.org/home/akhilhector/playground%20-%20hector/icon1.png',
      'title': 'icon1.png'
    },
    {
      'url': 'https://societyserver.org/home/akhilhector/playground%20-%20hector/icon3.jpg',
      'title': 'icon3.jpg'
    },
    {
      'url': 'https://societyserver.org/home/akhilhector/playground%20-%20hector/icon4.png',
      'title': 'icon4.png'
    },
    {
      'url': 'https://societyserver.org/home/akhilhector/playground%20-%20hector/icon4.jpg',
      'title': 'icon4.jpg'
    }
    ];
    $scope.imageViewer = function (index) {
      Lightbox.openModal($scope.images, index);
    };
  }]);

Observe the controller over here, we pass an array of images or a single image to an array object and then we use the same for our DOM. Options like URL, Title, and Thumbnail can be passed in the same object. In the same controller we need to write another function that uses the LightBox service in order to open a modal and serve the image which was passed as an URL. So the modal displays whatever source is being passed as an argument. Also if we are using a REST api for retrieving the images then we can have a we can have similar array object that stores all the information recieved from the api response. In order to better this, there can be a mime-handler written so that if an unknown/unsupported mime type is being requested for, then an error can be popped.

The HTML

<div class="row" ng-controller="steamImageViewer">
    <div class="col-md-12" ng-repeat="image in images">
        <div class="roomItem">
            <div class="roomItemIcon roomItemBlue"><i class="fa fa-image"></i>
            </div>
            <div class="itemText"> {{image.title}} <a href="#" ng-click="imageViewer($index)">view</a>
            </div>
        </div>
    </div>
</div>

The above DOM seems pretty straight forward, we use the help of the function which we previously wrote in the controller in order to get the data. So as soon as we click the Lightbox modal fires and displays the image. It is to be observed that this implementation goes with consideration that there are an array of images that are ought to be retrieved, but the same logic wouldn’t be fruitful for displaying a single image. In order to acheive that we can pass the image object to the $scope and use the same for displaying the image. And minor changes in the HTML will help displaying a single image instead of an array of images.

So here is how it looks :

week8gsoc3

week8gsoc2

week8gsoc1

Thats it folks,
Happy Hacking !!