A poor man’s Deep Clone

The issue of Extend vs Clone has been covered a lot.  I’m just going to assume you need Deep Clone and understand why.

You can quickly and easily code up a deepClone method or extension to underscore or jQuery.  This is NOT “fast” and I don’t recommend doing it for large objects or in a loop, but it’s certainly fast enough to use on one object for one specific function.  Just use built-in JSON features to serialize it and de-serialize it back into an object.  You will get a new object same as the original.  As always, be weary of old IE versions.

_.mixin({
   deepClone: function(obj) {
      return JSON.parse(JSON.stringify(obj));
   }
});

Protractor/Selenium sending keys

In case you weren’t aware, you can send ENTER and other keys from protractor.

elmInput.clear();
elmInput.sendKeys('ABC', protractor.Key.ENTER);

This is super helpful if you want to emulate exactly what a user is doing such as text fields, input number types, or select2.

Let’s start with the workaround for input type number.  You can not ‘clear’ the field like you might for a text input or textarea.  There are many elaborate hacks floating around the web, but the easiest and most straightforward way to fill them is by sending CTRL+A to select all and then typing a new number.

elmInput.sendKeys(protractor.Key.CONTROL + 'a');
elmInput.sendKeys('123');

select2 droplists are a little more complicated, but still not too bad for selenium. We mostly use them for multi-select choices where the user can type a few letters and then press enter.  Emulate that in selenium by clicking the select2 to open it, and then sending the selection text followed by the enter key.  This works great in a loop to select more than one element.

var elmSl2 = element(by.id('s2id_XXX'));
var txt = 'Your Text';

elmSl2.click().then(function () {
   elmSl2.element(by.css('.select2-input')).sendKeys(txt, protractor.Key.ENTER);
 });

 

Nice CSS indicator flag / highlighter

A few CSS properties make it pretty easy to design a nice corner banner or ‘badge’ on a div.

Capture2    badge

Taking a div inside our div as the first element and rotating it to the desired position, we get the desired effect.  Adding an all upper transform and some subtle borders really makes it pop!

<div style="overflow: hidden">
  <div class="badge">WORDS</div>
  <div>9.13%</div>
</div>

.badge {
   padding: 2px 0;
   font-size: 70%;
   text-align: center;
   color: white;
   font-weight: bold;
   position: relative;
   width: 160px;
   border-top: 1px solid black;
   border-bottom: 1px solid black;
   transform: translate(-21px, 2px) rotate(-21deg);
   -webkit-transform: translate(-21px, 2px) rotate(-21deg);
   -o-transform: translate(-21px, 2px) rotate(-21deg);
   text-transform: uppercase;
   display: block !important;
 }

Custom protractor browser.wait using jQuery

I was debugging a protractor/selenium test and couldn’t easily see why my test was failing.  Once I figured out I was counting my list items incorrectly, the fix was easy.

The trick for next time though is to add a more descriptive error message.  Browser.wait() returns a promise that you can handle with a success and failure function.  The success is fine if you want status or need to update some part of your test.

The failure method is a great place to be more descriptive than just a stack trace and protractor message about timeout out on the wait!  Almost useless!  Here you can detail why the wait timed out, or at least what you were waiting for and what you found.

var TIMEOUT = 3000;
browser.wait(
   function () {
     return browser.executeScript('return $("ol li").length')
    .then(function (result) { return result == 3; });
   }
, TIMEOUT)
.then(
   function success() { // anything you need to do here },
   function failure() {
     browser.executeScript('return $("ol li").length')
    .then(
       function (result) { 
          console.log("EXPECTED 3 list items. Found " + result); }
    );
   }
);

Let me know how it works out for you!

Avoid Undefined and Null on query of deep nested objects

I had a situation this week where I needed to query deep into an object and each part of the query was a variable.

obj[part1][part2][part3]

My source was some financial data which sometimes had values and other times did not.

{
  2015: {
    Stats: {
      WtdAvg: 0.153
    }
  }
  2014: null,
  2013: {
    Stats: {}
  }
}

This is normally very difficult data to work with.  Many solutions on the web document if conditions checking each level before using it.  While this is a valid approach, I felt it made my code messy.

Then I found the _.getPath() function available in Underscore-Contrib and Lodash.  It is a recursive function that fails anywhere along the query if a part is null or undefined.

// simplified version
var getPath = function getPath(obj, parts) {
    if (obj === undefined) return '';
    if (parts.length === 0) return obj;
    if (obj === null) return '';
    return getPath(obj[_.first(parts)], _.rest(parts));
}

In this simplified version, it’s easy to see how useful it is as a helper function.  I know the parts and, in my case, can easily handle undefined and null by returning empty string instead of extra null checks.

// var x = obj[part1][part2][part3];
var x = getPath(obj, [ part1, part2, part3 ]);

I hope you seek out well defined, well tested, helper functions like these before reinventing the wheel.

Cheers!

To CoffeeScript and Back Again

I have been using CoffeeScript for about 3 years now since I did some Ruby programming and it comes built into the pipeline.  At first it was a breath of fresh air.  No more mistakes with parens, spaces, semicolons and no more typing function (maybe the only feature I still miss is -> and @).  When programming in Ruby, there is a lot of similar syntax and publishing is simple.

I honestly told people once you get used to it, you’ll never go back. Boy have times changed for me…

For the first half of 2015 we wrote a very large project using CoffeeScript.  We then hired some new developers and decided to try a new project without it for the second half of 2015.  I can honestly say I no longer miss it.

First and foremost, we are coding in C# using a git repo.  It is really ugly to check in 3 new files for every small change to my code.  Some of you may only save the coffee?  but that just requires another step during a later build process and we just pull down the repo and package it.  The diffs and merges are a hassle which greatly reduces the time saving benefit.

Next, the age old argument that it is a hassle to develop in coffee and debug in javascript.  There are now some great plugins for chrome that allow you to debug in coffee and we definitely took advantage of them.  However, they are buggy and require special compile options.

Also, we are coding in C#, not ruby.  We had to implement our own compile pipeline and include some NuGet’s for coffee.  I see my coffee and javascript side by side in my editor and the coffee brevity no longer has the same appeal.

We are doing all of our javascript in Angular.  Let’s face it, all of the sample code on the web for Angular is straight javascript, so why should I convert it when I cut/paste?  Sorry, but I’m lazy that way.

The new developers on our team just don’t feel the benefits and as I went from an advocate to just a user of CoffeeScript, they were easily able to talk me out of it.  I think I’m following the trend as CoffeeScript appears to be dropping down the list of popular languages and resume keywords.

Angular animate not ready for primetime

I needed an options panel that I didn’t want to show until the user turned on a feature.  Basically a simple slide down div based on a checkbox.  I thought this would be pretty simple with Angular, but boy was I wrong.

Angular does a decent job of adding/remove classes during transitions.  In my particular case I started with ng-show, but in Angular 1.4.8 the events weren’t always accurate so I switched to ng-if.  I had much better luck with the events, so I tied some CSS transitions to them.  However, the events must run on the Angular digest loop so the timing was still off.  My slide effect stuttered pretty badly.

I was already down this path so I figured I would try the new ngAnimate features.  I wrote an animate directive and found some code on the web to do the slide effect and catch for double clicks and cleanup, etc.  It works well for straight text, but couldn’t calculate the height of my hidden div when it had other tables and divs inside.  Useless for my purposes.

I finally gave up and fell back to plain old jQuery slideUp() and slideDown().  A very simple $watch in my controller to catch the checkbox, and a jQuery slide to show/hide the options panel.  Works every time!!  No stutter!  Another case of the right tool for the right job and the ability to get my work done for the client.

Javascript: Converting from array to object and back

I found myself in the situation where my database required an array of acceptable values, but my UI was using angular checkboxes requiring an object model.  I wanted to be able to persist my model as an array, but bind it to my elements as a single object with boolean properties.  (think ‘Check all that apply‘ options)

['Red','Green','Blue'] vs. { 'Red': true, 'Green': true, 'Blue': true }

Underscore provides some great helper functions that make these conversions only 1 line of code.  _.reduce will boil down a list of values to one single value.  Exactly what I needed to convert from the list to the object.

Seed it with an empty object and create a key/value pair for each element in the array.

_.reduce(['a','b','c'], function (memo, val) { memo[val] = true; return memo; }, {});

>>> {a: true, b: true, c: true}

I then bind this new object to my angular checkboxes.

The Trick: If the user turns ON and then OFF the checkbox, angular will add a key/value pair to the array with false.  those must be removed before converting back!

_.pick will let me iterate through the elements in the object and return only the keys that pass the test.  _.keys will then turn that object back into an array!

>>> var obj = {Blue: true, Green: true, Red: true, Yellow: false, Purple: false}

_.pick(obj, function (value, key, object) { return value == true; });

>>> {Blue: true, Green: true, Red: true}

_.keys(_.pick(obj, function (value, key, object) { return value == true; }));

>> ['Blue','Green','Red']

So using _.reduce, _.pick, and _.keys I am able to easily convert between the array and the object.

Cheers!