Blissfully Reactive Bootstrap3 Tooltips with Meteor Templates

It’s been a long time since I wrote something here. I thought I would break the silence with a new post about Meteor.

Meteor makes it pretty easy to start prototyping a new project very quickly.
When you want your ol’ familiar Bootstrap for CSS, you just meteor add bootstrap and there it is, including the stylish $el.tooltip() component.

So while building templates in Meteor, I thought I had tooltips figured out. I’d write them something like this:

my_awesome_template.html


my_awesome_template.coffee

Template.my_awesome_template.rendered = ->
  @$('[title]').tooltip()

Template.my_awesome_template.tooltip_label = ->
  "It has #{Likes.find({}).count()} like(s)!"

Which looked great, but I quickly came to realize that when my Likes Collection changed, the bootstrap tooltip wasn’t getting refreshed, even though the underlying title attribute was. I tried using several event binding techniques like observe to try and refresh the tooltip whenever the collection changed, but those strategies weren’t panning out. I wasn’t interested in squirreling away a lot of tooltip code into my subscription callbacks, either.

It turns out, I was way over-complicating this. You see, I already have a function that was executing every time the label changed, it was just a tiny bit too fast. I wanted to refresh the tooltip AFTER the tooltip_label function ran, so this is what I did:

my_awesome_template.coffee

Template.my_awesome_template.tooltip_label = ->
  setTimeout (->
    $('#link').tooltip('fixTitle')
    ), 0
  "It has #{Likes.find().count()} like(s)!"

By calling setTimeout with a zero delay, I queued up the code to refresh the tooltip immediately after the function returns. A simple no cruft way to include reactive Bootstrap Tooltips in your Meteor Templates.

If you prefer to be educated through interactive media, here is a link to an example on Meteor Pad.

Updated August 10, 2014:
Turns out you can use the Meteor.defer function to do the same thing as setTimeout in an even cleaner way. Now my CoffeeScript looks like this:

my_awesome_template.coffee

Template.my_awesome_template.tooltip_label = ->
  Meteor.defer -> $('#link').tooltip('fixTitle')
  "It has #{Likes.find().count()} like(s)!"

Receiving Email Notifications for Report Processing Exceptions in SSRS

Seeing this error crop up in place of a graph or chart in an SSRS report always irked me.

Error: Subreport could not be shown

It means there is a problem, but it’s been swept under the rug. The calling application can’t process the error, because SSRS already has. It makes a note and replaces the report with a plain text label. And until recently, as the developer I wouldn’t know anything was wrong, because that same rug-sweep prevented anything amiss from showing up in the application’s logging system.

While going over the logs to find the source of an issue I was investigating, I noticed several other report processing errors that were unreported. I want to be proactive on issues where reports are broken, even if nobody reports a problem.

In SSRS, the Service Trace Log is the most complete source of information about errors running reports. I wanted to receive an email notification any time an error was logged by the Service Trace Log.

It seemed like a common enough request, and I was surprised to see no notes about setting up email notifications in the documentation for SSRS. In fact, the Microsoft recommendation is to just read the logs using a text editor, preferably before they expire in 14 days (default configuration).

There might be existing solutions that do something like this already, and there are a lot of improvements that can still be made, but my simple solution was to write a PowerShell Script that would watch the most recent SSRS Log File and generate an email when it found the text “ERROR:”. That script looks a bit like this:


$dir = 'C:\Program Files\Microsoft SQL Server\MSSQLSERVER\Reporting Services\LogFiles\';

$logFile = ls $dir | sort LastWriteTime | select -last 1

cat $logFile.FullName -Wait | where {$_ -match "ERROR:"} | % {

  Send-MailMessage `
    -To 'myemail@company.com' `
    -From 'donotreply@company.com' `
    -Subject 'SSRS ERROR in Trace Log' `
    -Body "An error was detected in the SSRS Trace Log $($logFile.FullName): $_" `
    -SmtpServer 'localhost';

}

A few things of note: SSRS’ LogFiles are timestamped and a new one is created in 24 hours or when the last one gets too large. This means the script will eventually start watching the wrong file after SSRS has started the next one. Luckily for me, the log files on our servers tend to get replaced only once each day at around 10:00 PM, which is outside office hours so nobody is running reports.

At 4:00 AM I have a Windows Scheduled Task that refreshes the script, or starts it if for whatever reason it stopped running.

The “-Wait” switch on Get-Content (PowerShell Alias: cat) is a cheap way to get a tail -f style log watcher in a PowerShell script.


Selenium Option Locators: Deciphering “@see #doSelect for details of option locators”

I like Selenium. It makes it really easy to bring automated web testing to the masses. But their documentation practices can be frustrating. I want to talk about a feature called Option Locators not because there is anything particularly sexy about them, but because I had such a hard time figuring out what they are.

But just in case I’m getting ahead of myself, let me start over by introducing the tool I’m talking about.

Selenium: Automating Web Browsers

If you do a lot of web development, this is a great tool to put in your toolbox. It is a web browser automation tool and what makes it really stand out for me is how easy it is to rapidly develop an automation macro (using a simple record and playback interface) and then export the script into a whole slew of other languages including Ruby, PHP, Java, or C#.

Imagine receiving a Selenium macro as an attachment to a bug report. You use the macro to resolve the issue and verify it’s been fixed, then you can save the macro away in your repository to test for possible regressions later. This can become the foundation for a fully featured automated testing system when you’re ready to make the leap to Selenium WebDriver.

Option Locators

Yesterday I was putting together a macro to populate a form that I had to repeatedly fill out as part of an issue I was working on. One of the steps was to select all of the option elements inside a select element called “ddlGeographyValue”. Now, as I’ve mentioned, you can create these macros using a record-and-playback style IDE, but unfortunately it takes a rather literal interpretation of this command.

Selenium IDE Screenshot

You can click on the picture to expand the size. It creates an individual addSelection command for each option. This wasn’t really what I wanted, not that it mattered much for a one-off throwaway script, but some of the selections were nested, so a static macro wasn’t going to do a lot of good. I was also curious if there was a way to make the addSelection command choose every option without coding them all in. Luckily the Selenium IDE comes with a built-in command reference, visible in the bottom of the image.

addSelection ( locator,optionLocator )
Arguments:
locator - an element locator identifying a multi-select box
optionLocator - an option locator (a label by default)
Add a selection to the set of selected options in a multi-select element using an option locator. @see #doSelect for details of option locators


From the IDE, the value of the Target column becomes the locator, and the Value column is the optionLocator. The documentation mentions that the default locator is label, but what other choices are there? I’ve highlighted the sentence @see #doSelect for details of option locators because that was the first thing I pasted into Google when I wanted to see what other option locators were available.

Your results may vary (they should include this post) but when I submitted that search to Google, every result for at least the first 4 pages was just a repeat of the command reference text, which has apparently been screen scraped by all of the internet. Seriously? Where are you, #doSelect? From Stack Overflow I got some partial answers on other option locators, but it was clear if I wanted a complete listing, I would need to go to the source. Source code, that is!

In case you’re wondering, the source code is available here.

Here’s the source code for the addSelection command:

Selenium.prototype.doAddSelection = function(locator, optionLocator) {
/**
* Add a selection to the set of selected options in a multi-select element using an option locator.
*
* @see #doSelect for details of option locators
*
* @param locator an element locator identifying a multi-select box
* @param optionLocator an option locator (a label by default)
*/
var element = this.browserbot.findElement(locator);
if (!("options" in element)) {
throw new SeleniumError("Specified element is not a Select (has no options)");
}
var locator = this.optionLocatorFactory.fromLocatorString(optionLocator);
var option = locator.findOption(element);
this.browserbot.addSelection(element, option);
};

And this brings us to our first real clue about what the optionLocator is. That would be whatever optionLocatorFactory makes it. Let’s look-up that next.

/**
* Factory for creating "Option Locators".
* An OptionLocator is an object for dealing with Select options (e.g. for
* finding a specified option, or asserting that the selected option of
* Select element matches some condition.
* The type of locator returned by the factory depends on the locator string:
* label=<exp> (OptionLocatorByLabel)
* value=<exp> (OptionLocatorByValue)
* index=<exp> (OptionLocatorByIndex)
* id=<exp> (OptionLocatorById)
* <exp> (default is OptionLocatorByLabel).
*/
function OptionLocatorFactory() {
}

And there we have it. I’m not going to post the factory functions, this comment gives you a pretty good idea what those are going to look like. Now why is a hopeful comment like this hidden back here in the source and not made available through the command reference in the Selenium IDE?

The irony is that those are precisely the locators I would have expected to support. OK, I probably wouldn’t have guessed “id” because I rarely give my options ids individually, but the rest were fairly obvious now that I know what they are! So why was I looking this up again?

Selecting All option elements using a Selenium macro

It turns out, none of these optionLocators allow you to define an addSelection command that selects more than one option at a time. I ended up using a separate command, getEval(script) to select the options. Now, getEval is actually hidden from the command drop down list in the Selenium IDE, the only reason I thought to use it was because it’s mentioned in the reference text for the command verifyEval which is listed.

getEval lets you run a snippet of javascript during your macro, which gives you an incredible amount of flexibility for performing actions that aren’t supported by the IDE. Here’s what I wrote to select all of the options elements for the ddlGeographyValues select element.

Command: getEval
Target: window.$("#ddlGeographyValue option").attr('selected','selected')
Value: (Empty)

That’s all I’ve got. If you made it this far, thanks for reading!