All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.qmetry.qaf.automation.cucumber.bdd2.parser.Bdd2Compiler Maven / Gradle / Ivy

Go to download

Functional test automation framework for web, mobile-web, mobile native and web-service

There is a newer version: 4.0.0-RC3
Show newest version
package com.qmetry.qaf.automation.cucumber.bdd2.parser;

import static com.qmetry.qaf.automation.core.ConfigurationManager.getBundle;
import static com.qmetry.qaf.automation.data.MetaDataScanner.applyMetafilter;
import static com.qmetry.qaf.automation.data.MetaDataScanner.hasDP;
import static com.qmetry.qaf.automation.util.ClassUtil.setField;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static java.util.Collections.unmodifiableList;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

import org.json.JSONArray;
import org.json.JSONObject;

import com.qmetry.qaf.automation.core.AutomationError;
import com.qmetry.qaf.automation.testng.dataprovider.QAFInetrceptableDataProvider;
import com.qmetry.qaf.automation.util.JSONUtil;

import gherkin.SymbolCounter;
import gherkin.ast.Background;
import gherkin.ast.DataTable;
import gherkin.ast.DocString;
import gherkin.ast.Examples;
import gherkin.ast.Feature;
import gherkin.ast.GherkinDocument;
import gherkin.ast.Location;
import gherkin.ast.Node;
import gherkin.ast.Scenario;
import gherkin.ast.ScenarioDefinition;
import gherkin.ast.ScenarioOutline;
import gherkin.ast.Step;
import gherkin.ast.TableCell;
import gherkin.ast.TableRow;
import gherkin.ast.Tag;
import gherkin.pickles.Argument;
import gherkin.pickles.Pickle;
import gherkin.pickles.PickleCell;
import gherkin.pickles.PickleLocation;
import gherkin.pickles.PickleRow;
import gherkin.pickles.PickleStep;
import gherkin.pickles.PickleString;
import gherkin.pickles.PickleTable;
import gherkin.pickles.PickleTag;

/**
 * 
 * @author chirag.jayswal
 *
 */
public class Bdd2Compiler {

	public List compile(GherkinDocument gherkinDocument) {
		List pickles = new ArrayList<>();
		Feature feature = gherkinDocument.getFeature();
		if (feature == null) {
			return pickles;
		}

		String language = feature.getLanguage();
		List featureTags = new ArrayList<>(feature.getTags());
		featureTags.add(new Tag(feature.getLocation(), "@Feature:"+feature.getName()));
		List backgroundSteps = new ArrayList<>();

		for (ScenarioDefinition scenarioDefinition : feature.getChildren()) {
			if (scenarioDefinition instanceof Background) {
				backgroundSteps =scenarioDefinition.getSteps(); //pickleSteps(scenarioDefinition);
			} else if (scenarioDefinition instanceof Scenario) {
				Map metadata = getMetaData(featureTags, ((Scenario) scenarioDefinition).getTags(),
						pickleLocation(scenarioDefinition.getLocation()));
				if (applyMetafilter(metadata)) {
					if (hasDP(metadata)) {
						ScenarioOutline outline = new ScenarioOutline(((Scenario) scenarioDefinition).getTags(),
								scenarioDefinition.getLocation(), scenarioDefinition.getKeyword(),
								scenarioDefinition.getName(), scenarioDefinition.getDescription(),
								scenarioDefinition.getSteps(), Collections.emptyList());
						compileScenarioOutline(pickles, backgroundSteps, outline, featureTags, language, metadata);
					} else {
						compileScenario(pickles, backgroundSteps, (Scenario) scenarioDefinition, featureTags, language,
								metadata);
					}
				}
			} else {
				Map metadata = getMetaData(featureTags,
						((ScenarioOutline) scenarioDefinition).getTags(),
						pickleLocation(scenarioDefinition.getLocation()));
				if (applyMetafilter(metadata)) {
					compileScenarioOutline(pickles, backgroundSteps, (ScenarioOutline) scenarioDefinition, featureTags,
							language, metadata);
				}
			}
		}
		return pickles;
	}

	private void compileScenario(List pickles, List backgroundSteps, Scenario scenario,
			List featureTags, String language, Map metadata) {
		List steps = new ArrayList<>();
		if (!scenario.getSteps().isEmpty())
			steps.addAll(pickleSteps(backgroundSteps));

		List scenarioTags = new ArrayList<>();
		scenarioTags.addAll(featureTags);
		scenarioTags.addAll(scenario.getTags());

		steps.addAll(pickleSteps(scenario.getSteps()));

		Pickle pickle = new Bdd2Pickle(scenario.getName(), language, steps, pickleTags(scenarioTags),
				singletonList(pickleLocation(scenario.getLocation())), metadata);
		pickles.add(pickle);
	}

