Wednesday 28 November 2012

Grails: Use of @Mixins in Controller/Services and unit testing methods that uses the mixin methods

So I spent an hour today trying to see why my tests are failing. I have a @Mixin in my service class and I was writing a unit test for a method that calls the mixin method. However, it was giving errors like these:
testPaymentTypes_exception_in_getting_payment_types(PaymentServiceTests)
|  groovy.lang.MissingMethodException: No signature of method: com.originfunds.service.PaymentService.extractExceptionMessage() is applicable for argument types: (java.lang.Exception) values: [java.lang.Exception: exception]
Turns out the problem is that in Grails 2.0, the unit testing infrastructure of Grails cleans up the meta classes between test runs. Therefore, to solve the problem, put this in your setUp clause: void setUp() { MyController.metaClass.mixin(LogTrait) }

Saturday 24 November 2012

Caution: extending Knockout's default bindings

So I'm working on a feature that requires that every input be sent to the server after a user types in the data. What a better way than to decorate the default "value" binding. My initial binding looks like this:
                     ko.bindingHandlers.trackedInput = {  
                          init : function(element, valueAccessor, allBindingsAccessor) {  
                               ko.bindingHandlers.value.init(element, valueAccessor, allBindingsAccessor);  
                          },  
                          update : function(element, valueAccessor) {  
                               track($(element));  
                               ko.bindingHandlers.value.update(element, valueAccessor);  
                          }  
                     }  
However, when I ran this, I got this error:
Uncaught TypeError: undefined is not a function
Upon digging into the source code, I found that the default 'value' binding actually requires a 3rd param that needs to passed in. So the correct way is this:
 ko.bindingHandlers.trackedInput = {  
                          init : function(element, valueAccessor, allBindingsAccessor) {  
                               ko.bindingHandlers.value.init(element, valueAccessor, allBindingsAccessor);  
                          },  
                          update : function(element, valueAccessor) {  
                               track($(element));  
                               ko.bindingHandlers.value.update(element, valueAccessor);  
                          }  
                     }  
                     vm = {choice : ko.observable()};  
                     ko.applyBindings(vm);  
                });  

Tuesday 20 November 2012

Grails unit test: | java.lang.NullPointerException: Cannot get property 'principal' on null object

So I have a controller that uses a command object as the param and the controller also uses the springSecurityService and am writing a test to cover the flow. For the life of me, if I don't call .validate() on the mocked command object, I get an error stating that the injected springSecurityService is null:
|  java.lang.NullPointerException: Cannot get property 'principal' on null object
Somebody else had a similar problem and their solution is to to an outright mock: http://stackoverflow.com/questions/10275803/how-to-mock-a-service-injected-in-a-domain-class-from-a-controller-test-class However, the springSecurityService seems to be populated when I call the mockCommandObject().validate()

Friday 16 November 2012

Knockout.js - Calling default foreach in a custom binding

So I created a binding that handles loading images asychroniously and I wanted to have a spinner to load while it's waiting. Initially I came up with something like this:

 ko.bindingHandlers.asyncImgs = {
  init: function (element, valueAccessor) {
   $(element).spin();
  },
  update: function (element, valueAccessor) {
      var value = ko.utils.unwrapObservable(valueAccessor());
      if (value) {
          $(element).spin(false);
                ko.bindingHandlers.foreach.update(element.firstElementChild, valueAccessor);           
         }
  }
 }
And my html looks like this:
      <div class="gifts" style="height: 220px; border: 1px solid" data-bind="asyncImgs: offer_${standardProduct.productIdIndirect}_gifts" data-for="${standardProduct.productIdIndirect}">  
           <div class="gift" data-bind="foreach: $data">  
                <img data-bind="attr: {src: image}"/>  
                <span data-bind="text: description"/>  
           </div>  
      </div>  
But the above doesn't work! The reason for this is because of the fact that we're not passing in the full context that the foreach binding needs. To fix it and to get it working, I had to pass in the following params (note this is only for v2.0.0+ of Knockout).

 ko.bindingHandlers.asyncImgs = {
  init: function (element, valueAccessor) {
   $(element).spin();
  },
  update: function (element, valueAccessor, allBindings, viewModel, context) {
      var value = ko.utils.unwrapObservable(valueAccessor());
      if (value) {
          $(element).spin(false);
                ko.bindingHandlers.foreach.update(element.firstElementChild, valueAccessor, allBindings, viewModel, context);           
         }
  }
 };

Problem installing ruby on Ubuntu server: "It seems your ruby installation is missing psych (for YAML output). To eliminate this warning, please install libyaml and reinstall your ruby."

I'm getting this issue when I'm trying to install ruby:

It seems your ruby installation is missing psych (for YAML output). To eliminate this warning, please install libyaml and reinstall your ruby.
The solution is to completely remove ruby, then reinstall what is necessary and reinstall it:

rvm uninstall all

sudo apt-get gcc install build-essential openssl libreadline6 libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev automake libtool bison subversion pkg-config

rvm install 1.9.3
There you have it!

Friday 2 November 2012

Ruby/Watir/Cucumber: Taking a screenshot error: No connection could be made because the target machine actively refused it. - connect(2)

I was tasked with investigating a framework that lets QAs and Devs work together so we can get a functional test suite up. One of the tasks is to ensure we can capture screenshots on error so we can troubleshoot it. Here's my original code:
 After do |scenario|  
  if scenario.failed?  
   Dir::mkdir('screenshots') if not File.directory?('screenshots')  
   screenshot = "./screenshots/FAILED_#{scenario.name.gsub(' ','_').gsub(/[^0-9A-Za-z_]/, '')}.png"  
   @browser.driver.save_screenshot(screenshot)  
   embed screenshot, 'image/png'  
  end  
  @browser.close  
 end  
But it will create the file but nothing gets populated, and this exception comes up: No connection could be made because the target machine actively refused it. - connect(2) Well I pinpointed the error - it's the fact that the browser is closed before I made the call to take the screenshot. Put the browser close in a finally (ensure) block to make sure it's closed off.