Page tree
Skip to end of metadata
Go to start of metadata

Agenda

Table of contents

Page object in general

Comming from an Angular (website) context, Protractor thinks in (web) pages. This is why they introduced the concept of page objects, to wrap elements of a certain page. For our use case page objects are more feature objects, so instead of an object for every confluence page, we use an object for certain elements (e.g. a macro, a space or a user).

For the Random Page plugin we added a RandomPageMacro page object, to wrap functionality of this element. It extends the ConfluenceMacro from the CPB and provides functions to check if the macro is on a specific page or the configure macro parameters.

See an an page object example here: RandomPageMacro.js

The RandomPageMacro page object

This page object wraps all functions required to insert and configure the random page macro.

Imports and constants

The file is starting with imports (as seen in the previous page), the next thing are constant parameters, which are required to recognoze the macro on a page

Macro param constants
var MACRO_PARAMS = {
   macroName: "Random Page",                    # name when searching the macro browser
   dataMacroName: "random-page-macro",          # macro locator for the edit mode
   macroViewLocator: by.id("randomPageWrapper") # macro locator for view mode
};

Class definition and inheritance

The next thing is class definition and inheritance from a the CPB page object. By extending the ConfluenceMacro class, you'll get some macro specific functions like inserting a macro to the page editior.

Class definition
function RandomPageMacro(params) { # class declaration

   ConfluenceMacro.apply(this, [MACRO_PARAMS]); # call super constructor
   
   ...

}

RandomPageMacro.prototype = new ConfluenceMacro(MACRO_PARAMS); # inheritance

module.exports = RandomPageMacro; # export the class

RandomPageMacro specific code

Some parameters and methods are only important for the RandomPageMacro.

There are macro parameters to configure the macro (pageCount) passed as constructor object

Macro configuration
##
 # @extends {ConfluenceMacro}
 # @param params {object}
 # @param? params.pageCount {int} number of random pages to be shown
 # @constructor
 #
function RandomPageMacro(params) {

Also the page object specifies methods that applies to the RandomPageMacro. For example there's a method to wait for an asynchronous API call

Macro configuration
   this.loadingIndicator = function () {
      return element(by.css(".spinner")); # this element indicates loading
   };

   this.waitForMacroToBeLoaded = function () {
      browser.wait(EC.invisibilityOf(self.loadingIndicator()), # protractor function to wait for an element to disappear
         DEFAULT_LOADING_TIMEOUT,                              # within the specified time
         "RandomPage macro did not load within " + DEFAULT_LOADING_TIMEOUT + "ms");
   };

Also the setting of the parameters are macro specific

Configure macro
   # overwrite this method for setting macro values
   this.insertMacroParams = function () { # abstract method from ConfluenceMacro
      self.setLimit();                    # the code here differs for every macro
   };

   this.setLimit = function () {
      if (self.params.limit) {
         # asyncElement waits until the element is actually displayed
         var limitInput = asyncElement(by.id("macro-param-limit"));
         limitInput.clear();                     # clear the input field
         limitInput.sendKeys(self.params.limit); # set the acutal value
      }
   };

Take away

You've seen an already advanced example for a page object. It wraps general function like accessing html elements, wait for async calls or set parameters. If you are unsure if using page object makes sense - do it.

Navigation

< Part 4: Test Files | Part 6: Implementing in TypeScript >

  • No labels