понеделник, 5 октомври 2015 г.

Jasmine Clock

Today I had to write unit tests for JavaScript time dependent code. I liked that Jasmine supported a way to make setTimeout or setInterval to behave synchronously. When we install clock with jasmine.clock().install(); into beforeEach we change behaviour of setTimeout and setInterval functions to be synchronous.
After this we can move forward in time like using time machine and check result of asynchronous process. We can go into future with jasmine.clock().tick function, which takes a number of milliseconds. This is small example code:

TimeoutSpec.js
1    describe("Jasmine Clock demo", function () { 
2     
3        // It is installed with a call to jasmine.clock().install  
4        // in a spec or suite that needs to manipulate time. 
5        beforeEach(function () { 
6            jasmine.clock().install(); 
7        }); 
8     
9        // Be sure to uninstall the clock after you are done  
10       // to restore the original functions. 
11       afterEach(function () { 
12           jasmine.clock().uninstall(); 
13       }); 
14    
15       it("setTimeout must behave synchronously", function () { 
16           var array = [1, 2, 3, 4, 5, 6]; 
17           var sum = 0; 
18           (function _handleArray() { 
19               sum += array.shift(); 
20               if (array.length != 0) { 
21                   setTimeout(_handleArray, 0); 
22               } 
23           }()); 
24    
25           // The cool part  
26           // We have something like 
27           // time machine and can  
28           // move time forward.  
29           jasmine.clock().tick(200); 
30           // 1 + 2 + 3 + 4 + 5 + 6 
31           // is equal to 21 
32           expect(sum).toEqual(21); 
33       }); 
34   }); 
35   
And here can be viewed this code: http://gonaumov.github.io/jasmineClockDemo/ running into Jasmine 2.3.4 with spec file.

четвъртък, 27 август 2015 г.

Get rid of crossdomain origin errors.

When developers work on web applications under Windows there are often crossdomain  origin errors. The old version of  Google Chrome browsers provides a  usefull feature
--disable-web-security command line argument for  chrome.exe but unfornatelly this option was deprecated.  When you try to use it under current version of Chrome
- Version 44.0.2403.157 m you will get the following error:
"You are using an unsupported command-line flag:   --disable-web-security. Stability and security will suffer.". I tried to download current Chromium build   but with no luck - this errors appear again. After a small time thinking I'm came to a solution that I want to share with other people with a similar problem. I download Opera that is based on Chrome. Under Opera this command line option
 works like a charm and you have the same tools available.  Even an emulator for mobile devices.


Here is small demo. Get response from yahoo when google is open. Executing of this small snippet
from console.

(function() {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
console.log(xhr.responseText);
}
}
xhr.open('GET', '//www.yahoo.com/', true);
xhr.send();
}());

And here is the result: 


But if you want to use just a Google Chrome I write this script to make the starting of Google Chrome browser without security much easier than it was before. The script checks if there is running instances of chrome.exe and if there is a present instance, alerts the user that the running instance must be killed before Google Crome is started. If the user clicks on Yes button, the script will kill all instances of chrome.exe. After this, will open a new browser instance without security. If the user clicks on No button, the script will do nothing. If there is no present running instance of chrome.exe, the script will start Google Chrome without security. How to use it? Just clone this repository and fill correct path to chrome.exe. The script is tested on windows 8 with admin rigths. Don't hesitate to write to me with suggestions and feature requests.
https://github.com/gonaumov/chromeRunner

събота, 13 юни 2015 г.

Cucumber-js and Chai how to expect if element with given selector exist in DOM

This week I had one problem with protractor and cucumberjs. I read protractor documentation and asked question into stackoverflow. I want to share one very small learned lesson here also. If you want to expect if element with a given selector exist in DOM you must use isPresent() it returns a promise that will resolve to whether the element is present on the page.

    element(by.id('someId')).isPresent().then(function(isElementVisible) {
         expect(isElementVisible).to.be.true;   
    });
 
Or use chai with promises.

    expect(element.isPresent()).to.eventually.be.false
 
However, the word "eventually" sounds unpleasant. We want to be sure not eventually sure. :)
Here can be viewed the quesion into stackoverflow.  

