Magellan supports the creation of custom step definitions via Groovy scripting.

Groovy: Java-syntax-compatible object-oriented programming language for the Java platform.

How to create custom step definitions

You need to create three groovy classes for the followings:

  • Project Step Definitions
  • UI Step Implementation
  • Config Step Implementation

Then place them under the following folder structure “project/common/resources/ext/hercules/” directory as shown below:

Example Custom Groovy Classes

The following example groovy classes were developed for a project called Catapult. If you want to see more custom steps examples please follow For more examples please follow Custom Step Examples

Example Step Definition: I logon as catapult user (\\S+) with password (\\S+)\$

FIRST STEP – Project Step Definitions:

package com.fostermoore.catalyst.catapult.cluster.common.resources.ext.hercules

import com.fostermoore.catalyst.kauri.Log
import com.fostermoore.catalyst.kauri.LogFactory
import com.fostermoore.catalyst.ng.blade.test.Support
import com.fostermoore.catalyst.ng.blade.test.hercules.HerculesFactory
import com.fostermoore.catalyst.ng.io.cucumber.java.en.And
import com.fostermoore.catalyst.ng.io.cucumber.java.en.Given
import com.fostermoore.catalyst.ng.io.cucumber.java.en.When
import com.fostermoore.catalyst.ng.io.cucumber.java.en.Then
import org.apache.commons.lang.StringUtils

import static com.fostermoore.catalyst.ng.blade.test.hercules.HerculesStepUtils.decodeVariables
import static com.fostermoore.catalyst.ng.blade.test.hercules.HerculesStepUtils.getElapsedNanos

class CatapultStepDefinitions {
  private CatapultSteps delegate
  private static final Log log = LogFactory.getLog(CatapultStepDefinitions.class)

  private CatapultSteps delegate() {
    switch (StringUtils.defaultIfBlank(System.getProperty(HerculesFactory.IMPLEMENTATION_KEY), HerculesFactory.CONFIG_IMPL).toLowerCase()) {
      case HerculesFactory.UI_IMPL:
        delegate = (new CatapultSeleniumSteps()) as CatapultSteps
        break
      default:
        delegate = (new CatapultConfigSteps()) as CatapultSteps
    }
  }

  @Given("^I logon as catapult user (\\S+) with password (\\S+)\$")
  @Documentation(value="logs the given user on with the given password",link="logonAsCatapult")
  public void logon(String username, String password)  {
    long start = System.nanoTime();
    String user = decodeVariables(delegate(), username);
    String pwd = decodeVariables(delegate(), password);
    delegate().logonAs(user, pwd);
    log.debug("[%s] logon as '%s' completed in %s", delegate().getMode(), user, getElapsedNanos(start));
  }

  @And("^I click catapult button (\\S+)\$")
  @Documentation(value="clicks catapult buttons",link="clickCatapultButton")
  public void click(String path)  {
    String button = decodeVariables(delegate(), path)
    delegate().clickButtons(button)
  }
}

SECOND STEP – Project Specific call:

package com.fostermoore.catalyst.catapult.cluster.common.resources.ext.hercules

import com.fostermoore.catalyst.ng.blade.test.hercules.HerculesSteps

interface CatapultSteps extends HerculesSteps {
  void clickButtons(String path);
}

THIRD STEP – Project UI Step Implementation:
Please check the list of UI Selenium API for more information:

package com.fostermoore.catalyst.catapult.cluster.common.resources.ext.hercules

import com.fostermoore.catalyst.cheetah.util.StringUtils
import com.fostermoore.catalyst.kauri.Log
import com.fostermoore.catalyst.kauri.LogFactory
import com.fostermoore.catalyst.ng.blade.test.hercules.HerculesSteps
import com.fostermoore.catalyst.ng.blade.test.hercules.selenium.HerculesSeleniumSteps
import org.openqa.selenium.By
import org.testng.Assert

class CatapultSeleniumSteps extends HerculesSeleniumSteps {
  private static final Log log = LogFactory.getLog(CatapultSeleniumSteps.class)
  public static String label_name;
  public static String label_index;

  CatapultSeleniumSteps() {
    super()
    init()
  }

  @Override
  public void logonAs(String username, String password) {
    setApplication(getSecurityApp());
    startService(getVariables().getString("logoff.service", "logoff"));
    startService(getVariables().getString("logon.service", "logon"));
    enterText(getVariables().getString("logon.username.label", "Username"), username, HerculesSteps.ATTRIBUTE_TYPE_TEXT);
    enterText(getVariables().getString("logon.password.label", "Password"), password, HerculesSteps.ATTRIBUTE_TYPE_TEXT);
    clickButton(getVariables().getString("logon.logon.button", "Logon"));
  }

  public void clickButtons(String path) {
    log.debug("In Catapult Selenium Step logonAs method")
    clickButton(path);
  }
}

