Skip to content

Commit

Permalink
chore: Add fill form Selenium test action
Browse files Browse the repository at this point in the history
- Action fills multiple form fields with given values
- Optionally submits form after fields have been set
  • Loading branch information
christophd committed Dec 7, 2023
1 parent edebb47 commit 6d65427
Show file tree
Hide file tree
Showing 17 changed files with 722 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
/*
* Copyright 2006-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.citrusframework.selenium.actions;

import java.util.LinkedHashMap;
import java.util.Map;

import org.citrusframework.context.TestContext;
import org.citrusframework.selenium.endpoint.SeleniumBrowser;
import org.openqa.selenium.By;
import org.openqa.selenium.json.Json;

/**
* Fill out form with given key-value pairs where each key is used to find the form field.
* Sets field values with set input action that supports both input and select form controls.
* Supports to submit the form after all fields are set.
*
* @author Christoph Deppisch
*/
public class FillFormAction extends AbstractSeleniumAction {

/** Key value pairs representing the form fields to fill */
private final Map<By, String> formFields;

/** Optional submit button id that gets clicked after fields are filled */
private final By submitButton;

/**
* Default constructor.
*/
public FillFormAction(Builder builder) {
super("fill-form", builder);

this.formFields = builder.formFields;
this.submitButton = builder.submitButton;
}

@Override
public void execute(SeleniumBrowser browser, TestContext context) {
formFields.forEach((by, value) -> {
new SetInputAction.Builder()
.element(by)
.value(value)
.build()
.execute(browser, context);
});

if (submitButton != null) {
new ClickAction.Builder()
.element(submitButton)
.build()
.execute(browser, context);
}
}

public Map<By, String> getFormFields() {
return formFields;
}

public By getSubmitButton() {
return submitButton;
}

/**
* Action builder.
*/
public static class Builder extends AbstractSeleniumAction.Builder<FillFormAction, FillFormAction.Builder> {

private final Map<By, String> formFields = new LinkedHashMap<>();

private By submitButton;

public Builder field(By by, String value) {
this.formFields.put(by, value);
return this;
}

public Builder field(String id, String value) {
return field(By.id(id), value);
}

public Builder fromJson(String formFieldsJson) {
return fields(new Json().toType(formFieldsJson, Map.class));
}

public Builder submit() {
this.submitButton = By.xpath("//input[@type='submit']");
return this;
}

public Builder submit(String id) {
return submit(By.id(id));
}

public Builder submit(By button) {
this.submitButton = button;
return this;
}

public Builder fields(Map<String, String> fields) {
fields.forEach(this::field);
return this;
}

@Override
public FillFormAction build() {
return new FillFormAction(this);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,16 @@ public SetInputAction.Builder setInput() {
return builder;
}

/**
* Fill form action.
*/
public FillFormAction.Builder fillForm() {
FillFormAction.Builder builder = new FillFormAction.Builder()
.browser(seleniumBrowser);
this.delegate = builder;
return builder;
}

/**
* Check input action.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ protected void execute(WebElement webElement, SeleniumBrowser browser, TestConte
super.execute(webElement, browser, context);

String tagName = webElement.getTagName();
if (null == tagName || !"select".equals(tagName.toLowerCase())) {
if (!"select".equalsIgnoreCase(tagName)) {
webElement.clear();
webElement.sendKeys(context.replaceDynamicContentInString(value));
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
* Copyright 2023 the original author or authors.
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.citrusframework.selenium.xml;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import jakarta.xml.bind.annotation.XmlAccessType;
import jakarta.xml.bind.annotation.XmlAccessorType;
import jakarta.xml.bind.annotation.XmlAttribute;
import jakarta.xml.bind.annotation.XmlElement;
import jakarta.xml.bind.annotation.XmlRootElement;
import jakarta.xml.bind.annotation.XmlType;
import org.citrusframework.TestActor;
import org.citrusframework.selenium.actions.AbstractSeleniumAction;
import org.citrusframework.selenium.actions.FillFormAction;
import org.citrusframework.selenium.endpoint.SeleniumBrowser;

@XmlRootElement(name = "fill-form")
public class FillForm extends AbstractSeleniumAction.Builder<FillFormAction, FillForm> {

private final FillFormAction.Builder delegate = new FillFormAction.Builder();

@XmlElement(name = "fields")
public void setFields(Fields fields) {
delegate.fields(fields.getFields()
.stream()
.collect(Collectors.toMap(Fields.Field::getId, Fields.Field::getValue)));
}

@XmlElement(name = "json")
public void setJson(String json) {
this.delegate.fromJson(json);
}

@XmlAttribute
public void setSubmit(String value) {
this.delegate.submit(value);
}

@Override
public FillForm description(String description) {
delegate.description(description);
return this;
}

@Override
public FillForm actor(TestActor actor) {
delegate.actor(actor);
return this;
}

@Override
public FillForm browser(SeleniumBrowser seleniumBrowser) {
delegate.browser(seleniumBrowser);
return this;
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
"fields"
})
public static class Fields {
@XmlElement(name = "field")
private List<Field> fields;

public void setFields(List<Field> fields) {
this.fields = fields;
}

public List<Field> getFields() {
if (fields == null) {
fields = new ArrayList<>();
}

return fields;
}

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {})
public static class Field {
@XmlAttribute
private String id;
@XmlAttribute
private String value;

@XmlElement(name = "value")
private String valueData;

public void setId(String id) {
this.id = id;
}

public String getId() {
return id;
}

public void setValue(String value) {
this.value = value;
}

public String getValue() {
if (value == null) {
return getValueData();
}

return value;
}

public String getValueData() {
return valueData;
}

public void setValueData(String valueData) {
this.valueData = valueData;
}
}
}

@Override
public FillFormAction build() {
return delegate.build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,14 @@ public void setSetInput(SetInput builder) {
this.builder = builder;
}

/**
* Fill form action.
*/
@XmlElement(name = "fill-form")
public void setFillForm(FillForm builder) {
this.builder = builder;
}

/**
* Check input action.
*/
Expand Down
Loading

0 comments on commit 6d65427

Please sign in to comment.