вторник, 2 юни 2015 г.

Емилиян Кърчев и http://energyaudit.bg

Емил или за възпитанието. Горкият Русо. Това е цитат от Богомил Райнов. Не е измислен от мен. Викнахме въпросният господин да направи експертиза на един теч, който излезе в следствие на направен ремонт. Решихме, че сайта му е най-представителен и изглежда най-професионално от всички. На сайта на господина няма цени. Казал е на жена ми цена от 138лв. Аз дойдох след работа, за да може да се извърши диагностиката, но не бях чул добре цената, която трябва да се плати.  Бях чул нещо от сорта на 174лв. Е дадох му 180лв с идеята, че ще си хване, колкото му трябват. Господина си ми пусна касова бележка за 180лв. След това разправял на жена ми, че за да ни пусне констативен протокол трябвало да чукне още 48лв а снимките се обработвали със специален софтуер. Не, че е кой знае какъв проблем де, но е важен принципа в крайна сметка. Браво Емо. Тия 50лв. да ги дадеш за лекарства. Ето го и сайта на господина.
Промяна от 04.06.2015г.
Да допълня. Това, че няма цени на сайта не отговаря на истината. Мое недоглеждане. Денят ми беше твърде зает, за да гледам сайта на господина. По тази причина и му дадох 180лв с идеята да си хване колкото е цената, както съм писал по-горе. Притежавам и касова бележка за сумата. По долу показвам и текущите цени на сайта на господина.
Сметката пак не излиза. При промяна цените спрямо тази дата (03.06.2015г) могат да бъдат извлечени от всеки кеш на търсеща машина.

неделя, 5 октомври 2014 г.

Bot for sexgangsters game.

I love to write user scripts. These days I have some fun to write bot for a very nice online game. From the programming perspective interesting part is the use of MutationObserver, with his help the programmer easily can detect changes in the DOM structure.
I made the bot as a add-on for Mozilla Firefox and set as a project in github. There are some issues, which I'll fix in my spare time.
https://github.com/gonaumov/sexGangstersBizBot

вторник, 12 август 2014 г.

Dynamic routing in AngularJS App.config method.

Some time ago I had a work task required to make dynamic routing in App.config method of AngularJS application. Initially I wanted to do something like this:

someApp.config(['$routeProvider', '$httpProvider', 
    '$compileProvider', 'settings',
    function ($routeProvider, $httpProvider, 
        $compileProvider, settings) {

        var $http = angular.injector(['ng']).get('$http');
        var $q = angular.injector(['ng']).get('$q');
        var isUserLogged = $q.defer();

        $http.get(settings.apiUri + settings.loginStatus).
          success(function (data) {
            if (data.status == "NOT_LOGGED") {
                isUserLogged.reject();
            } else {
                isUserLogged.resolve();
            }
        });

        isUserLogged.promise.
          catch(function () {
             $routeProvider.
                 when('/home', {
                     templateUrl: 'partials/home.html',
                     controller: 'HomeController'
                 }).
                 otherwise({
                 redirectTo: '/home'
             });
        });

        isUserLogged.promise.
         then(function () {
            $routeProvider.
                when('/accountsettings', {
                    templateUrl: 'partials/accountsettings.html',
                    controller: 'AccountSettingsController'
                }).
                otherwise({
                    redirectTo: '/accountsettings'
                });
        });
    }]);

But routing did not work because .config method behaves as synchronous. When I remove the http query and promice logic everything worked perfectly. I asked a question in stackoverflow, but there was no answer. After reading the documentation and digging I came to the decision that satisfy me. I did a manual bootstrapping of the application. First I make request to determine whether the user is logged or not. Then I trigger custom event listener whose call .config method of application and do routing in accordance whether the user is logged or not. Below is the code of the decision to which I got (with abbreviations).

angular.element(document).one("userStatusIsCheked", 
                        function(event, userIsLogged) {
    appName.config(['$routeProvider', 
        '$httpProvider', '$compileProvider',
        function ($routeProvider, 
         $httpProvider, $compileProvider) {
            if (userIsLogged == true) {
                $routeProvider.
                    when('/resetpassword/:hashValue', {
                        templateUrl: 'partials/home.html',
                        controller: 'ResetPasswordController'
                    }).
                    when('/accountsettings', {
                        templateUrl: 'partials/accountsettings.html',
                        controller: 'AccountSettingsController'
                    }).
                    when('/changepassword', 
                      {
                        templateUrl: 
                        'partials/accountsettingschangepassword.html',
                        controller: 'ChangePasswordController'
                    }).
                    when('/edit', {
                        templateUrl: 'partials/accountsettingsedit.html',
                        controller: 'EditAccountController'
                    }).
                    when('/apikeymanagement', {
                        templateUrl: 'partials/apikeymanagement.html',
                        controller: 'APIKeyManagementController'
                    }).
                    when('/dashboard', {
                        templateUrl: 'partials/dashboard.html',
                        controller: 'DashboardController'
                    }).
                    when('/pipelines', {
                        templateUrl: 'partials/pipelines.html',
                        controller: 'PipeLinesController'
                    }).
                    when('/preferences', {
                        templateUrl: 'partials/preferences.html',
                        controller: 'PreferencesController'
                    }).
                    when('/reports', {
                        templateUrl: 'partials/reports.html',
                        controller: 'ReportsController'
                    }).
                    when('/logout', {
                        templateUrl: 'partials/logout.html',
                        controller: 'LogoutController',
                        resolve: {
                            logout: function (logout, $q) {
                                var deferred = $q.defer();
                                logout()['finally'](
                                    function() {
                                        deferred.resolve();
                                    }
                                );
                                return deferred.promise;
                            }
                        }
                    }).
                    when('/privacy', {
                        templateUrl: 'partials/privacy.html',
                        controller: 'PrivacyController'
                    }).
                    when('/tos', {
                        templateUrl: 'partials/tos.html',
                        controller: 'TosController'
                    }).
                    when('/currentStatus', {
                        templateUrl: 'partials/currentStatus.html',
                        controller: 'CurrentStatusController'
                    }).
                    otherwise({
                        redirectTo: '/dashboard'
                    });

            } else {
                /**
                 * If user is not logged default action is
                 * home.
                 */
                $routeProvider.
                    when('/home', {
                        templateUrl: 'partials/home.html',
                        controller: 'HomeController'
                    }).
                    when('/resetpassword/:hashValue', {
                        templateUrl: 'partials/home.html',
                        controller: 'ResetPasswordController'
                    }).
                    when('/privacy', {
                        templateUrl: 'partials/privacy.html',
                        controller: 'PrivacyController'
                    }).
                    when('/tos', {
                        templateUrl: 'partials/tos.html',
                        controller: 'TosController'
                    }).
                    when('/currentStatus', {
                        templateUrl: 'partials/currentStatus.html',
                        controller: 'CurrentStatusController'
                    }).
                    otherwise({
                        redirectTo: '/home'
                    });

            }
        }]);

        angular.bootstrap(document, ['appName']);
});

angular.element(document).ready(function() {
    var injector = angular.injector(['appName']);
    var settings = injector.get('settings');
    var $http = injector.get('$http');

    var functionFactory = function (userStatus) {
        return function () {
            this.lUserStatus = userStatus;
            return this.lUserStatus;
        }
    };

    /**
     * So here we will check if user is logged or
     * not and after this construct conditional routing
     * into config method (above).
     */
    $http.get(settings.apiUri + settings.loginStatus).
             success(function (data) {
        if(angular.isDefined(data.status) && 
            data.status == "NOT_AUTHENTICATED") {
            appName.service('userIsLogged', functionFactory(false));
            angular.element(document).trigger("userStatusIsCheked", [false]);
        } else if(angular.isDefined(data.status) && data.
                status == "AUTHENTICATED") {
            appName.service('userIsLogged', 
            functionFactory(true));
            angular.element(document).trigger("userStatusIsCheked", [true]);
        }
    });
});


Hope this helps someone with a similar problem.

New site dedicated to web development

My wife and I started to create a website dedicated to the development for the web. We hope that this site will be useful to all interested in the subject design and programming. http://codinghunters.com/