org.conqat.engine.commons.findings.location.ManualTestCaseTextRegionLocation Maven / Gradle / Ivy
package org.conqat.engine.commons.findings.location;
import org.conqat.lib.commons.assertion.CCSMAssert;
import org.conqat.lib.commons.collections.Pair;
import org.conqat.lib.commons.js_export.ExportToTypeScript;
import org.conqat.lib.commons.string.StringUtils;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
/**
* This class represents a gap-less region of text in the test steps table in a
* manual test case description. It specifies
*
* - the indices of the test steps (table rows) where the text region starts
* and ends
* - whether it starts and ends in the 'action' or the 'check' part (table
* column) of the respective start and end test steps.
*
* In principle, there are three kinds of supported locations, which are listed
* below in decreasing order of specificity. Each location kind subsumes the one
* listed above.
*
* - Single cell locations: The text region starts and ends within the
* same table cell, i.e., start and end test steps (table row) as well as start
* and end columns are the same.
* - Single step locations: The text region starts and ends within the
* same table row, i.e., start and end test steps are the same but start and end
* columns are different (start in 'action' and end in 'check').
* - Unrestricted locations: The text region starts and ends in
* different table rows, i.e., start and end steps are different while start and
* end columns may or may not be different.
*
*/
@ExportToTypeScript
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = ManualTestCaseTextRegionLocation.class)
public class ManualTestCaseTextRegionLocation extends TeamscaleIssueFieldLocation {
private static final long serialVersionUID = 1L;
/**
* Pair that identifies the concrete test step position where the text region
* starts. The first element is the 0-based index of the start test step inside
* the test case description. The second element is a boolean which is
* {@code true} if the text regions start in the 'action' of the test step and
* {@code false} if it starts in the 'check' part.
*/
@JsonProperty("startTestStepIdentifier")
private final Pair startTestStepIdentifier;
/**
* Pair that identifies the concrete test step position where the text regions
* ends.
*
* @see #startTestStepIdentifier
*/
@JsonProperty("endTestStepIdentifier")
private final Pair endTestStepIdentifier;
/**
* Constructs a text region location with potentially different start and end
* test steps and step parts ('action' or 'check').
*/
public ManualTestCaseTextRegionLocation(TeamscaleIssueFieldLocation fieldLocation, int startStepIndex,
boolean startStepAction, int endStepIndex, boolean endStepAction) {
super(fieldLocation);
CCSMAssert.isTrue(startStepIndex >= 0 && endStepIndex >= 0,
() -> String.format("Test steps cannot be negative (start=%d, end=%d).", startStepIndex, endStepIndex));
CCSMAssert.isTrue(startStepIndex <= endStepIndex, () -> String
.format("Start step (%d) cannot be greater than end step (%d).", startStepIndex, endStepIndex));
if (startStepIndex == endStepIndex) {
CCSMAssert.isTrue(startStepAction == endStepAction || startStepAction,
"Single step locations cannot start in 'check' and end in 'action'.");
}
startTestStepIdentifier = new Pair<>(startStepIndex, startStepAction);
endTestStepIdentifier = new Pair<>(endStepIndex, endStepAction);
}
/**
* Constructs a text region location with potentially different start and end
* test steps and step parts ('action' or 'check').
*/
public ManualTestCaseTextRegionLocation(String uniformPath, String issueId, RawAndFieldSpecific startOffset,
RawAndFieldSpecific endOffset, RawAndFieldSpecific startLine, RawAndFieldSpecific endLine,
int startStepIndex, boolean startStepAction, int endStepIndex, boolean endStepAction,
String testStepsFieldName) {
this(new TeamscaleIssueFieldLocation(uniformPath, issueId, startOffset, endOffset, startLine, endLine,
testStepsFieldName), startStepIndex, startStepAction, endStepIndex, endStepAction);
}
/**
* Returns the 0-based index of the test step where the text regions starts.
*/
public int getStartStepIndex() {
return startTestStepIdentifier.getFirst();
}
/**
* Returns the 0-based index of the test step where the text regions ends.
*/
public int getEndStepIndex() {
return endTestStepIdentifier.getFirst();
}
/**
* Returns {@code true} if the text region starts in the 'action' part of the
* start test step and {@code false} if it starts in the 'check' part.
*/
public boolean startsInStepAction() {
return startTestStepIdentifier.getSecond();
}
/**
* Returns {@code true} if the text region ends in the 'action' part of the end
* test step and {@code false} if it ends in the 'check' part.
*/
public boolean endsInStepAction() {
return endTestStepIdentifier.getSecond();
}
/**
* Returns {@code true} if the text region resides within a single test step
* cell and {@code false} otherwise.
*/
public boolean isSingleCellLocation() {
return isSingleStepLocation() && startTestStepIdentifier.getSecond().equals(endTestStepIdentifier.getSecond());
}
/**
* Returns {@code true} if the text region resides within a single test step and
* {@code false} otherwise.
*/
public boolean isSingleStepLocation() {
return startTestStepIdentifier.getFirst().equals(endTestStepIdentifier.getFirst());
}
@Override
public String toLocationString() {
String fieldPath = String.join(ElementLocation.INTERNAL_PATH_SEPARATOR, getUniformPath(), getAffectedField());
String startStep = String.valueOf(getStartStepIndex() + 1); // User visible step index starts from 1
String startColumn = StringUtils.alternativeOnCondition(startsInStepAction(), "action", "check");
if (isSingleCellLocation()) {
return String.join(ElementLocation.INTERNAL_PATH_SEPARATOR, fieldPath, startStep, startColumn,
getFieldStartLine() + "-" + getFieldEndLine());
} else if (isSingleStepLocation()) {
String endColumn = StringUtils.alternativeOnCondition(endsInStepAction(), "action", "check");
return String.join(ElementLocation.INTERNAL_PATH_SEPARATOR, fieldPath, startStep,
startColumn + "@" + getFieldStartLine() + "-" + endColumn + "@" + getFieldEndLine());
} else {
String endColumn = StringUtils.alternativeOnCondition(endsInStepAction(), "action", "check");
String endStep = String.valueOf(getEndStepIndex() + 1); // User visible step index starts from 1
return String.join(ElementLocation.INTERNAL_PATH_SEPARATOR, fieldPath, startStep + "|" + startColumn + "@"
+ getFieldStartLine() + "-" + endStep + "|" + endColumn + "@" + getFieldEndLine());
}
}
/**
* Constructs a single cell text region location where start and end test steps
* as well as the corresponding step parts ('action' or 'check') are the same.
*/
public static ManualTestCaseTextRegionLocation forSingleCell(TeamscaleIssueFieldLocation fieldLocation,
int stepIndex, boolean stepAction) {
return new ManualTestCaseTextRegionLocation(fieldLocation, stepIndex, stepAction, stepIndex, stepAction);
}
/**
* Constructs a single cell text region location where start and end test steps
* as well as the corresponding step parts ('action' or 'check') are the same.
*/
public static ManualTestCaseTextRegionLocation forSingleCell(String uniformPath, String issueId,
RawAndFieldSpecific startOffset, RawAndFieldSpecific endOffset, RawAndFieldSpecific startLine,
RawAndFieldSpecific endLine, int stepIndex, boolean stepAction, String testStepsFieldName) {
return forSingleCell(new TeamscaleIssueFieldLocation(uniformPath, issueId, startOffset, endOffset, startLine,
endLine, testStepsFieldName), stepIndex, stepAction);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy