CFLocation and Safari

I had a weird issue today , and I thought I’d share.

I was having trouble reproducing an issue that a client was reporting in the flow of a page that was posting back to itself. No matter what I did I couldn’t get it to occur on my machine.

I then went over a dump of the cgi scope and noticed they were using Safari. I gave it a try, and BOOM, same problem.

I looked at what was happened, and it looked like the querystring of the last request was added to the querystring of where I was trying to cflocate.

So I was posting to “?method=delete_process&id=1” and cflocating to “?method=list” when I was done. Firefox tried to cflocate to “?method=list” but Safari posted to “?method=delete_process&id=1?method=list”. This caused the error, as id=1 was already deleted, and even if it wasn’t id=1? was invalid.

The fix was to prepend “#cgi.script_name#” before the question mark.

After a quick search, it turns out that this has come up in Forum over on Ray’s site (cflocation & safari).

Knowledge@Wharton interviews Adobe Co-founder

Last week’s issue of Knowledge@Wharton (my current employer) featured a pretty cool interview with Charles Geschke, one of the co-founders of Adobe. There’s a lot of great content, from stories about Steve Jobs and the beginning of Adobe, and the story of how they dealt with a hostile takeover attempt from Quark.

One of things I found was interesting was the inclusion of an internal document that outlined Adobe’s corporate values. It was a pretty interesting window into their overall philosophy, and a clear sign that as a company they are discouraged from wasting people’s times in meetings.

Check it out – Driving Adobe: Co-founder Charles Geschke on Challenges, Change and Values.

Speaking at ColdFusion Unconference at Max

Thanks to being quick on the old reply key I got myself on the speakers list for the ColdFusion Unconference. I’ll be speaking on Wednesday Morning at 9:30.

My session is on Formal Code reviews. I’ve spoken on them before, so I think I’m going to add a twist to achieve the whole “unconference” vibe. I think after I give my presentation which outlines how to go about code reviews, we’re going to go through that process with a piece of code. Granted it won’t be a full blown application, but it should give people a chance to actually feel how it works when you’re doing it the way I call right.

If anyone has anything they would like to hear or see discussed, let me know.

Starting a New Job

So once again, I’m moving jobs. I’m still with the Wharton School. However, now I will be working for Knowledge@Wharton. I’ll be working on small and medium sized projects, working on growing the backend platform, and anything else they tell me to do.

I’m pretty excited about the move. I’ll be joining a great team, it gives me an opportunity to work for a former boss again, and it’s a lot easier to point someone to a public site like Knowledge as an explanation of what I do.

I start Tuesday, after a visit to DC this weekend.

Unit Testing PDF Page Size in ColdFusion

I ran into a difficult Unit testing problem the other day. I had trouble determining the correct test to write, and finally did so. I thought that perhaps someone else might benefit from an exploration of testing strategy.

As you might know, we create pdf’s using ColdFusion for ExportReports.com. One of the new features we are adding is the ability to set the page size (legal, letter, A4… etc.) As page size is a feature, I need to test it. So I need to create a pdf file then determine what its page size is. At first I explored <cfpdf> and its ability to get at PDF metadata. No joy – it turned out that page size isn’t one of the things returned in the metadata. Then I looked at <cfpdf>’s ability to get thumbnails of the pages in the pdf. I could use <cfimage> to get the information about height and width of the image files, put that was in pixels and hard to translate to inches. (I tried assuming 300dpi, it did not yield good results.) Then it dawned on me that ratio of height to width could yield helpful answers. I found the dimensions in millimeters for the various page types, created ratios from them, and compared them to the ratio of the dimensions of the thumbnails. Then I had to correct a bit for precision, and it yielded me a solution. Here’s what it looked like in code:

<!— Grab a processable view of the pdf —>
<cfpdf
action=“thumbnail”
       source=“#pdfQuery.directory#/#pdfQuery.name#”
      
destination=“#dirreports#tn”
      
scale=“100”
overwrite=“TRUE”/>

<cfdirectory
action=“list”
             name=“thumbnailQuery”
            
directory=“#dirreports#tn”
            
filter=“*.jpg”
/>

<cfimage
action=“info”
         source=“#thumbnailQuery.directory#/#thumbnailQuery.name#”
        
structName=“pInfo”>

<cfset assertTRUE(validatePaperSize(width=pInfo.width, height=pInfo.height, pageType=‘legal’))/>

<cffunction
name=“validatePaperSize” access=“private”
output=“false” returntype=“boolean”
>
     <cfargument

name=“width”
type=“string”
required=“yes”
/>
     <cfargument

name=“height”
type=“string”
required=“yes”
/>
     <cfargument

name=“pageType”
type=“string”
required=“yes”
/>

    
<cfset
var ratios = structNew() />
     <cfset

var ratioToTest = NumberFormat(height/width, “_.___”) />

<!— These ratios were derived by using sizes in millimeters
listed here: http://en.wikipedia.org/wiki/Paper_size —>

     <cfset ratios[‘letter’] = NumberFormat(279/216, “_.___”) />
     <cfset ratios[‘legal’] = NumberFormat(356/216, “_.___”) />
     <cfset ratios[‘A4’] = NumberFormat(297/210, “_.___”) />
     <cfset ratios[‘A5’] = NumberFormat(210/148, “_.___”) />
     <cfset ratios[‘B4’] = NumberFormat(353/250, “_.___”) />
     <cfset ratios[‘B5’] = NumberFormat(250/176, “_.___”) />

     <!— Fudge precision —>
    