	private void compileScenarioOutline(List pickles, List backgroundSteps,
			ScenarioOutline scenarioOutline, List featureTags, String language, Map metadata) {
		List scenariotags = new ArrayList<>();
		scenariotags.addAll(featureTags);
		scenariotags.addAll(scenarioOutline.getTags());
		List examplesToUse = getExamples(metadata, scenarioOutline);

		for (final Examples examples : examplesToUse) {
			if (examples.getTableHeader() == null)
				continue;
			List variableCells = examples.getTableHeader().getCells();
			for (final TableRow values : examples.getTableBody()) {
				List valueCells = values.getCells();

				List steps = new ArrayList<>();
				if (!scenarioOutline.getSteps().isEmpty()) {
					//steps.addAll(backgroundSteps);
					steps.addAll(pickleSteps(backgroundSteps, variableCells, valueCells, pickleLocation(values.getLocation())));
				}

				steps.addAll(pickleSteps(scenarioOutline.getSteps(), variableCells, valueCells, pickleLocation(values.getLocation())));

			/*	for (Step scenarioOutlineStep : scenarioOutline.getSteps()) {
					String stepText = interpolate(scenarioOutlineStep.getText(), variableCells, valueCells);

					PickleStep pickleStep = new PickleStep(stepText,
							createPickleArguments(scenarioOutlineStep.getArgument(), variableCells, valueCells),
							asList(pickleLocation(values.getLocation()), pickleStepLocation(scenarioOutlineStep)));
					steps.add(pickleStep);
				}*/

				List tags = new ArrayList<>(scenariotags);
				tags.addAll(examples.getTags());

				Pickle pickle = new Bdd2Pickle(interpolate(scenarioOutline.getName(), variableCells, valueCells),
						language, steps, pickleTags(tags),
						asList(pickleLocation(values.getLocation()), pickleLocation(scenarioOutline.getLocation())),
						examples.getTableHeader().getCells(), valueCells, getMetaData(metadata, examples.getTags()));

				pickles.add(pickle);
			}
		}
	}

	@SuppressWarnings("unchecked")
	private List getExamples(Map metadata, ScenarioOutline scenarioOutline) {
		if (null == metadata || !hasDP(metadata)) {
			return scenarioOutline.getExamples();
		}

		List listToReturn = new ArrayList();
		List externalData = null;
		Location location = scenarioOutline.getLocation();

		try {

			externalData = Arrays.asList(QAFInetrceptableDataProvider.getData(metadata));
		} catch (Exception e) {
			if ("No data provider found".equalsIgnoreCase(e.getMessage())) {
				return scenarioOutline.getExamples();
			}
			throw new AutomationError(e.getMessage() + ":" + scenarioOutline.getName());
		}

		if (null == externalData) {
			return scenarioOutline.getExamples();
		}
		TableRow tableHeader = new TableRow(location,
				((Map) externalData.get(0)[0]).keySet().stream().map(key -> {
					return new TableCell(location, key);
				}).collect(Collectors.toList()));

		List tableBody = externalData.stream().map(o -> {
			return new TableRow(location, ((Map) o[0]).values().stream().map(val -> {
				return new TableCell(location, toString(val));
			}).collect(Collectors.toList()));
		}).collect(Collectors.toList());

		listToReturn.add(new Examples(location, new ArrayList<>(), null, null, null, tableHeader, tableBody));
		try {
			setField("examples", scenarioOutline, listToReturn);
		} catch (Throwable t) {
			// ignore it...
		}

		return listToReturn;
	}

	private List createPickleArguments(Node argument) {
		List noCells = emptyList();
		return createPickleArguments(argument, noCells, noCells);
	}

