Welcome to CQBlueprints - A resource for your Adobe CQ 5.4, 5.5, 5.6 and AEM6 projects. Get your CQ project on the right track.

AEM Test Framework

Installation

To use the framework in a maven project, first you must connect to the CQ Blueprints Maven Repository and add the following dependencies:

<dependency>
    <groupId>com.cqblueprints.testing</groupId>
    <artifactId>test-framework</artifactId>
    <version>0.1.9</version>
    <scope>test</scope>
</dependency>

Alternatively, the jar file can be downloaded directly here.

Test Environment Setup

The framework loads the test environment from a json file. The structure of the file is as follows:

{
  "authorUrl" : "http://localhost:4502",
  "publishUrl" : "http://localhost:4503",
  "testUser" : "admin",
  "testPassword" : "admin",
  "version" : "6.0",
  "browser" : "firefox",
  "proxyEnabled" : "true"
}

By default, the framework will use a settings.json file located in the root directory of the project. Alternative locations for the file can be specified by using the TestEnvironmentLoader:

environment = TestEnvironmentLoader.INSTANCE.loadConfiguration("filename");

The authorUrl and publishUrl parameters point to the instance under test and the user and password refer to a user with the correct ACL to create, edit, and delete pages under the test page path. The confguration also contains the version of AEM being tested. Valid values for browser are firefox, chrome, ie and html. HTML is a headless version of a browser and is a quick way to run tests if an actual browser is not required. The last settings parameter determines if a browsermob-proxy will be set up to intercept requests. A value of a "true" will configure the proxy and apply BASIC authentication to requests so the tests will not need to log in.

Usage

The testing framework uses JUnit and follows the same conventions for writing tests. To begin using the built in functionality, the test should extend the TestBase class and use the provided page objects which expose high level AEM functions that will simplify test writing and reduce the need to use low level selenium in your test cases. 

The TestBase uses the environment variable to setup and instantiate the WebDriver. A proxy is loaded and connected to the WebDriver which will add authentication info to each request and collects performance data. 

The correct version of each PageObject can be retrieved using the page factory. The example below shows how you can use selenium and the framework together to write test cases. 

// ACTIONS can be included with: import static com.headwire.testing.cq.base.BaseActions.ACTIONS;
protected static final String TEST_PAGE_PARENT = "/content/geometrixx/en/";
protected static final String TEST_PAGE_NAME = "testpage";
protected static final String TEST_PAGE_TEMPLATE = "/apps/geometrixx/templates/contentpage";
protected static final String TEST_PAGE = TEST_PAGE_PARENT+TEST_PAGE_NAME+".html"; 	

@Before
public void setup() throws ClientProtocolException, IOException {
	ACTIONS.createPage(TEST_PAGE_NAME, TEST_PAGE_PARENT, TEST_PAGE_TEMPLATE, environment);
	driver.get(environment.getAuthorUrl()+AEM_6_EDITOR+TEST_PAGE);
	wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("ContentFrame")));
}

@Test
public void placeComponent() throws Exception {
	AuthorPage authorPage = FactoryProducer.getPageFactory().getAuthorPage(driver, wait, environment.getVersion());
	authorPage.toggleSidePanel();
	authorPage.selectSidePanelTab("Components");
	authorPage.dragComponentIntoParsys("Reference", "par");
}

@After
public void tearDown() throws ClientProtocolException, IOException {
	ACTIONS.deletePage(TEST_PAGE.replace(".html", ""), environment);
}	

More Examples

Interactions:

The framework API provides ways to work with dialogs simply and efficiently. A simple example of how to input fields into dialogs is shown below:

@Test
public void editComponent() throws InterruptedException {
	String pagePath = environment.getAuthorUrl()+"/editor.html"+parentPath+pageName+".html";
	driver.get(pagePath);
		wait.until(ExpectedConditions.presenceOfElementLocated(By.id("ContentFrame")));
	AuthorPage authorPage = FactoryProducer.getPageFactory().getAuthorPage(driver, wait, environment.getVersion());
	authorPage.toggleSidePanel();
	authorPage.selectSidePanelTab("Components");
		wait.until(ExpectedConditions.presenceOfElementLocated(By.xpath("//article[contains(@class,'card-component')]")));
	authorPage.dragComponentIntoParsys("Download", "par");
	authorPage.editComponent("download");
	authorPage.fillInDialogFieldByName("./jcr:description", "Description text");
	authorPage.confirmDialog();
	authorPage.selectSidePanelTab("Assets");
		  authorPage.dragAssetIntoParsys("/content/dam/projects/outdoors/cover", "download");
}