<cfif
Abs(ratioToTest – ratios[arguments.pageType]) lt .005
>
    
     <cfreturn
true
/>
    
<cfelse>
    
     <cfreturn
false
/>
    
</cfif>    

</cffunction>

So it might not be perfect, but it works for me. Of course, I could just file a feature request with Adobe to add page size to PDF metadata.

Speaking at Max 2008

I found out last week, that I was accepted to speak at Max 2008 North America. I’ll be talking about using ColdFusion to act as middleware for enterprise applications. That may not be clear from the title of my session: ColdFusion as Enterprise Middleware.

I’m pretty excited about the whole thing, and very grateful to the crew at Adobe, especially Adam Lehman, for giving me a shot to speak.

If anyone has any suggestions, or content they would like to hear about, feel free to drop me a line. I don’t guarantee I’ll do what you say, but I will definitely will listen.

Use Selenium? Use XPath Checker.

Just a quick note if you are using Selenium to do your tests, and writing your own, you’ve probably had to write some XPath expressions. I had to write a particularly hard XPath string and got tired of trying to test my XPath expression in Selenium over and over again.

I did some quick Google searching and discovered a Firefox plug-in named XPath Checker. It works two ways:

  • It allows you to write an XPath expression and see what it returns.
  • It allows you to click on piece of a page and see an XPath expression that would find it

It rocks.

Using Selenium to Test ColdFusion Richtext

In the course of trying to get ready to release the code for Yet Another ColdFusion CMS, or Yacc, I was trying to test working with the CMS. In order to do that, I needed to get Selenium to work with it. It worked fine until I tried to edit content. I’m using cftextarea richtext=true to provide CMS editing capabilities. However, when I went to record the test in Selenium, it couldn’t handle working with FCKeditor which provides the richtext capabilities for ColdFusion. After a few hours of trial and error, I was able to test them.

Here’s how you do it:

First you have to do it via Selenium-RC, the Selenium Firefox IDE doesn’t seem to be able to do it. You can launch pretty easily via ANT:

<!–
Prerequsites
for
selenium–>    

<taskdef
resource=“selenium-ant.properties”>

    <classpath>

        <pathelement
location=“${selenium.jar}”/>

    </classpath>

</taskdef>

<target
name=“template.test.selenium”>

    <echo
message=“Running Selenium Tests.”
/>

            

    <selenese

        suite=“${template.test.selenium.suite}”

        browser=“*pifirefox”

        results=“${log.dir}templateuitestresults.html”

        haltOnFailure=“true”

        timeoutInSeconds=“240”

        startURL=“${host.url}”

     />

                

</target>

Where:

${selenium.jar}

The path of the selenium-server.jar file

${template.test.selenium.suite}

The path to the selenium test suite.

${log.dir}

The path to a space where you store logs

${host.url}

The base url of the testing webserver

pifirefox

This is the proxy Injection version of Firefox launcher

 

Now you’re launching your Selenium tests automatically in ANT, but you have to write your tests to actually interact with the FCKEditor. By default Selenium runs its tests as soon as the page loads. But in order to test the FCKEditor, you have to wait for it to exist. Here’s the Selenese to do that:

<tr>

    <td>waitForCondition</td>

    <td>typeof(window.ColdFusion) != ‘undefined’</td>

    <td>5000</td>

</tr>

<tr>

    <td>waitForCondition</td>

    <td>typeof(window.ColdFusion.RichText) != ‘undefined’</td>

    <td>5000</td>

</tr>

<tr>

    <td>waitForCondition</td>

    <td>typeof(window.FCKeditorAPI) != ‘undefined’</td>

    <td>5000</td>

</tr>        

<tr>

    <td>waitForCondition</td>

    <td>typeof(window.ColdFusion.RichText.getEditorObject(‘content’))
!= ‘undefined’
</td>

    <td>5000</td>

</tr>            

<tr>

    <td>storeEval</td>

    <td> selenium.browserbot.getCurrentWindow().ColdFusion.RichText.
getEditorObject(‘content’).SetHTML(‘
&lt;div
id=”testSection”
&gt;
&lt;h2&gt;Welcome&lt;/h2&gt;
&lt;p&gt;Test page added.&lt;/p&gt; &lt;/div&gt;‘) </td>

    <td></td>

</tr>

<tr>

    <td>waitForElementPresent</td>

    <td>id=testSection</td>

    <td></td>

</tr>

 

Assuming that “content” is the name of your cftextarea, this is how you do it. You test for the “Coldfusion” object exists, then the “Coldfusion.RichText”, then the “FCKeditorAPI” and finally the actual richtext area. Once everything exists, you have to set the HTML of the FCKeditor. There is no input element to type into, so you have to use the FCKEditor setHTML method. To do that you have to use a storeEval command, and then you wait for the typed element you added to appear.

Hopefully this saves a few hours of work for someone else at some point.