	private List createPickleArguments(Node argument, List variableCells,
			List valueCells) {
		List result = new ArrayList<>();
		if (argument == null)
			return result;
		if (argument instanceof DataTable) {
			DataTable t = (DataTable) argument;
			List rows = t.getRows();
			List newRows = new ArrayList<>(rows.size());
			for (TableRow row : rows) {
				List cells = row.getCells();
				List newCells = new ArrayList<>();
				for (TableCell cell : cells) {
					newCells.add(new PickleCell(pickleLocation(cell.getLocation()),
							interpolate(cell.getValue(), variableCells, valueCells)));
				}
				newRows.add(new PickleRow(newCells));
			}
			result.add(new PickleTable(newRows));
		} else if (argument instanceof DocString) {
			DocString ds = (DocString) argument;
			result.add(new PickleString(pickleLocation(ds.getLocation()),
					interpolate(ds.getContent(), variableCells, valueCells),
					ds.getContentType() == null ? null : interpolate(ds.getContentType(), variableCells, valueCells)));
		} else {
			throw new RuntimeException("Unexpected argument type: " + argument);
		}
		return result;
	}

	private List pickleSteps(List scenarioDefinition, List variableCells, List valueCells, PickleLocation location) {
		List result = new ArrayList<>();
		for (Step step : scenarioDefinition) {
				String stepText = interpolate(step.getText(), variableCells, valueCells);
	
				PickleStep pickleStep = new PickleStep(stepText,
						createPickleArguments(step.getArgument(), variableCells, valueCells),
						asList(location, pickleStepLocation(step)));
				result.add(pickleStep);
		}
		return unmodifiableList(result);
	}

	private List pickleSteps(List scenarioDefinition) {
		List result = new ArrayList<>();
		for (Step step : scenarioDefinition) {
			result.add(pickleStep(step));
		}
		return unmodifiableList(result);
	}

	private PickleStep pickleStep(Step step) {
		return new PickleStep(step.getText(), createPickleArguments(step.getArgument()),
				singletonList(pickleStepLocation(step)));
	}
	
	private String interpolate(String name, List variableCells, List valueCells) {
		int col = 0;
		Map row = new HashMap();
		for (TableCell variableCell : variableCells) {
			TableCell valueCell = valueCells.get(col++);
			String header = variableCell.getValue();
			String value = valueCell.getValue();
			name = name.replace("<" + header + ">", value);
			name = name.replace("${" + header + "}", value);
			row.put(header, value);
		}
		name = name.replace("\"${args[0]}\"", JSONObject.quote(JSONObject.valueToString(row)));
		name = name.replace("${args[0]}", JSONObject.valueToString(row));
		return name;
	}

	private PickleLocation pickleStepLocation(Step step) {
		return new PickleLocation(step.getLocation().getLine(), step.getLocation().getColumn()
				+ (step.getKeyword() != null ? SymbolCounter.countSymbols(step.getKeyword()) : 0));
	}

	private PickleLocation pickleLocation(Location location) {
		return new PickleLocation(location.getLine(), location.getColumn());
	}

	private List pickleTags(List tags) {
		List result = new ArrayList<>();
		for (Tag tag : tags) {
			result.add(pickleTag(tag));
		}
		return result;
	}

	private PickleTag pickleTag(Tag tag) {
		return new PickleTag(pickleLocation(tag.getLocation()), tag.getName());
	}

	private Map getMetaData(List featureTags, List tags, PickleLocation pickleLocation) {
		Map metaData = new TreeMap(String.CASE_INSENSITIVE_ORDER);
		metaData.put("line", pickleLocation.getLine());
		addMetaData(metaData, featureTags);
		addMetaData(metaData, tags);
		return metaData;
	}

	private void addMetaData(Map metaData, List tags) {
		tags.stream().filter(tag -> tag.getName().contains(":")).forEach(tag -> {
			String[] kv = tag.getName().substring(1).split(":", 2);
			metaData.put(kv[0], JSONUtil.toObject(getBundle().getSubstitutor().replace(kv[1])));
		});
		@SuppressWarnings("unchecked")
		List groups = (List) metaData.getOrDefault("groups", new ArrayList());
		// List groups =
		tags.stream().filter(tag -> !tag.getName().contains(":")).forEach(tag -> {
			groups.add(tag.getName().substring(1));
		});
		metaData.put("groups", groups);
	}

	private Map getMetaData(Map metaData, List tags) {
		Map metaDataToReturn = new TreeMap(String.CASE_INSENSITIVE_ORDER);
		metaDataToReturn.putAll(metaData);
		addMetaData(metaDataToReturn, tags);
		return metaData;
	}

	private String toString(Object o) {
		if (o instanceof Map) {
			return JSONObject.valueToString(o);
		}
		if (o instanceof Collections) {
			return new JSONArray(o).toString();
		}
		return String.valueOf(o);
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy