Skip to content
This repository was archived by the owner on Nov 23, 2021. It is now read-only.

Adding and configuring an AEM component

Mikołaj Mański edited this page Jul 13, 2016 · 15 revisions

Adding and configuring a component

This guide will show you how to add an example component, configure it and perform configuration validation using Bobcat. We will use provided SummerBlockbusterHitsPage and SectionHeaderComponent classes. So what's our test scenario? We will find our top parsys, insert a Section Header component there, modify default value and check if the provided value is saved and displayed properly. Let's start from finding our parsys into which Bobcat will insert a component.

Finding a parsys

Let's go to /cf#/content/geometrixx-media/en/entertainment/summer-blockbuster-hits-and-misses.html page. We can find our parsys there as shown on the image: Top parsys As we can see our parsys lays under div element with cq-placeholder-article-content-par_47article_47par1_47_42 class. We should add this parsys to our Page Object now. In order to do this let's add proper declaration of our parsys in the SummerBlockbusterHitsPage class:

@FindBy(xpath = "//div[contains(@class, 'cq-placeholder-article-content-par_47article_47par1_47_42')]/..")
private AemParsys topParsys;

The parsys is being found using xpath query where css class which we found before is provided. After defining a getter for this field, we are able to access it from our test classes. Let's create a test class now:

package com.example.test.summer;

import com.cognifide.qa.bb.aem.AemLogin;
import com.cognifide.qa.bb.aem.ui.parsys.AemParsys;
import com.cognifide.qa.bb.junit.Modules;
import com.cognifide.qa.bb.junit.TestRunner;
import com.cognifide.test.GuiceModule;
import com.google.inject.Inject;

import org.junit.After;
import org.junit.Before;
import org.junit.runner.RunWith;

@RunWith(TestRunner.class)
@Modules(GuiceModule.class)
public class AddComponentTest {

	@Inject
	private SummerBlockbusterHitsPage summerBlockbusterHitsPage;

	@Inject
	private AemLogin aemLogin;

	private AemParsys parsys;

	@Before
	public void openBlockbusterHitsPage() {
		aemLogin.authorLogin();
		summerBlockbusterHitsPage.open();
		assertTrue(summerBlockbusterHitsPage.isDisplayed());
		parsys = summerBlockbusterHitsPage.getTopParsys().clear();
	}

	@After
	public void cleanUp() {
		parsys.clear();
	}

}

We've created @Before and @After annotated methods here. In the openBlockbusterHitsPage() method, we are logging in to the AEM, opening the Summer Blockbuster Hits Page. The following line is responsible for waiting until the page fully renders to be sure that our parsys is visible:

assertTrue(summerBlockbusterHitsPage.isDisplayed());

After that we should clear the parsys as it should be always empty. The cleanUp() methods is clearing the parsys after test as well.

Adding a component into parsys

Since we have control of the parsys intwo which we want to insert our compnentnt, let's create out test scenario implementation now:

@Test
public void testAddingAndEditingSectionHeader() {
	SectionHeaderComponent sectionHeaderComponent = parsys.insertComponent(SectionHeaderComponent.class);

	//wait until page reloads after modifying the component
	assertTrue(summerBlockbusterHitsPage.isDisplayed());
	sectionHeaderComponent = parsys.getFirstComponentOfType(SectionHeaderComponent.class);

	assertThat(sectionHeaderComponent , CoreMatchers.notNullValue());
}

In the first line we are inserting the Section Header Component into our parsys. Class of this component has the following annotation:

@AemComponent(cssClassName = "section-header", group = "Geometrixx Media", name = "Section Header")

It provides information where the component is located in the sidekick so Bobcat can select appropriate component group and component itself to insert it.

Section Header component in the sidekick

The cssClassName property is helpful during component presence verification.

Editing a component

Since we have our component inserted into parsys, we can edit it. In order to do that we need to open a dialog window first. Now, let's edit this component by providing our custom value for Header Text property in the dialog window. We need to obtain AemDialog of this component at first.

AemDialog dialog = sectionHeaderComponent.getDialog();
dialog.open();

Now we need to access the Header Text dialog field and edit it. We can use a SectionHeaderComponent#getHeaderText() method. How does it work? In the Section Header Component class, there is a following field defined:

@DialogField(label = "Header Text")
private AemTextField headerText;

The @DialogField annotation looks for the dialog field with provided label. Please note that dialog window has to be opened when using it. Section Header component in the sidekick The next two lines are responsible for providing a test value and saving it:

title.setValue(TEST_VALUE);
dialog.ok();

When we click OK button on the dialog window, the page is being reloaded. We need to wait until it fully reloads and get our component once again:

//wait until page reloads after modifying the component
assertTrue(summerBlockbusterHitsPage.isDisplayed());
sectionHeaderComponent = parsys.getFirstComponentOfType(SectionHeaderComponent.class);

The last thing in this test case is an assertion - we are comparing the component's displayed value with our expected value. The SectionHeaderComponent has the following field defined

@FindBy(xpath = "./*/span")
private WebElement sectionText;
...

public String getText() {
	return sectionText.getText();
}

It holds the value of span element contained by this component. This is the element where our header text value is present Section Header component in the sidekick So this simple line in our test method is checking whether our component shows what we expect:

assertThat(sectionHeaderComponent.getText(), is(TEST_VALUE));

Summary

And this is it! We've written a simple test case which is checking whether adding and configuring is working properly. The entire code can be found below:

package com.cognifide.test.summer;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import com.cognifide.qa.bb.aem.AemLogin;
import com.cognifide.qa.bb.aem.dialog.classic.field.AemTextField;
import com.cognifide.qa.bb.aem.ui.AemDialog;
import com.cognifide.qa.bb.aem.ui.parsys.AemParsys;
import com.cognifide.qa.bb.junit.Modules;
import com.cognifide.qa.bb.junit.TestRunner;
import com.cognifide.test.GuiceModule;
import com.google.inject.Inject;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(TestRunner.class)
@Modules(GuiceModule.class)
public class AddComponentTest {

	private static final String TEST_VALUE = "Bobcat test";

	@Inject
	private SummerBlockbusterHitsPage summerBlockbusterHitsPage;

	@Inject
	private AemLogin aemLogin;

	private AemParsys parsys;

	@Before
	public void openSiteadminPage() {
		aemLogin.authorLogin();
		summerBlockbusterHitsPage.open();
		assertTrue(summerBlockbusterHitsPage.isDisplayed());
		parsys = summerBlockbusterHitsPage.getTopParsys().clear();
	}

	@Test
	public void testAddingAndEditingSectionHeader() {
		SectionHeaderComponent sectionHeaderComponent = parsys.insertComponent(SectionHeaderComponent.class);
		AemDialog dialog = sectionHeaderComponent.getDialog();
		dialog.open();
		AemTextField title = sectionHeaderComponent.getHeaderText();
		title.setValue(TEST_VALUE);
		dialog.ok();

		//wait until page reloads after modifying the component
		assertTrue(summerBlockbusterHitsPage.isDisplayed());
		sectionHeaderComponent = parsys.getFirstComponentOfType(SectionHeaderComponent.class);

		assertThat(sectionHeaderComponent.getText(), is(TEST_VALUE));
	}

	@After
	public void cleanUp() {
		parsys.clear();
	}

}

Modified SummerBlockbusterHitsPage class:

package com.cognifide.test.summer;

import org.openqa.selenium.support.FindBy;

import com.cognifide.qa.bb.aem.AbstractPage;
import com.cognifide.qa.bb.aem.ui.parsys.AemParsys;
import com.cognifide.qa.bb.qualifier.Frame;
import com.cognifide.qa.bb.qualifier.PageObject;

/**
 * This class represents a page from Geometrixx project.
 * <p/>
 * Frame annotation determines default frame for all methods in this class.
 */
@PageObject
@Frame("$cq")
public class SummerBlockbusterHitsPage extends AbstractPage {

	private static final String PAGE_TITLE = "Summer Blockbuster Hits and Misses";

	private static final String URL = "/cf#/content/geometrixx-media/en/entertainment/summer-blockbuster-hits-and-misses.html";


	@FindBy(xpath = "//div[contains(@class, 'cq-placeholder-article-content-par_47article_47par1_47_42')]/..")
	private AemParsys topParsys;

	@FindBy(xpath = "//div[contains(@class, 'cq-element-article-content-par_47image')]/...")
	private ImageComponent imageComponent;

	@FindBy(className = "cq-element-right-panel-par_47section_95header")
	private SectionHeaderComponent sectionHeader;


	public ImageComponent getImageComponent() {
		return imageComponent;
	}

	public SectionHeaderComponent getSectionHeader() {
		return sectionHeader;
	}

	public AemParsys getTopParsys() {
		return topParsys;
	}

	@Override
	public String getContentPath() {
		return URL;
	}

	@Override
	public String getPageTitle() {
		return PAGE_TITLE;
	}
}

Getting started with Bobcat

  1. Getting started

AEM Related Features

  1. Authoring tutorial - Classic
  1. AEM Classic Authoring Advanced usage
  1. Authoring tutorial - Touch UI

Clone this wiki locally