Friday, August 2, 2013

My First PeopleSoft Test Framework Test - It's about time!

I successfully created my first PeopleSoft Test Framework (PTF) test. I've been meaning to for some time. I was prompted by a bug our users found during our PeopleTools upgrade. The bug was not upgrade related. It had been there all along. So I followed the test first pattern. I created a test that failed due to the bug. Then I fixed the code and reran the test successfully to verify the bug was fixed. (As a novice, it wasn't quite that easy, but that was the end result.)

Peoplebooks does a fair, if overly wordy, job of describing how to get set up. I also leaned on the Remote PSAdmin blog. Because it uses Integration Broker, PTF requires some setup in the server/PIA side, so if you're not an admin, you'll need to enlist some help. The client is a Windows application.

One gotya', at least on Windows 7, the client has to run as Administrator. I do this by right-clicking the program in the Start Menu and selecting "Run as Administrator." If you don't do this, the recorder will not be able to "hook" the browser.

A few newbie hints:

  • On search pages and other prompt fields fully enter the text. Don't pick from the prompt or type-ahead. 
  • It's easy to record new steps. Just select the test step before where you want to insert and open the recorder. 
  • Don't be afraid to blow you test away and start again if you mess it up too badly.

Let me know your tips.

Monday, July 22, 2013

A Page Grid Display Bug in PeopleTools 8.53

We found a page grid display bug in PeopleTools 8.53.01. If you put the Row Action Buttons on the left of the grid, the column heading for the add button displays some html. The heading should be blank. Oracle says this should be fixed in PeopleTools 8.53.05. Workaround is to move the buttons to the right side of the grid.

Monday, July 15, 2013

PeopleTools 8.53 SQR jpeg Image Sizing Bug

We are in the middle of updating our PeopleSoft application to PeopleTools 8.53 from 8.49. While testing our SQR invoices, we encountered a bug in the way that the logos are embedded in the .pdf output. The logos, jpeg images from file, are not sized properly. We have 6 different Line of Business logos. Compared to 8.49, the logos ranged from very much smaller to somewhat larger and distorted. 

Oracle has acknowledged that this is a bug in PT 8.53 SQR. It will be fixed in PT 8.54, which, of course, won't be out for some time. The recommended workaround is to use .gif image files. 

I tested one gif logo today. It worked fine. We will be testing the rest soon.


We have tested all 6 of our .gif logos. There are some minor differences with the way they look in 8.49, but they will likely be acceptable as is. One upside, is the the invoice pdf is significantly smaller. Since we archive each invoice pdf, that will help save some storage costs.

Friday, May 31, 2013

JavaScript and PeopleTools 8.53

We are in the middle of updating our PeopleSoft application to PeopleTools 8.53 from 8.49. As expected, we are finding that some of our custom JavaScript is still working fine and some is not.

Loading JavaScript Libraries

A big change is how page content is loaded in 8.53. PeopleSoft now uses an AJAX approach, loading the content and content updates asynchronously. This approach caused our simple scheme of loading our jQuery JavaScript libraries from files using script tags in an HTML area to break. Luckily there is a solution. You can now put your library code into an HTML object and refer to it using PeopleTools meta-html.

So we went from this:

   <script language="JavaScript" src="/js/jquery-min.js"></script>

to this:

   <script language="JavaScript" src="%JavaScript(RH_JQUERY_LIB)"></script>

PeopleTools automatically minifies (somewhat) and caches your JavaScript on the web servers, so you don't need to maintain the library files on your web servers. We are switching some of our custom JavaScript to load this way also.

Modal Dialog Boxes

One of the nice PeopleTools improvements is the use of modal dialog boxes for messages (messagebox(), error, etc.). We spent a lot of time replacing the ugly 8.4x message pages and alerts with nice modal dialogs with the help of jQueryUI. Now we are tearing that out and leveraging the PeopleTools dialog code. I found a nice delivered JavaScript function, psConfirm2(), that is used to create dialogs. To simplify its use, I wrapped it in a helper function.