The dialog is opened using the editComponent(name) method where the name refres to the CRX name of the component. The fillInDialogFieldByName method can be used to input values into the appropriate dialog field based on its html name attribute. After the dialog has been populated, you can use the confirmDialog() method to submit the dialog.

Classic UI:

Most tests can be converted between the new interface and classic interface with minimal changes. The new UI makes use of the side panel while the classic UI uses the sidekick for components. The example below demonstrates how to write a test for the classic UI

@Test
public void createComponentClassic() throws InterruptedException {
	String PATH_STRING = "/content/geometrixx/en";
	String PATH_FIELD_NAME = "./parentPage";
	String[] VALID_LINKS = {"Products","Services","Company","Events","Support","Community", pageName};
		
	String pagePath = environment.getAuthorUrl()+parentPath+pageName+".html";
	driver.get(pagePath);
	AuthorPage authorPage = FactoryProducer.getPageFactory().getAuthorPage(driver, wait, environment.getVersion());
	authorPage.dragComponentIntoParsys("List", "par");
	authorPage.editComponent("list");
	authorPage.selectDropDown("Build list using", "Child pages");
	authorPage.fillInDialogFieldByName(PATH_FIELD_NAME, PATH_STRING);
	authorPage.confirmDialogOld();
	for (String link : VALID_LINKS) {
	     authorPage.assertExists(By.xpath("//a/h4[text()='"+link+"']"));
	}
}

Workflows:

The test framework also supports workflows. The API provides an easy way to kick off workflows from the sidekick and supports advancing workflows through both the AuthorPage and InboxPage objects.

@Test
public void sidekickWorkflow() {
	String pagePath = environment.getAuthorUrl()+parentPath+pageName+".html";
	driver.get(pagePath);
	AuthorPage dscPageNotStarted = FactoryProducer.getPageFactory().getAuthorPage(driver, wait, environment.getVersion());
	AuthorPage dscPageSecondStep = dscPageNotStarted.startWorkflowFromSidekick("Request for Activation");
	dscPageSecondStep.advanceWorkflowFromSidekick("Ready for activate. Ready for activate.");		           
	dscPageSecondStep.advanceWorkflowFromSidekick("Approved.");
}
	
@Test
public void inboxWorkflow() throws InterruptedException {
	String pagePath = environment.getAuthorUrl()+parentPath+pageName+".html";
	driver.get(pagePath);
	AuthorPage dscPageNotStarted = FactoryProducer.getPageFactory().getAuthorPage(driver, wait, environment.getVersion());
	dscPageNotStarted.startWorkflowFromSidekick("Request for Activation");
		
	driver.get(environment.getAuthorUrl()+"/inbox.html");
		
	InboxPage inboxPage = FactoryProducer.getPageFactory().getInboxPage(driver, wait, environment.getVersion());
	inboxPage.validateStatus("Approve content");
	inboxPage.advanceWorkflowThroughInbox(pageName, "comment 1");
	inboxPage.validateStatus("Waiting for activation");
	inboxPage.validateComment("comment 1");
		
	inboxPage.advanceWorkflowThroughInbox(pageName, "comment 2");
	Thread.sleep(5000); // wait for activation
		
	PublishPage publishPage = FactoryProducer.getPageFactory().getPublishPage(environment.getPublishUrl()+parentPath+pageName+".html", environment.getVersion());
	publishPage.isNot404(pageName); 	
}

More examples can be found in the sample project located here. The full list of page objects can be found in the javadocs.


Do you find the information on this site useful? Do you think we should add an article on a specific subject? We'd like to hear from you. Please drop us an email @ info@headwire.com

Search CQ Related Information