THIRD STEP II – Project Config Step Implementation:

package com.fostermoore.catalyst.catapult.cluster.common.resources.ext.hercules

import com.fostermoore.catalyst.cheetah.util.StringUtils
import com.fostermoore.catalyst.kauri.Log
import com.fostermoore.catalyst.kauri.LogFactory
import com.fostermoore.catalyst.ng.blade.api.ApiHandler
import com.fostermoore.catalyst.ng.blade.api.ApiRequest
import com.fostermoore.catalyst.ng.blade.api.ApiResponse
import com.fostermoore.catalyst.ng.blade.api.command.SmartSaveCommand
import com.fostermoore.catalyst.ng.blade.api.command.StartServiceCommand
import com.fostermoore.catalyst.ng.blade.api.command.UpdateCommand
import com.fostermoore.catalyst.ng.blade.api.command.ViewNodeButtonClickCommand
import com.fostermoore.catalyst.ng.blade.context.ApplicationContext
import com.fostermoore.catalyst.ng.blade.context.Session
import com.fostermoore.catalyst.ng.blade.context.User
import com.fostermoore.catalyst.ng.blade.context.impl.SessionImpl
import com.fostermoore.catalyst.ng.blade.controller.RedirectException
import com.fostermoore.catalyst.ng.blade.model.ViewNode
import com.fostermoore.catalyst.ng.blade.test.config.TestExecutionContext
import com.fostermoore.catalyst.ng.blade.test.hercules.config.HerculesConfigSteps
import org.testng.AssertJUnit

class CatapultConfigSteps extends HerculesConfigSteps {
  private static final Log log = LogFactory.getLog(CatapultConfigSteps.class)

  @Override
  public void logonAs(String username, String password) {
    log.debug("In Catapult Config Step logonAs method")
    setApplication(getSecurityApp());
    AssertJUnit.assertNotNull("Need to specify a username", username);
    User user = lookupUserFor(username);
    AssertJUnit.assertNotNull(user);
    setApplication(getMasterApp());
    Session session = ApplicationContext.get().getSession();
    if (session instanceof SessionImpl) {
      ((SessionImpl) session).setUser(user);
    } else {
      log.error("Failed to logon user as expected Session to be a SessionImpl but was:"  +session.getClass());
    }
    //this forces Kauri Ctx refresh
    ApplicationContext.Holder.set(ApplicationContext.get());
    //navigate to home service - TODO: is this needed?
    startService(getVariables().getString("home.service", "home"));
  }

  public void clickButtons(String path) {
    AssertJUnit.assertTrue("Need to specify a button to click", StringUtils.isNotBlank(path));
    ApiRequest apiRequest = new ApiRequest();
    AssertJUnit.assertNotNull(TestExecutionContext.Holder.get().getCurrentServiceTransaction());
    String vpathExpr = buildVpathExpression(path, ViewNode.TYPE_BUTTON, false);
    List<ViewNode> buttons = TestExecutionContext.Holder.get().getCurrentServiceTransaction().getViewTree().select(vpathExpr)
    if (buttons == null || buttons.isEmpty()) {
      //we have found no buttons
      AssertJUnit.fail("Expected to find button: '" + path + "', but didn't");
    } else if (buttons.size() > 1) {
      //we have found too many buttons, so now try just visible buttons
      vpathExpr = buildVpathExpression(path, ViewNode.TYPE_BUTTON, true);
      buttons = TestExecutionContext.Holder.get().getCurrentServiceTransaction().getViewTree().select(vpathExpr);
    }
    AssertJUnit.assertEquals("Expected to find only 1 button: '" + path + "', but found " + buttons.size(), 1, buttons.size());
    apiRequest.getCommands().add(new UpdateCommand().setId(TestExecutionContext.Holder.get().getCurrentServiceTransaction().getId()));
    apiRequest.getCommands().add(new ViewNodeButtonClickCommand().setVpath(vpathExpr));
    apiRequest.getCommands().add(new SmartSaveCommand());
    ApiHandler apiHandler = new ApiHandler();
    apiRequest.setReturnServiceTransaction(true).setReturnViewTree(true);
    try {
      ApiResponse response = apiHandler.handle(apiRequest);
      AssertJUnit.assertNull("Failed to process request '" + apiRequest + "', error(s):" + response.getError(), response.getError());
      TestExecutionContext.Holder.get().setCurrentServiceTransaction(response.getServiceTransaction());
      if (ApplicationContext.get().getResponse().getServiceUrl() != null) {
        handleRedirect(ApplicationContext.get().getResponse().getServiceUrl());
      } else {
        //TODO: we should not assume clicking a button, that does not result in a redirect, should always require the service transaction to be validated.
        validateServiceTransaction();
      }

    } catch (RedirectException e) {
      handleRedirect(e.getServiceUrl());
    }
  }
}
Custom step definitions don’t show colors
0
0

Jump to Section