// Generic function to call PS dialog box
// Do Not call directly. Use showConfirmDialog or showOKDialog instead.
function showDialog(title,msg,type,okAction,cancelAction,okAction) {
   var bDelay;
   msg = msg.replace(/\n/g,"<br>"); //replace CRs with html breaks
   psConfirm2(title, msg, type,cancelAction, okAction, null, bDelay);

Then I added two more functions: one for OK/Cancel dialogs and one for OK dialogs (like the old alert).

// Show OK/Cancel dialog box
// okAction and cancelAction are string name of functions to call on button click
// If an empty string ("") is passed to action, that button will close dialog.
function showConfirmDialog(title,msg,cancelAction,okAction) {
   showDialog(title, msg, "OKCancel",cancelAction, okAction);

// Show OK dialog box
function showOKDialog(title,msg) {
   showDialog(title, msg, "OK","", "");

Here is the code in action:

   msg = '%BIND(:2)'; // Confirm escalate msg 132
   showConfirmDialog("Confirm", msg,  "", "confirmSubmit()");

The dialogs look better if the message text is formatted HTML. I like to use <p></p> tags rather than <br> where possible. 

One gotcha is that any function passed to psConfirm2 has to be declared globally. If you are using jQuery, this means that it is declared outside the $(document).ready(function(){} block. In practice, I just put the declaration before the block, but the function definition inside. 

var confirmSubmit;
   confirmSubmit() {
      //Code goes here


You can change the look of your dialogs by overriding the delivered Stylesheet with your own custom Stylesheet. For instance, if you want to change the color of the buttons, override the .PSPUSHBUTTONTBOK style.

The dialogs seem to resize themselves to the length of the text lines. They often end up too wide for my taste. I found that forcing a new line with a <br> tag in a long paragraph is a good way to force a narrower dialog.

I'll be sharing some more findings in future posts.

Happy coding!

Friday, March 22, 2013

Using file:// Protocol with PeopleCode ViewAttachment()

We use the PeopleCode ViewAttachment() function a lot to download files to the user. In the 8.49 PeopleBooks, the only protocol mentioned for the file source is FTP (or the database). So we have always assumed the file has to be stored on an ftp server. As of tools 8.53, ftp, sftp, ftps, http and https are also supported. Note that there is no mention of file:// in 8.49 or 8.53. However, a recent comment on Jim Marion's blog mentioned using  file://. That would be great for us because we are often displaying files that we have first transferred from non-ftp storage or created on the fly. Our Application Servers are on Windows. but we have to transfer the file to an ftp server and pick it up from there rather than just putting it in a temporary Windows file folder.

So I gave file:// a test and found that it works! Here is the test code I used to download a log file from the Application Server.

&usrFilename = "APPSRV_0102.LOG";
&path = "file:///D:/psfs/fsfstst/logs";
&rtn = ViewAttachment(&path, &usrFilename, &usrFilename);

Let me know how it works for you.

Friday, February 22, 2013

Why are some of the PeopleTools JavaScript Functions Numbered?

If you spend any time digging around in the JavaScript on PeopleSoft, you will see a lot of functions and other objects with names that end with "_win0." I always wondered why that was, but since it never seemed to change, I just went with it.

Now that we are planning a PeopleTools upgrade to 8.53 (currently 8.49), I started looking at some 8.5x applications to see what upgrade issues I might have with my custom JavaScript. I'm mainly worried about the places where I override delivered JavaScript. I inadvertently discovered that it isn't always "_win0." If you use the "New Window" link that appears on most content pages, you will note that the URI on the new page changes from .../psp/... to .../psp_1/.... If you then look at the code you'll see that "_win0" is now  "_win1."

I have yet to figure out why the JavaScript is rewritten this way. I assumed that the JavaScript in one window or tab cannot interfere with the JavaScript in another. Am I wrong? Can anyone help me out here?

By-the-way, I got lucky in my original exploits. A lot of my functionality depended on overriding or proxying delivered function submitAction_win0. This could have broken, but our custom pages did not expose the "New Window" link. I've done some thinking about how to get around this. I took a look at HTML object PT_PAGESCRIPT where much of the basic delivered JavaScript in stored. You can see that code contains replacement variable %FormName. This must get replaced somewhere in the page processing with "winx." I'll do some experimenting with that. Or I may just have to parse the %ContentURI in PeopleCode to determine the window value. I don't think it's exposed anywhere else.

-Keep Digging

Thursday, November 8, 2012

Using JavaScript in PeopleSoft: Popup Form with jQuery UI Dialog

I recently had a requirement to enable users to send an email from a specific PeopleSoft page. To be consistent with other elements of our interface, I wanted to popup a dialog with a form where the user could enter the message details. The input would then be processed on the server in PeopleCode to send the message.

Here is the dialog.

As in other areas of our public interface, most of the heavy lifting will be done by jQuery and jQuery UI. See my earlier posts for basics. By-the-way, we are still on PeopleTools 8.49. There may be a better way to do this in the world of 8.50  and beyond.

I used my standard technique of putting the JavaScript and related markup in an HTML definition. On Page.activate, the markup is injected into an HTML area on the page. I also added to the page a field for each of the user input fields that are to be displayed in the dialog. These fields are all set to Invisible - Modifiable by JavaScript. This setting allows me to create hidden fields on the page that will will be picked up by the component processor. I also gave the fields friendly names in the Page Field Name field under the General tab.

I first added the jQuery libraries, css and hidden fields to my HTML markup. The hidden field names and ids match those I entered in Page Field Name.

<script src="/rhijs/jquery.min.js" type="text/javascript"></script>
<script src="/rhijs/jquery-ui.min.js" type="text/javascript"></script>
<script src="/rhijs/date.js"  type="text/javascript"></script>
<link type="text/css" href="/rhijs/jquery-ui-1.8.5.custom.css" rel="stylesheet" />
<link type="text/css" href="/rhijs/demos.css" rel="stylesheet" />

<!-- following fields added for Client Timesheet Email -->
<input type='hidden' name='EMAIL_TO' id='EMAIL_TO'/>
<input type='hidden' name='EMAIL_CC' id='EMAIL_CC'/>
<input type='hidden' name='EMAIL_BCC' id='EMAIL_BCC'/>
<input type='hidden' name='EMAIL_SUBJECT' id='EMAIL_SUBJECT'/>
<input type='hidden' name='MESSAGE' id='MESSAGE'/>

Then the HTML for the dialog form. I'm using a combination of custom and PeopleSoft class names to style the form. The main <div> has the attribute style="display:none" to prevent the html from being shown on the page .

<!-- Send Client Email Dialog html -->
<div id="sendEmailDialog" title="Email Timesheet" style="display:none">
<style type="text/css">
.emailLabel {
display: block;
width: 90px;
float: left;
margin: 5px;
.emailInput {margin: 5px; }
.emailInputDisabled {margin: 5px; border: none; background-color:white; }
.dialogFormset {border: none;}
<p class="RH_PAGE_HDR">Send Timesheet by Email</p>
<p class="PSEDITBOX_DISPONLY">Type email addresses into the To, CC and BCC fields using a semicolon (;) as the separator.</p>

<fieldset class="dialogFormset">
<label for="emailFrom" class="PSEDITBOXLABEL emailLabel">From:</label>
<input type="text" id="emailFrom" class="emailInputDisabled" size="50" maxlength="254" value="%BIND(:17)" class="PSEDITBOX_DISPONLY" disabled="disabled"/><br/>
<label for="emailTo" class="PSEDITBOXLABEL emailLabel">To:</label>
<input type="text" id="emailTo" name="emailTo" class="emailInput" size="50" maxlength="254"/><br/>
<label for="emailCC" class="PSEDITBOXLABEL emailLabel">CC:</label>
<input id="emailCC" class="emailInput" size="50" maxlength="254"/><br/>
<label for="emailBCC" class="PSEDITBOXLABEL emailLabel">BCC:</label>
<input id="emailBCC" class="emailInput" size="50" maxlength="254"/><br/>
<label for="emailSubject" class="PSEDITBOXLABEL emailLabel">Subject:</label>
<input id="emailSubject" class="emailInput" size="50" maxlength="80"/><br/>
<label for="attachment" class="PSEDITBOXLABEL emailLabel">Attachment:</label>
<input id="attachment" class="emailInputDisabled" id="emailFrom" size="50"  value="%BIND(:18)" class="PSEDITBOX_DISPONLY" disabled="disabled"/><br/>
<label for="emailMessage" class="PSEDITBOXLABEL emailLabel">Message:</label>
<textarea id="emailMessage" class="emailInput" rows="6" cols="60"></textarea>

When the user clicks on the email link, JavaScript pops up a jQuery UI dialog. Here's the code that does that:

// Send Client Timesheet Email 
function sendClientEmail() {
isDialogOpen = true;

// Send Client Email Dialog definition

var sendClientEmailDialog = $("#sendEmailDialog").dialog({
autoOpen: false,
width: 600,
modal: true,
buttons: {  "Send Email": sendEmail,
            Cancel: function() {
$( this ).dialog( "close" );
isDialogOpen = false;

// Send button function for sendClientEmailDialog dialog
var sendEmail = function() {
var mail = $('#emailTo').val();
if (mail == "") {
alert("To: address is required");
return false;
$('#EMAIL_TO').val(mail); //hidden field
$('#EMAIL_CC').val($('#emailCC').val()); //hidden field
$('#EMAIL_BCC').val($('#emailBCC').val()); //hidden field
$('#EMAIL_SUBJECT').val($('#emailSubject').val()); //hidden field
$('#MESSAGE').val($('#emailMessage').val().replace(/\n/g,"<br/>")); //Replace cr with break
$('#RH_TC_DERIVED_CONFIRMED').val('Y'); //hidden field
isDialogOpen = false;
return submitProxied.apply(window, localArgs); // continue submit process

In the sendClientEmailDialog definition, $("#sendEmailDialog").dialog uses the html we defined above as the body of the dialog.  The sendEmail function is called by the Send Email button. The function copies the form values into the hidden fields and continues with the normal PeopleSoft button processing. On the server, the component processor adds the hidden fields to the buffer where PeopleCode validates the input and sends the email.