Showing preview only (407K chars total). Download the full file or copy to clipboard to get everything.
Repository: mauriciotogneri/green-coffee
Branch: master
Commit: caf960ec6f63
Files: 95
Total size: 372.6 KB
Directory structure:
gitextract_xuvgahf2/
├── .gitignore
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── build.gradle
├── gradle/
│ └── wrapper/
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── greencoffee/
│ ├── build.gradle
│ └── src/
│ └── main/
│ ├── AndroidManifest.xml
│ └── java/
│ ├── com/
│ │ └── mauriciotogneri/
│ │ └── greencoffee/
│ │ ├── GreenCoffeeConfig.java
│ │ ├── GreenCoffeeSteps.java
│ │ ├── GreenCoffeeTest.java
│ │ ├── Localization.java
│ │ ├── Scenario.java
│ │ ├── ScenarioConfig.java
│ │ ├── ScreenCapture.java
│ │ ├── ScreenshotProvider.java
│ │ ├── StepDefinition.java
│ │ ├── TestLog.java
│ │ ├── TimedIdlingResource.java
│ │ ├── annotations/
│ │ │ ├── And.java
│ │ │ ├── But.java
│ │ │ ├── Given.java
│ │ │ ├── Then.java
│ │ │ └── When.java
│ │ ├── exceptions/
│ │ │ ├── DuplicatedStepDefinitionException.java
│ │ │ ├── InvalidExampleException.java
│ │ │ ├── InvalidMethodSignatureException.java
│ │ │ ├── InvalidStepDefinitionException.java
│ │ │ ├── NoStepsDefinedException.java
│ │ │ ├── StepDefinitionNotFoundException.java
│ │ │ └── StepFailureException.java
│ │ └── interactions/
│ │ ├── ActionableData.java
│ │ ├── ActionableObject.java
│ │ ├── ActionableView.java
│ │ ├── DataMatcher.java
│ │ └── ObjectMatcher.java
│ └── gherkin/
│ ├── AstBuilder.java
│ ├── AstNode.java
│ ├── Func.java
│ ├── GenerateTokens.java
│ ├── GherkinDialect.java
│ ├── GherkinDialectProvider.java
│ ├── GherkinLanguageConstants.java
│ ├── GherkinLine.java
│ ├── GherkinLineSpan.java
│ ├── IGherkinDialectProvider.java
│ ├── IGherkinLine.java
│ ├── Parser.java
│ ├── ParserException.java
│ ├── StringUtils.java
│ ├── SymbolCounter.java
│ ├── Token.java
│ ├── TokenFormatter.java
│ ├── TokenFormatterBuilder.java
│ ├── TokenMatcher.java
│ ├── TokenScanner.java
│ ├── ast/
│ │ ├── Background.java
│ │ ├── Comment.java
│ │ ├── DataTable.java
│ │ ├── DocString.java
│ │ ├── Examples.java
│ │ ├── Feature.java
│ │ ├── GherkinDocument.java
│ │ ├── Location.java
│ │ ├── Node.java
│ │ ├── Scenario.java
│ │ ├── ScenarioDefinition.java
│ │ ├── ScenarioOutline.java
│ │ ├── Step.java
│ │ ├── TableCell.java
│ │ ├── TableRow.java
│ │ └── Tag.java
│ ├── cli/
│ │ └── Main.java
│ ├── events/
│ │ ├── AttachmentEvent.java
│ │ ├── CucumberEvent.java
│ │ ├── GherkinDocumentEvent.java
│ │ ├── PickleEvent.java
│ │ └── SourceEvent.java
│ ├── pickles/
│ │ ├── Argument.java
│ │ ├── Compiler.java
│ │ ├── Pickle.java
│ │ ├── PickleCell.java
│ │ ├── PickleLocation.java
│ │ ├── PickleRow.java
│ │ ├── PickleStep.java
│ │ ├── PickleString.java
│ │ ├── PickleTable.java
│ │ └── PickleTag.java
│ └── stream/
│ ├── GherkinEvents.java
│ ├── SourceEvents.java
│ └── Stdio.java
└── settings.gradle
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.iml
gradle.properties
.gradle
/.idea
/local.properties
/greencoffee/build
/build
================================================
FILE: CHANGELOG.md
================================================
# Change Log
All notable changes to this project are documented in this file.
## [3.6.0] - 2021-02-15
### Changed
- Removed JCenter support
## [3.5.0] - 2018-10-01
### Changed
- Updated dependencies and build tools
## [3.3.0] - 2018-08-23
### Changed
- Updated screenshot interface to allow to pass a custom screenshot provider
## [3.2.1] - 2018-04-13
### Changed
- Updated screenshot parameter from path to boolean. When set to `true`, screenshots will be placed in the folder `Android/data/your_package/files/screenshots`
### Removed
- Method `grantPermission`. Use `GrantPermissionRule` instead
## [3.0.0] - 2018-02-12
### Changed
- Updated to Java 8
- Updated Android build tools, compile version and Gradle version
- Updated visibility of some classes and methods
- Some constructor parameters of the class `ScenarioConfig` are optional
## [2.9.0] - 2017-09-18
### Changed
- Using Espresso `3.0.1`
## [2.8.1] - 2017-07-06
### Added
- Added method `text()` to `ActionableObject`
- Added method `onViewWithAll(Matcher<? super View>... matchers)`
- Added class `TimedIdlingResource`
## [2.8.0] - 2017-07-05
### Added
- Added boolean methods for actionable elements
- Improved data matchers
## [2.7.0] - 2017-07-04
### Added
- Added methods `waitFor(long millis)` and `waitFor(long value, TimeUnit timeUnit)`
- Added class `SpinnerMatcher`
## [2.6.0] - 2017-04-28
### Added
- Improvements in `ActionableView` (by @thanhlcm90)
- Added callback `afterScenarioEnds(Scenario scenario, Locale locale)`
- Added method `grantPermission(String permission)`
## [2.5.0] - 2017-04-26
### Added
- Improvements in `ActionableView` (by @thanhlcm90)
## [2.4.0] - 2017-04-02
### Changed
- Using Gradle plugin version 2.3.0
- Overridden method `toString()` for class `ScenarioConfig`
## [2.2.0] - 2017-03-17
### Removed
- Unused third party libraries
## [2.1.1] - 2017-03-02
### Added
- Added the helper methods `closeKeyboard()` and `pressBack()`
- Added method `beforeScenarioStarts(Scenario scenario, Locale locale)`
## [2.0.1] - 2017-02-24
### Added
- Support to launch the scenarios with different locales
- Support to take screenshots during the tests
- This CHANGELOG
### Changed
- The constructor of `GreenCoffeeTest`
- Updated to latest version of [Gherkin java](https://github.com/cucumber/gherkin-java)
### Removed
- Example app. Moved [here](https://github.com/vndly/green-coffee-example)
## [1.0.0] - 2016-09-04
### Added
- First stable version of the library
================================================
FILE: LICENSE.md
================================================
MIT License
Copyright (c) 2021 Mauricio Togneri
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
[](https://github.com/mauriciotogneri/green-coffee/blob/master/LICENSE.md)
[](https://android-arsenal.com/details/1/4313)
# Green Coffee
**Green Coffee** is a library that allows you to run your acceptance tests written in Gherkin in your Android instrumentation tests using the step definitions that you declare. Visit the [wiki](https://github.com/mauriciotogneri/green-coffee/wiki) for more detailed information.
## Example
Given the following feature:
```gherkin
Feature: Login screen to authenticate users
Scenario: Invalid username and password
Given I see an empty login form
When I introduce an invalid username
And I introduce an invalid password
And I press the login button
Then I see an error message saying 'Invalid credentials'
```
First, create a class that extends from `GreenCoffeeTest` and declare the Activity, the feature and the step definitions that will be used:
```java
@RunWith(Parameterized.class)
public class LoginFeatureTest extends GreenCoffeeTest
{
@Rule
public ActivityTestRule<LoginActivity> activity = new ActivityTestRule<>(LoginActivity.class);
public LoginFeatureTest(ScenarioConfig scenarioConfig)
{
super(scenarioConfig);
}
@Parameters(name = "{0}")
public static Iterable<ScenarioConfig> scenarios() throws IOException
{
return new GreenCoffeeConfig()
.withFeatureFromAssets("assets/login.feature")
.takeScreenshotOnFail()
.scenarios(
new Locale("en", "GB"),
new Locale("es", "ES")
); // the locales used to run the scenarios (optional)
}
@Test
public void test()
{
start(new LoginSteps());
}
}
```
Next, create a class containing the steps definitions:
```java
public class LoginSteps extends GreenCoffeeSteps
{
@Given("^I see an empty login form$")
public void iSeeAnEmptyLoginForm()
{
onViewWithId(R.id.login_input_username).isEmpty();
onViewWithId(R.id.login_input_password).isEmpty();
}
@When("^I introduce an invalid username$")
public void iIntroduceAnInvalidUsername()
{
onViewWithId(R.id.login_input_username).type("guest");
}
@When("^I introduce an invalid password$")
public void iIntroduceAnInvalidPassword()
{
onViewWithId(R.id.login_input_password).type("1234");
}
@When("^I press the login button$")
public void iPressTheLoginButton()
{
onViewWithId(R.id.login_button_doLogin).click();
}
@Then("^I see an error message saying 'Invalid credentials'$")
public void iSeeAnErrorMessageSayingInvalidCredentials()
{
onViewWithText(R.string.login_credentials_error).isDisplayed();
}
}
```
And that's it, now you can create your own tests using Green Coffee. This is how it looks when you run a more complex test:

You can see an example applied to a full app [here](https://github.com/vndly/green-coffee-example).
## Installation
Add the following code to your root `build.gradle`:
```groovy
allprojects
{
repositories
{
maven
{
url 'https://jitpack.io'
}
}
}
```
Add the following code to your module `build.gradle` file:
```groovy
dependencies
{
androidTestImplementation 'androidx.test:runner:1.3.0'
androidTestImplementation 'androidx.test:rules:1.3.0'
androidTestImplementation 'com.github.mauriciotogneri:green-coffee:3.6.0'
}
```
And the following test instrumentation runner:
```groovy
defaultConfig
{
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
}
```
================================================
FILE: build.gradle
================================================
buildscript
{
repositories
{
google()
mavenCentral()
maven
{
url 'https://plugins.gradle.org/m2/'
}
}
dependencies
{
classpath 'com.android.tools.build:gradle:4.1.2'
}
}
allprojects
{
repositories
{
google()
mavenCentral()
maven
{
url 'http://maven.aliyun.com/nexus/content/groups/public/'
}
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Mon Feb 15 21:58:43 CET 2021
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
================================================
FILE: gradlew
================================================
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
================================================
FILE: greencoffee/build.gradle
================================================
apply plugin: 'com.android.library'
android
{
compileSdkVersion 30
buildToolsVersion '30.0.3'
defaultConfig
{
minSdkVersion 14
targetSdkVersion 30
versionCode 1
versionName '3.6.0'
}
dexOptions
{
javaMaxHeapSize '2g'
preDexLibraries true
}
compileOptions
{
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies
{
implementation 'io.cucumber:gherkin-jvm-deps:1.0.6'
implementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
================================================
FILE: greencoffee/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.mauriciotogneri.greencoffee" />
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/GreenCoffeeConfig.java
================================================
package com.mauriciotogneri.greencoffee;
import com.mauriciotogneri.greencoffee.exceptions.InvalidExampleException;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import gherkin.AstBuilder;
import gherkin.Parser;
import gherkin.ast.Examples;
import gherkin.ast.Feature;
import gherkin.ast.GherkinDocument;
import gherkin.ast.ScenarioDefinition;
import gherkin.ast.ScenarioOutline;
import gherkin.ast.Step;
import gherkin.ast.TableCell;
import gherkin.ast.TableRow;
import gherkin.ast.Tag;
public class GreenCoffeeConfig
{
private final List<Scenario> scenarios;
private final ScreenshotProvider screenshotProvider;
private GreenCoffeeConfig(List<Scenario> scenarios, ScreenshotProvider screenshotProvider)
{
this.scenarios = scenarios;
this.screenshotProvider = screenshotProvider;
}
public GreenCoffeeConfig()
{
this(new ArrayList<>(), null);
}
public List<ScenarioConfig> scenarios(Locale... locales)
{
List<ScenarioConfig> scenarioConfigs = new ArrayList<>();
Locale[] finalLocales = locales;
if (finalLocales.length == 0)
{
finalLocales = new Locale[1];
finalLocales[0] = Locale.getDefault();
}
for (Locale locale : finalLocales)
{
for (Scenario scenario : scenarios)
{
scenarioConfigs.add(new ScenarioConfig(scenario, locale, screenshotProvider));
}
}
return scenarioConfigs;
}
public GreenCoffeeConfig takeScreenshotOnFail()
{
return new GreenCoffeeConfig(scenarios, ScreenshotProvider.getDefault());
}
public GreenCoffeeConfig takeScreenshotOnFail(ScreenshotProvider screenshotProvider)
{
return new GreenCoffeeConfig(scenarios, screenshotProvider);
}
public GreenCoffeeConfig withTags(String firstTag, String... restTags)
{
List<String> tagList = new ArrayList<>();
tagList.add(firstTag);
tagList.addAll(Arrays.asList(restTags));
List<Scenario> filtered = new ArrayList<>();
for (Scenario scenario : scenarios)
{
if (scenario.hasTags(tagList))
{
filtered.add(scenario);
}
}
return new GreenCoffeeConfig(filtered, screenshotProvider);
}
public GreenCoffeeConfig withFeatureFromString(String featureSource)
{
return new GreenCoffeeConfig(scenarios(featureSource), screenshotProvider);
}
public GreenCoffeeConfig withFeatureFromAssets(String featurePath) throws IOException
{
InputStream stream = getClass().getClassLoader().getResourceAsStream(featurePath);
return withFeatureFromInputStream(stream);
}
public GreenCoffeeConfig withFeatureFromUrl(String featureUrl) throws IOException
{
URL url = new URL(featureUrl);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");
return withFeatureFromInputStream(urlConnection.getInputStream());
}
public GreenCoffeeConfig withFeatureFromInputStream(InputStream featureInput) throws IOException
{
BufferedReader reader = new BufferedReader(new InputStreamReader(featureInput));
StringBuilder builder = new StringBuilder();
String line;
while ((line = reader.readLine()) != null)
{
builder.append(String.format("%s%n", line));
}
reader.close();
return new GreenCoffeeConfig(scenarios(builder.toString()), screenshotProvider);
}
private List<Scenario> scenarios(String featureSource)
{
Parser<GherkinDocument> parser = new Parser<>(new AstBuilder());
GherkinDocument gherkinDocument = parser.parse(featureSource);
Feature feature = gherkinDocument.getFeature();
List<ScenarioDefinition> backgrounds = backgrounds(feature);
List<ScenarioDefinition> scenarios = scenarios(feature);
List<Scenario> result = new ArrayList<>();
for (ScenarioDefinition scenarioDefinition : scenarios)
{
String name = scenarioDefinition.getName();
String description = scenarioDefinition.getDescription();
List<Step> steps = new ArrayList<>();
List<String> tags = new ArrayList<>();
for (ScenarioDefinition background : backgrounds)
{
steps.addAll(background.getSteps());
}
if (isScenarioNormal(scenarioDefinition))
{
gherkin.ast.Scenario scenarioNormal = (gherkin.ast.Scenario) scenarioDefinition;
tags.addAll(tags(scenarioNormal.getTags()));
}
else if (isScenarioOutline(scenarioDefinition))
{
ScenarioOutline scenarioOutline = (ScenarioOutline) scenarioDefinition;
tags.addAll(tags(scenarioOutline.getTags()));
}
steps.addAll(scenarioDefinition.getSteps());
result.add(new Scenario(name, description, steps, tags));
}
return result;
}
private List<String> tags(List<Tag> tags)
{
List<String> result = new ArrayList<>();
for (Tag tag : tags)
{
result.add(tag.getName());
}
return result;
}
private List<ScenarioDefinition> backgrounds(Feature feature)
{
List<ScenarioDefinition> result = new ArrayList<>();
for (ScenarioDefinition scenario : feature.getChildren())
{
if (gherkin.ast.Background.class.isInstance(scenario))
{
result.add(scenario);
}
}
return result;
}
private List<ScenarioDefinition> scenarios(Feature feature)
{
List<ScenarioDefinition> result = new ArrayList<>();
for (ScenarioDefinition scenario : feature.getChildren())
{
if (isScenarioNormal(scenario))
{
result.add(scenario);
}
else if (isScenarioOutline(scenario))
{
ScenarioOutline scenarioOutline = (ScenarioOutline) scenario;
for (Examples examples : scenarioOutline.getExamples())
{
for (TableRow row : examples.getTableBody())
{
result.add(concreteScenario(scenarioOutline, parametersMap(examples.getTableHeader(), row)));
}
}
}
}
return result;
}
private boolean isScenarioNormal(ScenarioDefinition scenario)
{
return gherkin.ast.Scenario.class.isInstance(scenario);
}
private boolean isScenarioOutline(ScenarioDefinition scenario)
{
return gherkin.ast.ScenarioOutline.class.isInstance(scenario);
}
private Map<String, String> parametersMap(TableRow header, TableRow row)
{
List<TableCell> headerCells = header.getCells();
List<TableCell> rowCells = row.getCells();
if (headerCells.size() == rowCells.size())
{
Map<String, String> parameters = new LinkedHashMap<>();
for (int i = 0; i < headerCells.size(); i++)
{
TableCell headerCell = headerCells.get(i);
TableCell rowCell = rowCells.get(i);
parameters.put(headerCell.getValue(), rowCell.getValue());
}
return parameters;
}
else
{
throw new InvalidExampleException(header.getLocation().getLine(), header.getLocation().getColumn());
}
}
private ScenarioDefinition concreteScenario(ScenarioOutline abstractScenario, Map<String, String> parameters)
{
List<Step> steps = new ArrayList<>();
for (Step step : abstractScenario.getSteps())
{
steps.add(concreteStep(step, parameters));
}
return new gherkin.ast.Scenario(
abstractScenario.getTags(),
abstractScenario.getLocation(),
abstractScenario.getKeyword(),
abstractScenario.getName(),
abstractScenario.getDescription(),
steps);
}
private Step concreteStep(Step abstractStep, Map<String, String> parameters)
{
String text = abstractStep.getText();
for (Entry<String, String> entry : parameters.entrySet())
{
String target = String.format("<%s>", entry.getKey());
String replacement = entry.getValue();
text = text.replace(target, replacement);
}
return new Step(
abstractStep.getLocation(),
abstractStep.getKeyword(),
text,
abstractStep.getArgument());
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/GreenCoffeeSteps.java
================================================
package com.mauriciotogneri.greencoffee;
import android.support.annotation.IdRes;
import android.support.annotation.StringRes;
import android.support.test.InstrumentationRegistry;
import android.support.test.espresso.Espresso;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.support.test.espresso.matcher.ViewMatchers;
import android.view.View;
import android.view.ViewGroup;
import com.mauriciotogneri.greencoffee.annotations.And;
import com.mauriciotogneri.greencoffee.annotations.But;
import com.mauriciotogneri.greencoffee.annotations.Given;
import com.mauriciotogneri.greencoffee.annotations.Then;
import com.mauriciotogneri.greencoffee.annotations.When;
import com.mauriciotogneri.greencoffee.exceptions.InvalidStepDefinitionException;
import com.mauriciotogneri.greencoffee.interactions.ActionableData;
import com.mauriciotogneri.greencoffee.interactions.ActionableObject;
import com.mauriciotogneri.greencoffee.interactions.ActionableView;
import com.mauriciotogneri.greencoffee.interactions.DataMatcher;
import com.mauriciotogneri.greencoffee.interactions.ObjectMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import static android.support.test.espresso.Espresso.onData;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static org.hamcrest.Matchers.allOf;
public class GreenCoffeeSteps
{
List<StepDefinition> stepDefinitions()
{
List<StepDefinition> stepDefinitions = new ArrayList<>();
for (Method method : getClass().getDeclaredMethods())
{
String pattern = pattern(method);
if (pattern != null)
{
StepDefinition stepDefinition = new StepDefinition(pattern, method, this);
stepDefinitions.add(stepDefinition);
}
}
return stepDefinitions;
}
private String pattern(Method method)
{
String result = null;
Given given = method.getAnnotation(Given.class);
if (given != null)
{
result = given.value();
}
When when = method.getAnnotation(When.class);
if (when != null)
{
checkInvalidStepDefinition(result, method);
result = when.value();
}
Then then = method.getAnnotation(Then.class);
if (then != null)
{
checkInvalidStepDefinition(result, method);
result = then.value();
}
And and = method.getAnnotation(And.class);
if (and != null)
{
checkInvalidStepDefinition(result, method);
result = and.value();
}
But but = method.getAnnotation(But.class);
if (but != null)
{
checkInvalidStepDefinition(result, method);
result = but.value();
}
return result;
}
private void checkInvalidStepDefinition(String pattern, Method method)
{
if (pattern != null)
{
throw new InvalidStepDefinitionException(method);
}
}
protected ActionableObject onViewWithId(@IdRes int resourceId)
{
return new ActionableView(onView(withId(resourceId)));
}
protected ActionableObject onViewWithId(@IdRes int resourceId, int index)
{
return new ActionableView(onView(withIndex(withId(resourceId), index)));
}
protected ActionableObject onViewWithText(@StringRes int resourceId)
{
return new ActionableView(onView(ViewMatchers.withText(resourceId)));
}
protected ActionableObject onViewWithText(@StringRes int resourceId, int index)
{
return new ActionableView(onView(withIndex(ViewMatchers.withText(resourceId), index)));
}
protected ActionableObject onViewWithText(Object text)
{
return new ActionableView(onView(ViewMatchers.withText(text.toString())));
}
protected ActionableObject onViewWithText(Object text, int index)
{
return new ActionableView(onView(withIndex(ViewMatchers.withText(text.toString()), index)));
}
protected ActionableObject onViewWithAll(Matcher<? super View>... matchers)
{
return new ActionableView(onView(allOf(matchers)));
}
protected <T> ActionableObject onViewWithObject(T object)
{
return new ActionableData(onData(new ObjectMatcher<>(object)));
}
protected <T> ActionableObject onViewWithObject(@IdRes int resourceId, Class<T> clazz, T object)
{
return new DataMatcher<>(resourceId, clazz).with(object);
}
protected ActionableObject onViewChildOf(@IdRes int parentViewId, int index)
{
return new ActionableView(onView(nthChildOf(withId(parentViewId), index)));
}
protected void pressBack()
{
Espresso.pressBack();
}
protected void closeKeyboard()
{
Espresso.closeSoftKeyboard();
}
protected String string(@StringRes int stringId)
{
return InstrumentationRegistry.getTargetContext().getString(stringId);
}
protected Locale locale()
{
return new Localization(InstrumentationRegistry.getTargetContext()).locale();
}
protected void takeScreenshot(File file)
{
ScreenCapture screenCapture = new ScreenCapture();
screenCapture.takeScreenshot(file);
}
protected Matcher<View> withIndex(Matcher<View> matcher, int index)
{
return new TypeSafeMatcher<View>()
{
private int currentIndex;
private int viewObjHash;
@Override
public void describeTo(Description description)
{
description.appendText(String.format("with index: %d", index));
}
@Override
public boolean matchesSafely(View view)
{
if (matcher.matches(view) && (currentIndex++ == index))
{
viewObjHash = view.hashCode();
}
return (view.hashCode() == viewObjHash);
}
};
}
protected Matcher<View> nthChildOf(Matcher<View> parentMatcher, int childPosition)
{
return new TypeSafeMatcher<View>()
{
@Override
public void describeTo(Description description)
{
description.appendText(String.format("with %d child view of type parentMatcher", childPosition));
}
@Override
public boolean matchesSafely(View view)
{
if (!(view.getParent() instanceof ViewGroup))
{
return parentMatcher.matches(view.getParent());
}
ViewGroup group = (ViewGroup) view.getParent();
return parentMatcher.matches(view.getParent()) && group.getChildAt(childPosition).equals(view);
}
};
}
protected void waitFor(long value, TimeUnit timeUnit)
{
onView(isRoot()).perform(actionWaitFor(value, timeUnit));
}
protected void waitFor(long millis)
{
waitFor(millis, TimeUnit.MILLISECONDS);
}
private ViewAction actionWaitFor(long value, TimeUnit timeUnit)
{
long millis = timeUnit.toMillis(value);
return new ViewAction()
{
@Override
public Matcher<View> getConstraints()
{
return isRoot();
}
@Override
public String getDescription()
{
return "Wait for " + millis + " milliseconds.";
}
@Override
public void perform(UiController uiController, View view)
{
uiController.loopMainThreadForAtLeast(millis);
}
};
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/GreenCoffeeTest.java
================================================
package com.mauriciotogneri.greencoffee;
import com.mauriciotogneri.greencoffee.exceptions.DuplicatedStepDefinitionException;
import com.mauriciotogneri.greencoffee.exceptions.NoStepsDefinedException;
import com.mauriciotogneri.greencoffee.exceptions.StepDefinitionNotFoundException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Set;
import static android.support.test.InstrumentationRegistry.getTargetContext;
import gherkin.ast.Node;
import gherkin.ast.Step;
public class GreenCoffeeTest
{
private final ScenarioConfig scenarioConfig;
private final TestLog testLog;
public GreenCoffeeTest(ScenarioConfig scenario)
{
this.scenarioConfig = scenario;
this.testLog = new TestLog();
beforeScenarioStarts(scenario.scenario(), scenario.locale());
Localization localization = new Localization(getTargetContext());
localization.locale(scenarioConfig.locale());
}
protected void beforeScenarioStarts(Scenario scenario, Locale locale)
{
}
protected void afterScenarioEnds(Scenario scenario, Locale locale)
{
}
protected void start(GreenCoffeeSteps... targets)
{
if (targets.length == 0)
{
throw new NoStepsDefinedException();
}
Scenario scenario = scenarioConfig.scenario();
testLog.logScenario(scenario);
List<StepDefinition> stepDefinitions = new ArrayList<>();
for (GreenCoffeeSteps greenCoffeeSteps : targets)
{
stepDefinitions.addAll(greenCoffeeSteps.stepDefinitions());
}
validateStepDefinitions(stepDefinitions);
try
{
for (Step step : scenario.steps())
{
processStep(step, stepDefinitions);
}
}
catch (Exception e)
{
if (scenarioConfig.hasScreenshotProvider())
{
ScreenshotProvider screenshotProvider = scenarioConfig.screenshotProvider();
screenshotProvider.takeScreenshot(scenario);
}
throw e;
}
finally
{
afterScenarioEnds(scenarioConfig.scenario(), scenarioConfig.locale());
}
}
private void validateStepDefinitions(List<StepDefinition> stepDefinitions)
{
Set<String> patterns = new HashSet<>();
for (StepDefinition stepDefinition : stepDefinitions)
{
String pattern = stepDefinition.pattern();
if (!patterns.contains(pattern))
{
patterns.add(pattern);
}
else
{
throw new DuplicatedStepDefinitionException(stepDefinition.method(), pattern);
}
}
}
private void processStep(Step step, List<StepDefinition> stepDefinitions)
{
String keyword = step.getKeyword().trim();
String text = step.getText().trim();
Node argument = step.getArgument();
testLog.logStep(keyword, text);
for (StepDefinition stepDefinition : stepDefinitions)
{
if (stepDefinition.matches(text))
{
stepDefinition.invoke(text, argument);
return;
}
}
throw new StepDefinitionNotFoundException(keyword, text);
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/Localization.java
================================================
package com.mauriciotogneri.greencoffee;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.util.DisplayMetrics;
import java.util.Locale;
public class Localization
{
private final Context context;
public Localization(Context context)
{
this.context = context;
}
public Locale locale()
{
return getSystemLocale(configuration(resources()));
}
public boolean locale(Locale newLocale)
{
Resources resources = resources();
DisplayMetrics displayMetrics = resources.getDisplayMetrics();
Configuration config = configuration(resources);
Locale systemLocale = getSystemLocale(config);
if (!systemLocale.equals(newLocale))
{
updateSystemLocale(config, newLocale);
updateSystemConfiguration(resources, config, displayMetrics);
return true;
}
else
{
return false;
}
}
public void reset()
{
locale(Locale.getDefault());
}
// =============================================================================================
private Resources resources()
{
return context.getResources();
}
private Configuration configuration(Resources resources)
{
return resources.getConfiguration();
}
// =============================================================================================
private Locale getSystemLocale(Configuration config)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
{
return systemLocale(config);
}
else
{
return systemLocaleLegacy(config);
}
}
@SuppressWarnings("deprecation")
private Locale systemLocaleLegacy(Configuration config)
{
return config.locale;
}
@TargetApi(Build.VERSION_CODES.N)
private Locale systemLocale(Configuration config)
{
return config.getLocales().get(0);
}
// =============================================================================================
private void updateSystemLocale(Configuration config, Locale locale)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
{
systemLocale(config, locale);
}
else
{
systemLocaleLegacy(config, locale);
}
}
@SuppressWarnings("deprecation")
private void systemLocaleLegacy(Configuration config, Locale locale)
{
config.locale = locale;
}
@TargetApi(Build.VERSION_CODES.N)
private void systemLocale(Configuration config, Locale locale)
{
config.setLocale(locale);
}
// =============================================================================================
@SuppressWarnings("deprecation")
private void updateSystemConfiguration(Resources resources, Configuration config, DisplayMetrics displayMetrics)
{
resources.updateConfiguration(config, displayMetrics);
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/Scenario.java
================================================
package com.mauriciotogneri.greencoffee;
import java.util.Collections;
import java.util.List;
import gherkin.ast.Step;
public class Scenario
{
private final String name;
private final String description;
private final List<String> tags;
private final List<Step> steps;
public Scenario(String name, String description, List<Step> steps, List<String> tags)
{
this.name = name;
this.description = description;
this.tags = tags;
this.steps = Collections.unmodifiableList(steps);
}
public String name()
{
return name;
}
public String description()
{
return description;
}
public boolean hasTags(List<String> tagList)
{
for (String tag : tagList)
{
if (tags.contains(tag))
{
return true;
}
}
return false;
}
public boolean hasTags(String... tagList)
{
for (String tag : tagList)
{
if (tags.contains(tag))
{
return true;
}
}
return false;
}
public List<Step> steps()
{
return steps;
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/ScenarioConfig.java
================================================
package com.mauriciotogneri.greencoffee;
import java.util.Locale;
public class ScenarioConfig
{
private final Scenario scenario;
private final Locale locale;
private final ScreenshotProvider screenshotProvider;
public ScenarioConfig(Scenario scenario, Locale locale, ScreenshotProvider screenshotProvider)
{
this.scenario = scenario;
this.locale = locale;
this.screenshotProvider = screenshotProvider;
}
public ScenarioConfig(Scenario scenario, Locale locale)
{
this(scenario, locale, ScreenshotProvider.getDefault());
}
public ScenarioConfig(Scenario scenario)
{
this(scenario, null, ScreenshotProvider.getDefault());
}
public Scenario scenario()
{
return scenario;
}
public Locale locale()
{
return (locale != null) ? locale : Locale.getDefault();
}
public Boolean hasScreenshotProvider()
{
return (screenshotProvider != null);
}
public ScreenshotProvider screenshotProvider()
{
return screenshotProvider;
}
@Override
public String toString()
{
if (locale != null)
{
return String.format("%s - %s", scenario.name(), locale.toString());
}
else
{
return scenario.name();
}
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/ScreenCapture.java
================================================
package com.mauriciotogneri.greencoffee;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
import android.support.test.runner.lifecycle.Stage;
import android.view.View;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Collection;
import java.util.Iterator;
class ScreenCapture
{
void takeScreenshot(File file)
{
InstrumentationRegistry.getInstrumentation().runOnMainSync(() ->
{
Collection<Activity> resumedActivities = ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(Stage.RESUMED);
Iterator<Activity> iterator = resumedActivities.iterator();
if (iterator.hasNext())
{
Activity activity = iterator.next();
try
{
takeScreenshot(activity, file);
}
catch (Exception e)
{
// ignore
}
}
});
}
private void takeScreenshot(Activity activity, File file) throws Exception
{
View view = activity.getWindow().getDecorView().getRootView();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache(true);
Bitmap bitmap = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
File parentFolder = file.getParentFile();
if (parentFolder.exists() || parentFolder.mkdirs())
{
FileOutputStream outputStream = new FileOutputStream(file);
bitmap.compress(CompressFormat.JPEG, 100, outputStream);
outputStream.flush();
outputStream.close();
}
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/ScreenshotProvider.java
================================================
package com.mauriciotogneri.greencoffee;
import java.io.File;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import static android.support.test.InstrumentationRegistry.getTargetContext;
public interface ScreenshotProvider
{
static ScreenshotProvider getDefault()
{
return new DefaultScreenshotProvider();
}
void takeScreenshot(Scenario scenario);
class DefaultScreenshotProvider implements ScreenshotProvider
{
private final ScreenCapture screenCapture;
DefaultScreenshotProvider()
{
screenCapture = new ScreenCapture();
}
@Override
public void takeScreenshot(Scenario scenario)
{
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
String fileName = String.format("%s - %s.jpg", scenario.name(), dateFormat.format(new Date()));
File file = new File(getTargetContext().getExternalFilesDir("screenshots"), fileName);
screenCapture.takeScreenshot(file);
}
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/StepDefinition.java
================================================
package com.mauriciotogneri.greencoffee;
import com.mauriciotogneri.greencoffee.exceptions.InvalidMethodSignatureException;
import com.mauriciotogneri.greencoffee.exceptions.StepFailureException;
import java.lang.reflect.Method;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import gherkin.ast.DataTable;
import gherkin.ast.DocString;
import gherkin.ast.Node;
class StepDefinition
{
private final Pattern pattern;
private final Method method;
private final Object target;
StepDefinition(String expression, Method method, Object target)
{
this.pattern = Pattern.compile(expression);
this.method = method;
this.target = target;
}
String pattern()
{
return pattern.pattern();
}
Method method()
{
return method;
}
boolean matches(String text)
{
Matcher matcher = pattern.matcher(text);
return matcher.find();
}
void invoke(String text, Node argument)
{
Matcher matcher = pattern.matcher(text);
if (matcher.find())
{
Object[] parameters;
try
{
parameters = parameters(matcher, argument);
}
catch (Exception e)
{
throw new InvalidMethodSignatureException(method, pattern.pattern(), text);
}
try
{
method.invoke(target, parameters);
}
catch (Exception e)
{
Throwable cause = e.getCause();
throw new StepFailureException(method, pattern.pattern(), text, (cause != null) ? cause.toString() : e.toString());
}
}
else
{
throw new RuntimeException();
}
}
private Object[] parameters(Matcher matcher, Node argument)
{
Object[] parameters = new Object[matcher.groupCount() + ((argument != null) ? 1 : 0)];
Class<?>[] types = method.getParameterTypes();
int limit = (argument != null) ? (parameters.length - 1) : parameters.length;
for (int i = 0; i < limit; i++)
{
parameters[i] = castParameter(matcher.group(i + 1), types[i]);
}
if (argument != null)
{
if (argument.getClass().equals(DocString.class))
{
DocString docString = (DocString) argument;
parameters[parameters.length - 1] = docString.getContent();
}
else if (argument.getClass().equals(DataTable.class))
{
DataTable dataTable = (DataTable) argument;
parameters[parameters.length - 1] = dataTable.getRows();
}
}
return parameters;
}
private Object castParameter(String value, Class<?> clazz)
{
if (clazz.equals(int.class) || clazz.equals(Integer.class))
{
return Integer.parseInt(value);
}
else if (clazz.equals(long.class) || clazz.equals(Long.class))
{
return Long.parseLong(value);
}
else if (clazz.equals(float.class) || clazz.equals(Float.class))
{
return Float.parseFloat(value);
}
else if (clazz.equals(double.class) || clazz.equals(Double.class))
{
return Double.parseDouble(value);
}
else if (clazz.equals(byte.class) || clazz.equals(Byte.class))
{
return Byte.parseByte(value);
}
else if (clazz.equals(short.class) || clazz.equals(Short.class))
{
return Short.parseShort(value);
}
else if (clazz.equals(boolean.class) || clazz.equals(Boolean.class))
{
return Boolean.parseBoolean(value);
}
else if (clazz.equals(char.class) || clazz.equals(Character.class))
{
return value.charAt(0);
}
else
{
return value;
}
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/TestLog.java
================================================
package com.mauriciotogneri.greencoffee;
import android.text.TextUtils;
class TestLog
{
void logScenario(Scenario scenario)
{
log(String.format("Scenario: %s", scenario.name()));
if (!TextUtils.isEmpty(scenario.description()))
{
for (String line : scenario.description().split("\n"))
{
log(String.format("\t%s", line.trim()));
}
}
}
void logStep(String keyword, String text)
{
log(String.format("\t%s %s", keyword, text));
}
private void log(String message)
{
System.out.println(message);
System.out.flush();
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/TimedIdlingResource.java
================================================
package com.mauriciotogneri.greencoffee;
import android.support.test.espresso.Espresso;
import android.support.test.espresso.IdlingResource;
import java.util.concurrent.TimeUnit;
public class TimedIdlingResource implements IdlingResource
{
private final long timeout;
private ResourceCallback resourceCallback;
public TimedIdlingResource(long millis)
{
this.timeout = System.currentTimeMillis() + millis;
}
public TimedIdlingResource(long value, TimeUnit timeUnit)
{
this.timeout = timeUnit.toMillis(value);
}
@Override
public String getName()
{
return getClass().getName() + ":" + (timeout - System.currentTimeMillis());
}
@Override
public boolean isIdleNow()
{
boolean idle = System.currentTimeMillis() >= timeout;
if (idle && (resourceCallback != null))
{
resourceCallback.onTransitionToIdle();
}
return idle;
}
@Override
public void registerIdleTransitionCallback(ResourceCallback resourceCallback)
{
this.resourceCallback = resourceCallback;
}
public void start()
{
Espresso.registerIdlingResources(this);
}
public void stop()
{
Espresso.unregisterIdlingResources(this);
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/annotations/And.java
================================================
package com.mauriciotogneri.greencoffee.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface And
{
String value();
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/annotations/But.java
================================================
package com.mauriciotogneri.greencoffee.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface But
{
String value();
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/annotations/Given.java
================================================
package com.mauriciotogneri.greencoffee.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Given
{
String value();
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/annotations/Then.java
================================================
package com.mauriciotogneri.greencoffee.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Then
{
String value();
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/annotations/When.java
================================================
package com.mauriciotogneri.greencoffee.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface When
{
String value();
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/exceptions/DuplicatedStepDefinitionException.java
================================================
package com.mauriciotogneri.greencoffee.exceptions;
import java.lang.reflect.Method;
public class DuplicatedStepDefinitionException extends RuntimeException
{
public DuplicatedStepDefinitionException(Method method, String pattern)
{
super(String.format("Duplicated step definition%n%nClass: %s%nMethod: %s%nPattern: \"%s\"%n", method.getDeclaringClass().getSimpleName(), method.getName(), pattern));
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/exceptions/InvalidExampleException.java
================================================
package com.mauriciotogneri.greencoffee.exceptions;
public class InvalidExampleException extends RuntimeException
{
public InvalidExampleException(int line, int column)
{
super(String.format("Invalid example format at: [%s, %s]", line, column));
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/exceptions/InvalidMethodSignatureException.java
================================================
package com.mauriciotogneri.greencoffee.exceptions;
import java.lang.reflect.Method;
public class InvalidMethodSignatureException extends RuntimeException
{
public InvalidMethodSignatureException(Method method, String pattern, String text)
{
super(String.format("Invalid number of type of parameters%n%nClass: %s%nMethod: %s%nPattern: \"%s\"%nText matched: \"%s\"%n", method.getDeclaringClass().getSimpleName(), method.getName(), pattern, text));
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/exceptions/InvalidStepDefinitionException.java
================================================
package com.mauriciotogneri.greencoffee.exceptions;
import java.lang.reflect.Method;
public class InvalidStepDefinitionException extends RuntimeException
{
public InvalidStepDefinitionException(Method method)
{
super(String.format("A step definition cannot have more than one annotation%n%nClass: %s%nMethod: %s%n", method.getDeclaringClass().getSimpleName(), method.getName()));
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/exceptions/NoStepsDefinedException.java
================================================
package com.mauriciotogneri.greencoffee.exceptions;
public class NoStepsDefinedException extends RuntimeException
{
public NoStepsDefinedException()
{
super("No steps defined for the feature");
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/exceptions/StepDefinitionNotFoundException.java
================================================
package com.mauriciotogneri.greencoffee.exceptions;
public class StepDefinitionNotFoundException extends RuntimeException
{
public StepDefinitionNotFoundException(String keyword, String text)
{
super(String.format("Step definition not found for: '%s: %s'", keyword, text));
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/exceptions/StepFailureException.java
================================================
package com.mauriciotogneri.greencoffee.exceptions;
import java.lang.reflect.Method;
public class StepFailureException extends RuntimeException
{
public StepFailureException(Method method, String pattern, String text, String cause)
{
super(String.format("Error processing step%n%nClass: %s%nMethod: %s%nPattern: \"%s\"%nText matched: \"%s\"%n%n%s", method.getDeclaringClass().getSimpleName(), method.getName(), pattern, text, cause));
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/interactions/ActionableData.java
================================================
package com.mauriciotogneri.greencoffee.interactions;
import android.support.test.espresso.DataInteraction;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.support.test.espresso.ViewAssertion;
import android.view.View;
import android.widget.TextView;
import org.hamcrest.Matcher;
import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom;
public class ActionableData extends ActionableObject
{
private final DataInteraction dataInteraction;
public ActionableData(DataInteraction dataInteraction)
{
this.dataInteraction = dataInteraction;
}
@Override
public ActionableObject check(ViewAssertion viewAssertion)
{
return new ActionableView(dataInteraction.check(viewAssertion));
}
@Override
public ActionableObject perform(ViewAction viewAction)
{
return new ActionableView(dataInteraction.perform(viewAction));
}
@Override
public String text()
{
String[] stringHolder = {null};
dataInteraction.perform(new ViewAction()
{
@Override
public Matcher<View> getConstraints()
{
return isAssignableFrom(TextView.class);
}
@Override
public String getDescription()
{
return "getting text from a TextView";
}
@Override
public void perform(UiController uiController, View view)
{
TextView textView = (TextView) view;
stringHolder[0] = textView.getText().toString();
}
});
return stringHolder[0];
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/interactions/ActionableObject.java
================================================
package com.mauriciotogneri.greencoffee.interactions;
import android.support.test.espresso.ViewAction;
import android.support.test.espresso.ViewAssertion;
import android.support.test.espresso.action.ViewActions;
import android.support.test.espresso.assertion.ViewAssertions;
import android.support.test.espresso.matcher.BoundedMatcher;
import android.support.test.espresso.matcher.ViewMatchers;
import android.view.View;
import android.widget.ImageView;
import org.hamcrest.Description;
import org.hamcrest.Matchers;
public abstract class ActionableObject
{
public ActionableObject click()
{
return perform(ViewActions.click());
}
public ActionableObject doubleClick()
{
return perform(ViewActions.doubleClick());
}
public ActionableObject longClick()
{
return perform(ViewActions.longClick());
}
public ActionableObject type(String text)
{
return perform(ViewActions.typeText(text));
}
public ActionableObject clearText()
{
return perform(ViewActions.clearText());
}
public ActionableObject scrollTo()
{
return perform(ViewActions.scrollTo());
}
public ActionableObject swipeUp()
{
return perform(ViewActions.swipeUp());
}
public ActionableObject swipeDown()
{
return perform(ViewActions.swipeDown());
}
public ActionableObject swipeLeft()
{
return perform(ViewActions.swipeLeft());
}
public ActionableObject swipeRight()
{
return perform(ViewActions.swipeRight());
}
public ActionableObject doesNotExist()
{
return check(ViewAssertions.doesNotExist());
}
public boolean checkIfDoesNotExist()
{
return checkIf(this::doesNotExist);
}
public ActionableObject contains(Object text)
{
return check(ViewAssertions.matches(ViewMatchers.withText(Matchers.containsString(text.toString()))));
}
public boolean checkIfContains(Object text)
{
return checkIf(() -> contains(text));
}
public ActionableObject doesNotContain(Object text)
{
return check(ViewAssertions.matches(ViewMatchers.withText(Matchers.not(Matchers.containsString(text.toString())))));
}
public boolean checkIfDoesNotContain(Object text)
{
return checkIf(() -> doesNotContain(text));
}
public ActionableObject isEmpty()
{
return check(ViewAssertions.matches(ViewMatchers.withText("")));
}
public boolean checkIfIsEmpty()
{
return checkIf(this::isEmpty);
}
public ActionableObject isNotEmpty()
{
return check(ViewAssertions.matches(Matchers.not(ViewMatchers.withText(""))));
}
public boolean checkIfIsNotEmpty()
{
return checkIf(this::isNotEmpty);
}
public ActionableObject hasFocus()
{
return check(ViewAssertions.matches(ViewMatchers.hasFocus()));
}
public boolean checkIfHasFocus()
{
return checkIf(this::hasFocus);
}
public ActionableObject doesNotHaveFocus()
{
return check(ViewAssertions.matches(Matchers.not(ViewMatchers.hasFocus())));
}
public boolean checkIfDoesNotHaveFocus()
{
return checkIf(this::doesNotHaveFocus);
}
public ActionableObject hasErrorText(Object text)
{
return check(ViewAssertions.matches(ViewMatchers.hasErrorText(text.toString())));
}
public boolean checkIfHasErrorText(Object text)
{
return checkIf(() -> hasErrorText(text));
}
public ActionableObject isChecked()
{
return check(ViewAssertions.matches(ViewMatchers.isChecked()));
}
public boolean checkIfIsChecked()
{
return checkIf(this::isChecked);
}
public ActionableObject isNotChecked()
{
return check(ViewAssertions.matches(ViewMatchers.isNotChecked()));
}
public boolean checkIfIsNotChecked()
{
return checkIf(this::isNotChecked);
}
public ActionableObject isClickable()
{
return check(ViewAssertions.matches(ViewMatchers.isClickable()));
}
public boolean checkIfIsClickable()
{
return checkIf(this::isClickable);
}
public ActionableObject isFocusable()
{
return check(ViewAssertions.matches(ViewMatchers.isFocusable()));
}
public boolean checkIfIsFocusable()
{
return checkIf(this::isFocusable);
}
public ActionableObject isNotFocusable()
{
return check(ViewAssertions.matches(Matchers.not(ViewMatchers.isFocusable())));
}
public boolean checkIfIsNotFocusable()
{
return checkIf(this::isNotFocusable);
}
public ActionableObject isEnabled()
{
return check(ViewAssertions.matches(ViewMatchers.isEnabled()));
}
public boolean checkIfIsEnabled()
{
return checkIf(this::isEnabled);
}
public ActionableObject isDisabled()
{
return check(ViewAssertions.matches(Matchers.not(ViewMatchers.isEnabled())));
}
public boolean checkIfIsDisabled()
{
return checkIf(this::isDisabled);
}
public ActionableObject isSelected()
{
return check(ViewAssertions.matches(ViewMatchers.isSelected()));
}
public boolean checkIfIsSelected()
{
return checkIf(this::isSelected);
}
public ActionableObject isNotSelected()
{
return check(ViewAssertions.matches(Matchers.not(ViewMatchers.isSelected())));
}
public boolean checkIfIsNotSelected()
{
return checkIf(this::isNotSelected);
}
public ActionableObject isDisplayed()
{
return check(ViewAssertions.matches(ViewMatchers.isDisplayed()));
}
public boolean checkIfIsDisplayed()
{
return checkIf(this::isDisplayed);
}
public ActionableObject isCompletelyDisplayed()
{
return check(ViewAssertions.matches(ViewMatchers.isCompletelyDisplayed()));
}
public boolean checkIfIsCompletelyDisplayed()
{
return checkIf(this::isCompletelyDisplayed);
}
public ActionableObject isNotDisplayed()
{
return check(ViewAssertions.matches(Matchers.not(ViewMatchers.isDisplayed())));
}
public boolean checkIfIsNotDisplayed()
{
return checkIf(this::isNotDisplayed);
}
public ActionableObject hasDrawable()
{
return check(ViewAssertions.matches(hasDrawableImageView()));
}
public boolean checkIfHasDrawable()
{
return checkIf(this::hasDrawable);
}
public ActionableObject doesNotHaveDrawable()
{
return check(ViewAssertions.matches(Matchers.not(hasDrawableImageView())));
}
public boolean checkIfDoesNotHaveDrawable()
{
return checkIf(this::doesNotHaveDrawable);
}
public abstract ActionableObject check(ViewAssertion viewAssertion);
public abstract ActionableObject perform(ViewAction viewAction);
public abstract String text();
private boolean checkIf(Runnable runnable)
{
try
{
runnable.run();
return true;
}
catch (Exception e)
{
return false;
}
}
public BoundedMatcher<View, ImageView> hasDrawableImageView()
{
return new BoundedMatcher<View, ImageView>(ImageView.class)
{
@Override
public void describeTo(Description description)
{
description.appendText("has drawable");
}
@Override
public boolean matchesSafely(ImageView imageView)
{
return (imageView.getDrawable() != null);
}
};
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/interactions/ActionableView.java
================================================
package com.mauriciotogneri.greencoffee.interactions;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.support.test.espresso.ViewAssertion;
import android.support.test.espresso.ViewInteraction;
import android.view.View;
import android.widget.TextView;
import org.hamcrest.Matcher;
import static android.support.test.espresso.matcher.ViewMatchers.isAssignableFrom;
public class ActionableView extends ActionableObject
{
private final ViewInteraction viewInteraction;
public ActionableView(ViewInteraction viewInteraction)
{
this.viewInteraction = viewInteraction;
}
@Override
public ActionableObject check(ViewAssertion viewAssertion)
{
return new ActionableView(viewInteraction.check(viewAssertion));
}
@Override
public ActionableObject perform(ViewAction viewAction)
{
return new ActionableView(viewInteraction.perform(viewAction));
}
@Override
public String text()
{
String[] stringHolder = {null};
viewInteraction.perform(new ViewAction()
{
@Override
public Matcher<View> getConstraints()
{
return isAssignableFrom(TextView.class);
}
@Override
public String getDescription()
{
return "getting text from a TextView";
}
@Override
public void perform(UiController uiController, View view)
{
TextView textView = (TextView) view;
stringHolder[0] = textView.getText().toString();
}
});
return stringHolder[0];
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/interactions/DataMatcher.java
================================================
package com.mauriciotogneri.greencoffee.interactions;
import android.support.annotation.IdRes;
import android.support.test.espresso.DataInteraction;
import android.support.test.espresso.matcher.BoundedMatcher;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import static android.support.test.espresso.Espresso.onData;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
public class DataMatcher<T, C>
{
private final int resourceId;
private final Class<T> clazz;
public DataMatcher(@IdRes int resourceId, Class<T> clazz)
{
this.resourceId = resourceId;
this.clazz = clazz;
}
public DataMatcher(Class<T> clazz)
{
this(0, clazz);
}
public ActionableData with(C content)
{
DataInteraction dataInteraction = onData(dataMatcher(content));
if (resourceId != 0)
{
return new ActionableData(dataInteraction.inAdapterView(withId(resourceId)));
}
else
{
return new ActionableData(dataInteraction);
}
}
private Matcher<Object> dataMatcher(C content)
{
DataMatcher<T, C> dataMatcher = this;
return new BoundedMatcher<Object, T>(clazz)
{
@Override
public boolean matchesSafely(T data)
{
return dataMatcher.matches(data, content);
}
@Override
public void describeTo(Description description)
{
description.appendText(String.format("with content: '%s'", content));
}
};
}
public boolean matches(T element, C content)
{
return element.equals(content);
}
}
================================================
FILE: greencoffee/src/main/java/com/mauriciotogneri/greencoffee/interactions/ObjectMatcher.java
================================================
package com.mauriciotogneri.greencoffee.interactions;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
public class ObjectMatcher<T> extends BaseMatcher<T>
{
private final T element;
public ObjectMatcher(T element)
{
this.element = element;
}
@Override
public boolean matches(Object object)
{
return element.equals(object);
}
@Override
public void describeTo(Description description)
{
description.appendText("Spinner matcher for: " + element);
}
}
================================================
FILE: greencoffee/src/main/java/gherkin/AstBuilder.java
================================================
package gherkin;
import gherkin.ast.Background;
import gherkin.ast.Comment;
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 java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import static gherkin.Parser.Builder;
import static gherkin.Parser.RuleType;
import static gherkin.Parser.TokenType;
import static gherkin.StringUtils.join;
public class AstBuilder implements Builder<GherkinDocument> {
private Deque<AstNode> stack;
private List<Comment> comments;
public AstBuilder() {
reset();
}
@Override
public void reset() {
stack = new ArrayDeque<>();
stack.push(new AstNode(RuleType.None));
comments = new ArrayList<>();
}
private AstNode currentNode() {
return stack.peek();
}
@Override
public void build(Token token) {
RuleType ruleType = RuleType.cast(token.matchedType);
if (token.matchedType == TokenType.Comment) {
comments.add(new Comment(getLocation(token, 0), token.matchedText));
} else {
currentNode().add(ruleType, token);
}
}
@Override
public void startRule(RuleType ruleType) {
stack.push(new AstNode(ruleType));
}
@Override
public void endRule(RuleType ruleType) {
AstNode node = stack.pop();
Object transformedNode = getTransformedNode(node);
currentNode().add(node.ruleType, transformedNode);
}
private Object getTransformedNode(AstNode node) {
switch (node.ruleType) {
case Step: {
Token stepLine = node.getToken(TokenType.StepLine);
Node stepArg = node.getSingle(RuleType.DataTable, null);
if (stepArg == null) {
stepArg = node.getSingle(RuleType.DocString, null);
}
return new Step(getLocation(stepLine, 0), stepLine.matchedKeyword, stepLine.matchedText, stepArg);
}
case DocString: {
Token separatorToken = node.getTokens(TokenType.DocStringSeparator).get(0);
String contentType = separatorToken.matchedText.length() > 0 ? separatorToken.matchedText : null;
List<Token> lineTokens = node.getTokens(TokenType.Other);
StringBuilder content = new StringBuilder();
boolean newLine = false;
for (Token lineToken : lineTokens) {
if (newLine) content.append("\n");
newLine = true;
content.append(lineToken.matchedText);
}
return new DocString(getLocation(separatorToken, 0), contentType, content.toString());
}
case DataTable: {
List<TableRow> rows = getTableRows(node);
return new DataTable(rows);
}
case Background: {
Token backgroundLine = node.getToken(TokenType.BackgroundLine);
String description = getDescription(node);
List<Step> steps = getSteps(node);
return new Background(getLocation(backgroundLine, 0), backgroundLine.matchedKeyword, backgroundLine.matchedText, description, steps);
}
case Scenario_Definition: {
List<Tag> tags = getTags(node);
AstNode scenarioNode = node.getSingle(RuleType.Scenario, null);
if (scenarioNode != null) {
Token scenarioLine = scenarioNode.getToken(TokenType.ScenarioLine);
String description = getDescription(scenarioNode);
List<Step> steps = getSteps(scenarioNode);
return new Scenario(tags, getLocation(scenarioLine, 0), scenarioLine.matchedKeyword, scenarioLine.matchedText, description, steps);
} else {
AstNode scenarioOutlineNode = node.getSingle(RuleType.ScenarioOutline, null);
if (scenarioOutlineNode == null) {
throw new RuntimeException("Internal grammar error");
}
Token scenarioOutlineLine = scenarioOutlineNode.getToken(TokenType.ScenarioOutlineLine);
String description = getDescription(scenarioOutlineNode);
List<Step> steps = getSteps(scenarioOutlineNode);
List<Examples> examplesList = scenarioOutlineNode.getItems(RuleType.Examples_Definition);
return new ScenarioOutline(tags, getLocation(scenarioOutlineLine, 0), scenarioOutlineLine.matchedKeyword, scenarioOutlineLine.matchedText, description, steps, examplesList);
}
}
case Examples_Definition: {
List<Tag> tags = getTags(node);
AstNode examplesNode = node.getSingle(RuleType.Examples, null);
Token examplesLine = examplesNode.getToken(TokenType.ExamplesLine);
String description = getDescription(examplesNode);
List<TableRow> rows = examplesNode.getSingle(RuleType.Examples_Table, null);
TableRow tableHeader = rows != null && !rows.isEmpty() ? rows.get(0) : null;
List<TableRow> tableBody = rows != null && !rows.isEmpty() ? rows.subList(1, rows.size()) : null;
return new Examples(getLocation(examplesLine, 0), tags, examplesLine.matchedKeyword, examplesLine.matchedText, description, tableHeader, tableBody);
}
case Examples_Table: {
return getTableRows(node);
}
case Description: {
List<Token> lineTokens = node.getTokens(TokenType.Other);
// Trim trailing empty lines
int end = lineTokens.size();
while (end > 0 && lineTokens.get(end - 1).matchedText.matches("\\s*")) {
end--;
}
lineTokens = lineTokens.subList(0, end);
return join(new StringUtils.ToString<Token>() {
@Override
public String toString(Token t) {
return t.matchedText;
}
}, "\n", lineTokens);
}
case Feature: {
AstNode header = node.getSingle(RuleType.Feature_Header, new AstNode(RuleType.Feature_Header));
if (header == null) return null;
List<Tag> tags = getTags(header);
Token featureLine = header.getToken(TokenType.FeatureLine);
if (featureLine == null) return null;
List<ScenarioDefinition> scenarioDefinitions = new ArrayList<>();
Background background = node.getSingle(RuleType.Background, null);
if (background != null) scenarioDefinitions.add(background);
scenarioDefinitions.addAll(node.<ScenarioDefinition>getItems(RuleType.Scenario_Definition));
String description = getDescription(header);
if (featureLine.matchedGherkinDialect == null) return null;
String language = featureLine.matchedGherkinDialect.getLanguage();
return new Feature(tags, getLocation(featureLine, 0), language, featureLine.matchedKeyword, featureLine.matchedText, description, scenarioDefinitions);
}
case GherkinDocument: {
Feature feature = node.getSingle(RuleType.Feature, null);
return new GherkinDocument(feature, comments);
}
}
return node;
}
private List<TableRow> getTableRows(AstNode node) {
List<TableRow> rows = new ArrayList<>();
for (Token token : node.getTokens(TokenType.TableRow)) {
rows.add(new TableRow(getLocation(token, 0), getCells(token)));
}
ensureCellCount(rows);
return rows;
}
private void ensureCellCount(List<TableRow> rows) {
if (rows.isEmpty()) return;
int cellCount = rows.get(0).getCells().size();
for (TableRow row : rows) {
if (row.getCells().size() != cellCount) {
throw new ParserException.AstBuilderException("inconsistent cell count within the table", row.getLocation());
}
}
}
private List<TableCell> getCells(Token token) {
List<TableCell> cells = new ArrayList<>();
for (GherkinLineSpan cellItem : token.mathcedItems) {
cells.add(new TableCell(getLocation(token, cellItem.column), cellItem.text));
}
return cells;
}
private List<Step> getSteps(AstNode node) {
return node.getItems(RuleType.Step);
}
private Location getLocation(Token token, int column) {
return column == 0 ? token.location : new Location(token.location.getLine(), column);
}
private String getDescription(AstNode node) {
return node.getSingle(RuleType.Description, null);
}
private List<Tag> getTags(AstNode node) {
AstNode tagsNode = node.getSingle(RuleType.Tags, new AstNode(RuleType.None));
if (tagsNode == null)
return new ArrayList<>();
List<Token> tokens = tagsNode.getTokens(TokenType.TagLine);
List<Tag> tags = new ArrayList<>();
for (Token token : tokens) {
for (GherkinLineSpan tagItem : token.mathcedItems) {
tags.add(new Tag(getLocation(token, tagItem.column), tagItem.text));
}
}
return tags;
}
@Override
public GherkinDocument getResult() {
return currentNode().getSingle(RuleType.GherkinDocument, null);
}
}
================================================
FILE: greencoffee/src/main/java/gherkin/AstNode.java
================================================
package gherkin;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static gherkin.Parser.RuleType;
import static gherkin.Parser.TokenType;
public class AstNode {
private final Map<RuleType, List<Object>> subItems = new HashMap<RuleType, List<Object>>();
public final RuleType ruleType;
public AstNode(RuleType ruleType) {
this.ruleType = ruleType;
}
public void add(RuleType ruleType, Object obj) {
List<Object> items = subItems.get(ruleType);
if (items == null) {
items = new ArrayList<Object>();
subItems.put(ruleType, items);
}
items.add(obj);
}
public <T> T getSingle(RuleType ruleType, T defaultResult) {
List<Object> items = getItems(ruleType);
return (T) (items.isEmpty() ? defaultResult : items.get(0));
}
public <T> List<T> getItems(RuleType ruleType) {
List<T> items = (List<T>) subItems.get(ruleType);
if (items == null) {
return Collections.emptyList();
}
return items;
}
public Token getToken(TokenType tokenType) {
RuleType ruleType = RuleType.cast(tokenType);
return getSingle(ruleType, new Token(null, null));
}
public List<Token> getTokens(TokenType tokenType) {
return getItems(RuleType.cast(tokenType));
}
}
================================================
FILE: greencoffee/src/main/java/gherkin/Func.java
================================================
package gherkin;
public interface Func<V> {
V call();
}
================================================
FILE: greencoffee/src/main/java/gherkin/GenerateTokens.java
================================================
package gherkin;
import gherkin.stream.Stdio;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
public class GenerateTokens {
public static void main(String[] args) throws FileNotFoundException, UnsupportedEncodingException {
TokenFormatterBuilder builder = new TokenFormatterBuilder();
Parser<String> parser = new Parser<>(builder);
TokenMatcher matcher = new TokenMatcher();
for (String fileName : args) {
InputStreamReader in = new InputStreamReader(new FileInputStream(fileName), "UTF-8");
String result = parser.parse(in, matcher);
Stdio.out.print(result);
Stdio.out.flush(); // print doesn't autoflush
}
}
}
================================================
FILE: greencoffee/src/main/java/gherkin/GherkinDialect.java
================================================
package gherkin;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class GherkinDialect {
private final Map<String, List<String>> keywords;
private String language;
public GherkinDialect(String language, Map<String, List<String>> keywords) {
this.language = language;
this.keywords = keywords;
}
public List<String> getFeatureKeywords() {
return keywords.get("feature");
}
public List<String> getScenarioKeywords() {
return keywords.get("scenario");
}
public List<String> getStepKeywords() {
List<String> result = new ArrayList<>();
result.addAll(keywords.get("given"));
result.addAll(keywords.get("when"));
result.addAll(keywords.get("then"));
result.addAll(keywords.get("and"));
result.addAll(keywords.get("but"));
return result;
}
public List<String> getBackgroundKeywords() {
return keywords.get("background");
}
public List<String> getScenarioOutlineKeywords() {
return keywords.get("scenarioOutline");
}
public List<String> getExamplesKeywords() {
return keywords.get("examples");
}
public String getLanguage() {
return language;
}
}
================================================
FILE: greencoffee/src/main/java/gherkin/GherkinDialectProvider.java
================================================
package gherkin;
import java.util.List;
import java.util.Map;
import gherkin.ast.Location;
import gherkin.deps.com.google.gson.Gson;
public class GherkinDialectProvider implements IGherkinDialectProvider {
private static Map<String, Map<String, List<String>>> DIALECTS;
private final String default_dialect_name;
static {
Gson gson = new Gson();
try {
//Reader dialects = new InputStreamReader(GherkinDialectProvider.class.getResourceAsStream("/gherkin/gherkin-languages.json"), "UTF-8");
String dialects = "{\n" +
" \"af\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"En \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Agtergrond\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Maar \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Voorbeelde\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Funksie\",\n" +
" \"Besigheid Behoefte\",\n" +
" \"Vermoë\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Gegewe \"\n" +
" ],\n" +
" \"name\": \"Afrikaans\",\n" +
" \"native\": \"Afrikaans\",\n" +
" \"scenario\": [\n" +
" \"Situasie\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Situasie Uiteensetting\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Dan \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Wanneer \"\n" +
" ]\n" +
" },\n" +
" \"am\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Եվ \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Կոնտեքստ\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Բայց \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Օրինակներ\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Ֆունկցիոնալություն\",\n" +
" \"Հատկություն\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Դիցուք \"\n" +
" ],\n" +
" \"name\": \"Armenian\",\n" +
" \"native\": \"հայերեն\",\n" +
" \"scenario\": [\n" +
" \"Սցենար\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Սցենարի կառուցվացքը\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Ապա \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Եթե \",\n" +
" \"Երբ \"\n" +
" ]\n" +
" },\n" +
" \"ar\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"و \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"الخلفية\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"لكن \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"امثلة\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"خاصية\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"بفرض \"\n" +
" ],\n" +
" \"name\": \"Arabic\",\n" +
" \"native\": \"العربية\",\n" +
" \"scenario\": [\n" +
" \"سيناريو\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"سيناريو مخطط\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"اذاً \",\n" +
" \"ثم \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"متى \",\n" +
" \"عندما \"\n" +
" ]\n" +
" },\n" +
" \"ast\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Y \",\n" +
" \"Ya \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Antecedentes\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Peru \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Exemplos\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Carauterística\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Dáu \",\n" +
" \"Dada \",\n" +
" \"Daos \",\n" +
" \"Daes \"\n" +
" ],\n" +
" \"name\": \"Asturian\",\n" +
" \"native\": \"asturianu\",\n" +
" \"scenario\": [\n" +
" \"Casu\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Esbozu del casu\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Entós \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Cuando \"\n" +
" ]\n" +
" },\n" +
" \"az\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Və \",\n" +
" \"Həm \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Keçmiş\",\n" +
" \"Kontekst\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Amma \",\n" +
" \"Ancaq \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Nümunələr\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Özəllik\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Tutaq ki \",\n" +
" \"Verilir \"\n" +
" ],\n" +
" \"name\": \"Azerbaijani\",\n" +
" \"native\": \"Azərbaycanca\",\n" +
" \"scenario\": [\n" +
" \"Ssenari\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Ssenarinin strukturu\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"O halda \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Əgər \",\n" +
" \"Nə vaxt ki \"\n" +
" ]\n" +
" },\n" +
" \"bg\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"И \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Предистория\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Но \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Примери\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Функционалност\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Дадено \"\n" +
" ],\n" +
" \"name\": \"Bulgarian\",\n" +
" \"native\": \"български\",\n" +
" \"scenario\": [\n" +
" \"Сценарий\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Рамка на сценарий\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"То \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Когато \"\n" +
" ]\n" +
" },\n" +
" \"bm\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Dan \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Latar Belakang\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Tetapi \",\n" +
" \"Tapi \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Contoh\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Fungsi\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Diberi \",\n" +
" \"Bagi \"\n" +
" ],\n" +
" \"name\": \"Malay\",\n" +
" \"native\": \"Bahasa Melayu\",\n" +
" \"scenario\": [\n" +
" \"Senario\",\n" +
" \"Situasi\",\n" +
" \"Keadaan\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Kerangka Senario\",\n" +
" \"Kerangka Situasi\",\n" +
" \"Kerangka Keadaan\",\n" +
" \"Garis Panduan Senario\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Maka \",\n" +
" \"Kemudian \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Apabila \"\n" +
" ]\n" +
" },\n" +
" \"bs\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"I \",\n" +
" \"A \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Pozadina\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Ali \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Primjeri\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Karakteristika\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Dato \"\n" +
" ],\n" +
" \"name\": \"Bosnian\",\n" +
" \"native\": \"Bosanski\",\n" +
" \"scenario\": [\n" +
" \"Scenariju\",\n" +
" \"Scenario\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Scenariju-obris\",\n" +
" \"Scenario-outline\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Zatim \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Kada \"\n" +
" ]\n" +
" },\n" +
" \"ca\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"I \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Rerefons\",\n" +
" \"Antecedents\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Però \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Exemples\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Característica\",\n" +
" \"Funcionalitat\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Donat \",\n" +
" \"Donada \",\n" +
" \"Atès \",\n" +
" \"Atesa \"\n" +
" ],\n" +
" \"name\": \"Catalan\",\n" +
" \"native\": \"català\",\n" +
" \"scenario\": [\n" +
" \"Escenari\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Esquema de l'escenari\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Aleshores \",\n" +
" \"Cal \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Quan \"\n" +
" ]\n" +
" },\n" +
" \"cs\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"A také \",\n" +
" \"A \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Pozadí\",\n" +
" \"Kontext\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Ale \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Příklady\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Požadavek\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Pokud \",\n" +
" \"Za předpokladu \"\n" +
" ],\n" +
" \"name\": \"Czech\",\n" +
" \"native\": \"Česky\",\n" +
" \"scenario\": [\n" +
" \"Scénář\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Náčrt Scénáře\",\n" +
" \"Osnova scénáře\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Pak \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Když \"\n" +
" ]\n" +
" },\n" +
" \"cy-GB\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"A \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Cefndir\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Ond \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Enghreifftiau\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Arwedd\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Anrhegedig a \"\n" +
" ],\n" +
" \"name\": \"Welsh\",\n" +
" \"native\": \"Cymraeg\",\n" +
" \"scenario\": [\n" +
" \"Scenario\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Scenario Amlinellol\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Yna \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Pryd \"\n" +
" ]\n" +
" },\n" +
" \"da\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Og \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Baggrund\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Men \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Eksempler\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Egenskab\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Givet \"\n" +
" ],\n" +
" \"name\": \"Danish\",\n" +
" \"native\": \"dansk\",\n" +
" \"scenario\": [\n" +
" \"Scenarie\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Abstrakt Scenario\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Så \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Når \"\n" +
" ]\n" +
" },\n" +
" \"de\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Und \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Grundlage\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Aber \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Beispiele\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Funktionalität\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Angenommen \",\n" +
" \"Gegeben sei \",\n" +
" \"Gegeben seien \"\n" +
" ],\n" +
" \"name\": \"German\",\n" +
" \"native\": \"Deutsch\",\n" +
" \"scenario\": [\n" +
" \"Szenario\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Szenariogrundriss\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Dann \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Wenn \"\n" +
" ]\n" +
" },\n" +
" \"el\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Και \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Υπόβαθρο\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Αλλά \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Παραδείγματα\",\n" +
" \"Σενάρια\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Δυνατότητα\",\n" +
" \"Λειτουργία\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Δεδομένου \"\n" +
" ],\n" +
" \"name\": \"Greek\",\n" +
" \"native\": \"Ελληνικά\",\n" +
" \"scenario\": [\n" +
" \"Σενάριο\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Περιγραφή Σεναρίου\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Τότε \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Όταν \"\n" +
" ]\n" +
" },\n" +
" \"em\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"\uD83D\uDE02\"\n" +
" ],\n" +
" \"background\": [\n" +
" \"\uD83D\uDCA4\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"\uD83D\uDE14\"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"\uD83D\uDCD3\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"\uD83D\uDCDA\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"\uD83D\uDE10\"\n" +
" ],\n" +
" \"name\": \"Emoji\",\n" +
" \"native\": \"\uD83D\uDE00\",\n" +
" \"scenario\": [\n" +
" \"\uD83D\uDCD5\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"\uD83D\uDCD6\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"\uD83D\uDE4F\"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"\uD83C\uDFAC\"\n" +
" ]\n" +
" },\n" +
" \"en\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"And \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Background\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"But \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Examples\",\n" +
" \"Scenarios\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Feature\",\n" +
" \"Business Need\",\n" +
" \"Ability\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Given \"\n" +
" ],\n" +
" \"name\": \"English\",\n" +
" \"native\": \"English\",\n" +
" \"scenario\": [\n" +
" \"Scenario\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Scenario Outline\",\n" +
" \"Scenario Template\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Then \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"When \"\n" +
" ]\n" +
" },\n" +
" \"en-Scouse\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"An \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Dis is what went down\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Buh \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Examples\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Feature\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Givun \",\n" +
" \"Youse know when youse got \"\n" +
" ],\n" +
" \"name\": \"Scouse\",\n" +
" \"native\": \"Scouse\",\n" +
" \"scenario\": [\n" +
" \"The thing of it is\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Wharrimean is\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Dun \",\n" +
" \"Den youse gotta \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Wun \",\n" +
" \"Youse know like when \"\n" +
" ]\n" +
" },\n" +
" \"en-au\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Too right \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"First off\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Yeah nah \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"You'll wanna\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Pretty much\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Y'know \"\n" +
" ],\n" +
" \"name\": \"Australian\",\n" +
" \"native\": \"Australian\",\n" +
" \"scenario\": [\n" +
" \"Awww, look mate\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Reckon it's like\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"But at the end of the day I reckon \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"It's just unbelievable \"\n" +
" ]\n" +
" },\n" +
" \"en-lol\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"AN \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"B4\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"BUT \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"EXAMPLZ\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"OH HAI\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"I CAN HAZ \"\n" +
" ],\n" +
" \"name\": \"LOLCAT\",\n" +
" \"native\": \"LOLCAT\",\n" +
" \"scenario\": [\n" +
" \"MISHUN\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"MISHUN SRSLY\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"DEN \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"WEN \"\n" +
" ]\n" +
" },\n" +
" \"en-old\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Ond \",\n" +
" \"7 \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Aer\",\n" +
" \"Ær\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Ac \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Se the\",\n" +
" \"Se þe\",\n" +
" \"Se ðe\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Hwaet\",\n" +
" \"Hwæt\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Thurh \",\n" +
" \"Þurh \",\n" +
" \"Ðurh \"\n" +
" ],\n" +
" \"name\": \"Old English\",\n" +
" \"native\": \"Englisc\",\n" +
" \"scenario\": [\n" +
" \"Swa\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Swa hwaer swa\",\n" +
" \"Swa hwær swa\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Tha \",\n" +
" \"Þa \",\n" +
" \"Ða \",\n" +
" \"Tha the \",\n" +
" \"Þa þe \",\n" +
" \"Ða ðe \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Tha \",\n" +
" \"Þa \",\n" +
" \"Ða \"\n" +
" ]\n" +
" },\n" +
" \"en-pirate\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Aye \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Yo-ho-ho\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Avast! \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Dead men tell no tales\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Ahoy matey!\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Gangway! \"\n" +
" ],\n" +
" \"name\": \"Pirate\",\n" +
" \"native\": \"Pirate\",\n" +
" \"scenario\": [\n" +
" \"Heave to\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Shiver me timbers\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Let go and haul \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Blimey! \"\n" +
" ]\n" +
" },\n" +
" \"eo\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Kaj \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Fono\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Sed \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Ekzemploj\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Trajto\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Donitaĵo \",\n" +
" \"Komence \"\n" +
" ],\n" +
" \"name\": \"Esperanto\",\n" +
" \"native\": \"Esperanto\",\n" +
" \"scenario\": [\n" +
" \"Scenaro\",\n" +
" \"Kazo\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Konturo de la scenaro\",\n" +
" \"Skizo\",\n" +
" \"Kazo-skizo\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Do \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Se \"\n" +
" ]\n" +
" },\n" +
" \"es\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Y \",\n" +
" \"E \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Antecedentes\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Pero \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Ejemplos\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Característica\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Dado \",\n" +
" \"Dada \",\n" +
" \"Dados \",\n" +
" \"Dadas \"\n" +
" ],\n" +
" \"name\": \"Spanish\",\n" +
" \"native\": \"español\",\n" +
" \"scenario\": [\n" +
" \"Escenario\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Esquema del escenario\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Entonces \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Cuando \"\n" +
" ]\n" +
" },\n" +
" \"et\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Ja \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Taust\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Kuid \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Juhtumid\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Omadus\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Eeldades \"\n" +
" ],\n" +
" \"name\": \"Estonian\",\n" +
" \"native\": \"eesti keel\",\n" +
" \"scenario\": [\n" +
" \"Stsenaarium\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Raamstsenaarium\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Siis \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Kui \"\n" +
" ]\n" +
" },\n" +
" \"fa\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"و \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"زمینه\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"اما \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"نمونه ها\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"وِیژگی\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"با فرض \"\n" +
" ],\n" +
" \"name\": \"Persian\",\n" +
" \"native\": \"فارسی\",\n" +
" \"scenario\": [\n" +
" \"سناریو\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"الگوی سناریو\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"آنگاه \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"هنگامی \"\n" +
" ]\n" +
" },\n" +
" \"fi\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Ja \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Tausta\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Mutta \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Tapaukset\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Ominaisuus\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Oletetaan \"\n" +
" ],\n" +
" \"name\": \"Finnish\",\n" +
" \"native\": \"suomi\",\n" +
" \"scenario\": [\n" +
" \"Tapaus\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Tapausaihio\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Niin \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Kun \"\n" +
" ]\n" +
" },\n" +
" \"fr\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Et que \",\n" +
" \"Et qu'\",\n" +
" \"Et \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Contexte\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Mais que \",\n" +
" \"Mais qu'\",\n" +
" \"Mais \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Exemples\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Fonctionnalité\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Soit \",\n" +
" \"Etant donné que \",\n" +
" \"Etant donné qu'\",\n" +
" \"Etant donné \",\n" +
" \"Etant donnée \",\n" +
" \"Etant donnés \",\n" +
" \"Etant données \",\n" +
" \"Étant donné que \",\n" +
" \"Étant donné qu'\",\n" +
" \"Étant donné \",\n" +
" \"Étant donnée \",\n" +
" \"Étant donnés \",\n" +
" \"Étant données \"\n" +
" ],\n" +
" \"name\": \"French\",\n" +
" \"native\": \"français\",\n" +
" \"scenario\": [\n" +
" \"Scénario\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Plan du scénario\",\n" +
" \"Plan du Scénario\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Alors \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Quand \",\n" +
" \"Lorsque \",\n" +
" \"Lorsqu'\"\n" +
" ]\n" +
" },\n" +
" \"ga\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Agus\"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Cúlra\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Ach\"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Samplaí\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Gné\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Cuir i gcás go\",\n" +
" \"Cuir i gcás nach\",\n" +
" \"Cuir i gcás gur\",\n" +
" \"Cuir i gcás nár\"\n" +
" ],\n" +
" \"name\": \"Irish\",\n" +
" \"native\": \"Gaeilge\",\n" +
" \"scenario\": [\n" +
" \"Cás\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Cás Achomair\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Ansin\"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Nuair a\",\n" +
" \"Nuair nach\",\n" +
" \"Nuair ba\",\n" +
" \"Nuair nár\"\n" +
" ]\n" +
" },\n" +
" \"gj\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"અને \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"બેકગ્રાઉન્ડ\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"પણ \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"ઉદાહરણો\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"લક્ષણ\",\n" +
" \"વ્યાપાર જરૂર\",\n" +
" \"ક્ષમતા\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"આપેલ છે \"\n" +
" ],\n" +
" \"name\": \"Gujarati\",\n" +
" \"native\": \"ગુજરાતી\",\n" +
" \"scenario\": [\n" +
" \"સ્થિતિ\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"પરિદ્દશ્ય રૂપરેખા\",\n" +
" \"પરિદ્દશ્ય ઢાંચો\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"પછી \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"ક્યારે \"\n" +
" ]\n" +
" },\n" +
" \"gl\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"E \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Contexto\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Mais \",\n" +
" \"Pero \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Exemplos\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Característica\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Dado \",\n" +
" \"Dada \",\n" +
" \"Dados \",\n" +
" \"Dadas \"\n" +
" ],\n" +
" \"name\": \"Galician\",\n" +
" \"native\": \"galego\",\n" +
" \"scenario\": [\n" +
" \"Escenario\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Esbozo do escenario\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Entón \",\n" +
" \"Logo \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Cando \"\n" +
" ]\n" +
" },\n" +
" \"he\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"וגם \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"רקע\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"אבל \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"דוגמאות\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"תכונה\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"בהינתן \"\n" +
" ],\n" +
" \"name\": \"Hebrew\",\n" +
" \"native\": \"עברית\",\n" +
" \"scenario\": [\n" +
" \"תרחיש\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"תבנית תרחיש\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"אז \",\n" +
" \"אזי \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"כאשר \"\n" +
" ]\n" +
" },\n" +
" \"hi\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"और \",\n" +
" \"तथा \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"पृष्ठभूमि\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"पर \",\n" +
" \"परन्तु \",\n" +
" \"किन्तु \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"उदाहरण\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"रूप लेख\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"अगर \",\n" +
" \"यदि \",\n" +
" \"चूंकि \"\n" +
" ],\n" +
" \"name\": \"Hindi\",\n" +
" \"native\": \"हिंदी\",\n" +
" \"scenario\": [\n" +
" \"परिदृश्य\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"परिदृश्य रूपरेखा\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"तब \",\n" +
" \"तदा \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"जब \",\n" +
" \"कदा \"\n" +
" ]\n" +
" },\n" +
" \"hr\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"I \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Pozadina\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Ali \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Primjeri\",\n" +
" \"Scenariji\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Osobina\",\n" +
" \"Mogućnost\",\n" +
" \"Mogucnost\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Zadan \",\n" +
" \"Zadani \",\n" +
" \"Zadano \"\n" +
" ],\n" +
" \"name\": \"Croatian\",\n" +
" \"native\": \"hrvatski\",\n" +
" \"scenario\": [\n" +
" \"Scenarij\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Skica\",\n" +
" \"Koncept\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Onda \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Kada \",\n" +
" \"Kad \"\n" +
" ]\n" +
" },\n" +
" \"ht\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Ak \",\n" +
" \"Epi \",\n" +
" \"E \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Kontèks\",\n" +
" \"Istorik\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Men \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Egzanp\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Karakteristik\",\n" +
" \"Mak\",\n" +
" \"Fonksyonalite\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Sipoze \",\n" +
" \"Sipoze ke \",\n" +
" \"Sipoze Ke \"\n" +
" ],\n" +
" \"name\": \"Creole\",\n" +
" \"native\": \"kreyòl\",\n" +
" \"scenario\": [\n" +
" \"Senaryo\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Plan senaryo\",\n" +
" \"Plan Senaryo\",\n" +
" \"Senaryo deskripsyon\",\n" +
" \"Senaryo Deskripsyon\",\n" +
" \"Dyagram senaryo\",\n" +
" \"Dyagram Senaryo\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Lè sa a \",\n" +
" \"Le sa a \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Lè \",\n" +
" \"Le \"\n" +
" ]\n" +
" },\n" +
" \"hu\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"És \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Háttér\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"De \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Példák\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Jellemző\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Amennyiben \",\n" +
" \"Adott \"\n" +
" ],\n" +
" \"name\": \"Hungarian\",\n" +
" \"native\": \"magyar\",\n" +
" \"scenario\": [\n" +
" \"Forgatókönyv\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Forgatókönyv vázlat\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Akkor \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Majd \",\n" +
" \"Ha \",\n" +
" \"Amikor \"\n" +
" ]\n" +
" },\n" +
" \"id\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Dan \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Dasar\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Tapi \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Contoh\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Fitur\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Dengan \"\n" +
" ],\n" +
" \"name\": \"Indonesian\",\n" +
" \"native\": \"Bahasa Indonesia\",\n" +
" \"scenario\": [\n" +
" \"Skenario\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Skenario konsep\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Maka \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Ketika \"\n" +
" ]\n" +
" },\n" +
" \"is\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Og \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Bakgrunnur\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"En \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Dæmi\",\n" +
" \"Atburðarásir\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Eiginleiki\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Ef \"\n" +
" ],\n" +
" \"name\": \"Icelandic\",\n" +
" \"native\": \"Íslenska\",\n" +
" \"scenario\": [\n" +
" \"Atburðarás\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Lýsing Atburðarásar\",\n" +
" \"Lýsing Dæma\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Þá \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Þegar \"\n" +
" ]\n" +
" },\n" +
" \"it\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"E \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Contesto\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Ma \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Esempi\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Funzionalità\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Dato \",\n" +
" \"Data \",\n" +
" \"Dati \",\n" +
" \"Date \"\n" +
" ],\n" +
" \"name\": \"Italian\",\n" +
" \"native\": \"italiano\",\n" +
" \"scenario\": [\n" +
" \"Scenario\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Schema dello scenario\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Allora \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Quando \"\n" +
" ]\n" +
" },\n" +
" \"ja\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"かつ\"\n" +
" ],\n" +
" \"background\": [\n" +
" \"背景\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"しかし\",\n" +
" \"但し\",\n" +
" \"ただし\"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"例\",\n" +
" \"サンプル\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"フィーチャ\",\n" +
" \"機能\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"前提\"\n" +
" ],\n" +
" \"name\": \"Japanese\",\n" +
" \"native\": \"日本語\",\n" +
" \"scenario\": [\n" +
" \"シナリオ\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"シナリオアウトライン\",\n" +
" \"シナリオテンプレート\",\n" +
" \"テンプレ\",\n" +
" \"シナリオテンプレ\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"ならば\"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"もし\"\n" +
" ]\n" +
" },\n" +
" \"jv\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Lan \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Dasar\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Tapi \",\n" +
" \"Nanging \",\n" +
" \"Ananging \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Conto\",\n" +
" \"Contone\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Fitur\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Nalika \",\n" +
" \"Nalikaning \"\n" +
" ],\n" +
" \"name\": \"Javanese\",\n" +
" \"native\": \"Basa Jawa\",\n" +
" \"scenario\": [\n" +
" \"Skenario\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Konsep skenario\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Njuk \",\n" +
" \"Banjur \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Manawa \",\n" +
" \"Menawa \"\n" +
" ]\n" +
" },\n" +
" \"ka\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"და\"\n" +
" ],\n" +
" \"background\": [\n" +
" \"კონტექსტი\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"მაგ\u00ADრამ\"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"მაგალითები\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"თვისება\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"მოცემული\"\n" +
" ],\n" +
" \"name\": \"Georgian\",\n" +
" \"native\": \"ქართველი\",\n" +
" \"scenario\": [\n" +
" \"სცენარის\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"სცენარის ნიმუში\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"მაშინ\"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"როდესაც\"\n" +
" ]\n" +
" },\n" +
" \"kn\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"ಮತ್ತು \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"ಹಿನ್ನೆಲೆ\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"ಆದರೆ \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"ಉದಾಹರಣೆಗಳು\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"ಹೆಚ್ಚಳ\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"ನೀಡಿದ \"\n" +
" ],\n" +
" \"name\": \"Kannada\",\n" +
" \"native\": \"ಕನ್ನಡ\",\n" +
" \"scenario\": [\n" +
" \"ಕಥಾಸಾರಾಂಶ\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"ವಿವರಣೆ\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"ನಂತರ \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"ಸ್ಥಿತಿಯನ್ನು \"\n" +
" ]\n" +
" },\n" +
" \"ko\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"그리고\"\n" +
" ],\n" +
" \"background\": [\n" +
" \"배경\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"하지만\",\n" +
" \"단\"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"예\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"기능\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"조건\",\n" +
" \"먼저\"\n" +
" ],\n" +
" \"name\": \"Korean\",\n" +
" \"native\": \"한국어\",\n" +
" \"scenario\": [\n" +
" \"시나리오\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"시나리오 개요\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"그러면\"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"만일\",\n" +
" \"만약\"\n" +
" ]\n" +
" },\n" +
" \"lt\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Ir \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Kontekstas\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Bet \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Pavyzdžiai\",\n" +
" \"Scenarijai\",\n" +
" \"Variantai\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Savybė\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Duota \"\n" +
" ],\n" +
" \"name\": \"Lithuanian\",\n" +
" \"native\": \"lietuvių kalba\",\n" +
" \"scenario\": [\n" +
" \"Scenarijus\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Scenarijaus šablonas\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Tada \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Kai \"\n" +
" ]\n" +
" },\n" +
" \"lu\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"an \",\n" +
" \"a \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Hannergrond\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"awer \",\n" +
" \"mä \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Beispiller\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Funktionalitéit\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"ugeholl \"\n" +
" ],\n" +
" \"name\": \"Luxemburgish\",\n" +
" \"native\": \"Lëtzebuergesch\",\n" +
" \"scenario\": [\n" +
" \"Szenario\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Plang vum Szenario\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"dann \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"wann \"\n" +
" ]\n" +
" },\n" +
" \"lv\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Un \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Konteksts\",\n" +
" \"Situācija\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Bet \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Piemēri\",\n" +
" \"Paraugs\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Funkcionalitāte\",\n" +
" \"Fīča\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Kad \"\n" +
" ],\n" +
" \"name\": \"Latvian\",\n" +
" \"native\": \"latviešu\",\n" +
" \"scenario\": [\n" +
" \"Scenārijs\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Scenārijs pēc parauga\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Tad \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Ja \"\n" +
" ]\n" +
" },\n" +
" \"mk-Cyrl\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"И \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Контекст\",\n" +
" \"Содржина\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Но \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Примери\",\n" +
" \"Сценарија\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Функционалност\",\n" +
" \"Бизнис потреба\",\n" +
" \"Можност\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Дадено \",\n" +
" \"Дадена \"\n" +
" ],\n" +
" \"name\": \"Macedonian\",\n" +
" \"native\": \"Македонски\",\n" +
" \"scenario\": [\n" +
" \"Сценарио\",\n" +
" \"На пример\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Преглед на сценарија\",\n" +
" \"Скица\",\n" +
" \"Концепт\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Тогаш \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Кога \"\n" +
" ]\n" +
" },\n" +
" \"mk-Latn\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"I \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Kontekst\",\n" +
" \"Sodrzhina\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"No \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Primeri\",\n" +
" \"Scenaria\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Funkcionalnost\",\n" +
" \"Biznis potreba\",\n" +
" \"Mozhnost\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Dadeno \",\n" +
" \"Dadena \"\n" +
" ],\n" +
" \"name\": \"Macedonian (Latin)\",\n" +
" \"native\": \"Makedonski (Latinica)\",\n" +
" \"scenario\": [\n" +
" \"Scenario\",\n" +
" \"Na primer\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Pregled na scenarija\",\n" +
" \"Skica\",\n" +
" \"Koncept\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Togash \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Koga \"\n" +
" ]\n" +
" },\n" +
" \"mn\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Мөн \",\n" +
" \"Тэгээд \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Агуулга\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Гэхдээ \",\n" +
" \"Харин \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Тухайлбал\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Функц\",\n" +
" \"Функционал\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Өгөгдсөн нь \",\n" +
" \"Анх \"\n" +
" ],\n" +
" \"name\": \"Mongolian\",\n" +
" \"native\": \"монгол\",\n" +
" \"scenario\": [\n" +
" \"Сценар\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Сценарын төлөвлөгөө\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Тэгэхэд \",\n" +
" \"Үүний дараа \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Хэрэв \"\n" +
" ]\n" +
" },\n" +
" \"nl\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"En \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Achtergrond\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Maar \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Voorbeelden\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Functionaliteit\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Gegeven \",\n" +
" \"Stel \"\n" +
" ],\n" +
" \"name\": \"Dutch\",\n" +
" \"native\": \"Nederlands\",\n" +
" \"scenario\": [\n" +
" \"Scenario\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Abstract Scenario\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Dan \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Als \",\n" +
" \"Wanneer \"\n" +
" ]\n" +
" },\n" +
" \"no\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Og \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Bakgrunn\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Men \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Eksempler\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Egenskap\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Gitt \"\n" +
" ],\n" +
" \"name\": \"Norwegian\",\n" +
" \"native\": \"norsk\",\n" +
" \"scenario\": [\n" +
" \"Scenario\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Scenariomal\",\n" +
" \"Abstrakt Scenario\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Så \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Når \"\n" +
" ]\n" +
" },\n" +
" \"pa\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"ਅਤੇ \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"ਪਿਛੋਕੜ\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"ਪਰ \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"ਉਦਾਹਰਨਾਂ\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"ਖਾਸੀਅਤ\",\n" +
" \"ਮੁਹਾਂਦਰਾ\",\n" +
" \"ਨਕਸ਼ ਨੁਹਾਰ\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"ਜੇਕਰ \",\n" +
" \"ਜਿਵੇਂ ਕਿ \"\n" +
" ],\n" +
" \"name\": \"Panjabi\",\n" +
" \"native\": \"ਪੰਜਾਬੀ\",\n" +
" \"scenario\": [\n" +
" \"ਪਟਕਥਾ\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"ਪਟਕਥਾ ਢਾਂਚਾ\",\n" +
" \"ਪਟਕਥਾ ਰੂਪ ਰੇਖਾ\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"ਤਦ \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"ਜਦੋਂ \"\n" +
" ]\n" +
" },\n" +
" \"pl\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Oraz \",\n" +
" \"I \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Założenia\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Ale \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Przykłady\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Właściwość\",\n" +
" \"Funkcja\",\n" +
" \"Aspekt\",\n" +
" \"Potrzeba biznesowa\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Zakładając \",\n" +
" \"Mając \",\n" +
" \"Zakładając, że \"\n" +
" ],\n" +
" \"name\": \"Polish\",\n" +
" \"native\": \"polski\",\n" +
" \"scenario\": [\n" +
" \"Scenariusz\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Szablon scenariusza\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Wtedy \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Jeżeli \",\n" +
" \"Jeśli \",\n" +
" \"Gdy \",\n" +
" \"Kiedy \"\n" +
" ]\n" +
" },\n" +
" \"pt\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"E \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Contexto\",\n" +
" \"Cenário de Fundo\",\n" +
" \"Cenario de Fundo\",\n" +
" \"Fundo\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Mas \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Exemplos\",\n" +
" \"Cenários\",\n" +
" \"Cenarios\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Funcionalidade\",\n" +
" \"Característica\",\n" +
" \"Caracteristica\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Dado \",\n" +
" \"Dada \",\n" +
" \"Dados \",\n" +
" \"Dadas \"\n" +
" ],\n" +
" \"name\": \"Portuguese\",\n" +
" \"native\": \"português\",\n" +
" \"scenario\": [\n" +
" \"Cenário\",\n" +
" \"Cenario\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Esquema do Cenário\",\n" +
" \"Esquema do Cenario\",\n" +
" \"Delineação do Cenário\",\n" +
" \"Delineacao do Cenario\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Então \",\n" +
" \"Entao \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Quando \"\n" +
" ]\n" +
" },\n" +
" \"ro\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"Si \",\n" +
" \"Și \",\n" +
" \"Şi \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Context\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Dar \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Exemple\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Functionalitate\",\n" +
" \"Funcționalitate\",\n" +
" \"Funcţionalitate\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Date fiind \",\n" +
" \"Dat fiind \",\n" +
" \"Dati fiind \",\n" +
" \"Dați fiind \",\n" +
" \"Daţi fiind \"\n" +
" ],\n" +
" \"name\": \"Romanian\",\n" +
" \"native\": \"română\",\n" +
" \"scenario\": [\n" +
" \"Scenariu\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Structura scenariu\",\n" +
" \"Structură scenariu\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Atunci \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Cand \",\n" +
" \"Când \"\n" +
" ]\n" +
" },\n" +
" \"ru\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"И \",\n" +
" \"К тому же \",\n" +
" \"Также \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Предыстория\",\n" +
" \"Контекст\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Но \",\n" +
" \"А \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Примеры\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Функция\",\n" +
" \"Функциональность\",\n" +
" \"Функционал\",\n" +
" \"Свойство\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Допустим \",\n" +
" \"Дано \",\n" +
" \"Пусть \"\n" +
" ],\n" +
" \"name\": \"Russian\",\n" +
" \"native\": \"русский\",\n" +
" \"scenario\": [\n" +
" \"Сценарий\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Структура сценария\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"То \",\n" +
" \"Затем \",\n" +
" \"Тогда \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Если \",\n" +
" \"Когда \"\n" +
" ]\n" +
" },\n" +
" \"sk\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"A \",\n" +
" \"A tiež \",\n" +
" \"A taktiež \",\n" +
" \"A zároveň \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Pozadie\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Ale \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Príklady\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Požiadavka\",\n" +
" \"Funkcia\",\n" +
" \"Vlastnosť\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"Pokiaľ \",\n" +
" \"Za predpokladu \"\n" +
" ],\n" +
" \"name\": \"Slovak\",\n" +
" \"native\": \"Slovensky\",\n" +
" \"scenario\": [\n" +
" \"Scenár\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Náčrt Scenáru\",\n" +
" \"Náčrt Scenára\",\n" +
" \"Osnova Scenára\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Tak \",\n" +
" \"Potom \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Keď \",\n" +
" \"Ak \"\n" +
" ]\n" +
" },\n" +
" \"sl\": {\n" +
" \"and\": [\n" +
" \"In \",\n" +
" \"Ter \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Kontekst\",\n" +
" \"Osnova\",\n" +
" \"Ozadje\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"Toda \",\n" +
" \"Ampak \",\n" +
" \"Vendar \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Primeri\",\n" +
" \"Scenariji\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Funkcionalnost\",\n" +
" \"Funkcija\",\n" +
" \"Možnosti\",\n" +
" \"Moznosti\",\n" +
" \"Lastnost\",\n" +
" \"Značilnost\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"Dano \",\n" +
" \"Podano \",\n" +
" \"Zaradi \",\n" +
" \"Privzeto \"\n" +
" ],\n" +
" \"name\": \"Slovenian\",\n" +
" \"native\": \"Slovenski\",\n" +
" \"scenario\": [\n" +
" \"Scenarij\",\n" +
" \"Primer\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Struktura scenarija\",\n" +
" \"Skica\",\n" +
" \"Koncept\",\n" +
" \"Oris scenarija\",\n" +
" \"Osnutek\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"Nato \",\n" +
" \"Potem \",\n" +
" \"Takrat \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"Ko \",\n" +
" \"Ce \",\n" +
" \"Če \",\n" +
" \"Kadar \"\n" +
" ]\n" +
" },\n" +
" \"sr-Cyrl\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"И \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Контекст\",\n" +
" \"Основа\",\n" +
" \"Позадина\"\n" +
" ],\n" +
" \"but\": [\n" +
" \"* \",\n" +
" \"Али \"\n" +
" ],\n" +
" \"examples\": [\n" +
" \"Примери\",\n" +
" \"Сценарији\"\n" +
" ],\n" +
" \"feature\": [\n" +
" \"Функционалност\",\n" +
" \"Могућност\",\n" +
" \"Особина\"\n" +
" ],\n" +
" \"given\": [\n" +
" \"* \",\n" +
" \"За дато \",\n" +
" \"За дате \",\n" +
" \"За дати \"\n" +
" ],\n" +
" \"name\": \"Serbian\",\n" +
" \"native\": \"Српски\",\n" +
" \"scenario\": [\n" +
" \"Сценарио\",\n" +
" \"Пример\"\n" +
" ],\n" +
" \"scenarioOutline\": [\n" +
" \"Структура сценарија\",\n" +
" \"Скица\",\n" +
" \"Концепт\"\n" +
" ],\n" +
" \"then\": [\n" +
" \"* \",\n" +
" \"Онда \"\n" +
" ],\n" +
" \"when\": [\n" +
" \"* \",\n" +
" \"Када \",\n" +
" \"Кад \"\n" +
" ]\n" +
" },\n" +
" \"sr-Latn\": {\n" +
" \"and\": [\n" +
" \"* \",\n" +
" \"I \"\n" +
" ],\n" +
" \"background\": [\n" +
" \"Kontekst\",\n" +
" \"Osnova\",\n" +
" \"Pozadina\"\n" +
" ],\n" +
"
gitextract_xuvgahf2/ ├── .gitignore ├── CHANGELOG.md ├── LICENSE.md ├── README.md ├── build.gradle ├── gradle/ │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── greencoffee/ │ ├── build.gradle │ └── src/ │ └── main/ │ ├── AndroidManifest.xml │ └── java/ │ ├── com/ │ │ └── mauriciotogneri/ │ │ └── greencoffee/ │ │ ├── GreenCoffeeConfig.java │ │ ├── GreenCoffeeSteps.java │ │ ├── GreenCoffeeTest.java │ │ ├── Localization.java │ │ ├── Scenario.java │ │ ├── ScenarioConfig.java │ │ ├── ScreenCapture.java │ │ ├── ScreenshotProvider.java │ │ ├── StepDefinition.java │ │ ├── TestLog.java │ │ ├── TimedIdlingResource.java │ │ ├── annotations/ │ │ │ ├── And.java │ │ │ ├── But.java │ │ │ ├── Given.java │ │ │ ├── Then.java │ │ │ └── When.java │ │ ├── exceptions/ │ │ │ ├── DuplicatedStepDefinitionException.java │ │ │ ├── InvalidExampleException.java │ │ │ ├── InvalidMethodSignatureException.java │ │ │ ├── InvalidStepDefinitionException.java │ │ │ ├── NoStepsDefinedException.java │ │ │ ├── StepDefinitionNotFoundException.java │ │ │ └── StepFailureException.java │ │ └── interactions/ │ │ ├── ActionableData.java │ │ ├── ActionableObject.java │ │ ├── ActionableView.java │ │ ├── DataMatcher.java │ │ └── ObjectMatcher.java │ └── gherkin/ │ ├── AstBuilder.java │ ├── AstNode.java │ ├── Func.java │ ├── GenerateTokens.java │ ├── GherkinDialect.java │ ├── GherkinDialectProvider.java │ ├── GherkinLanguageConstants.java │ ├── GherkinLine.java │ ├── GherkinLineSpan.java │ ├── IGherkinDialectProvider.java │ ├── IGherkinLine.java │ ├── Parser.java │ ├── ParserException.java │ ├── StringUtils.java │ ├── SymbolCounter.java │ ├── Token.java │ ├── TokenFormatter.java │ ├── TokenFormatterBuilder.java │ ├── TokenMatcher.java │ ├── TokenScanner.java │ ├── ast/ │ │ ├── Background.java │ │ ├── Comment.java │ │ ├── DataTable.java │ │ ├── DocString.java │ │ ├── Examples.java │ │ ├── Feature.java │ │ ├── GherkinDocument.java │ │ ├── Location.java │ │ ├── Node.java │ │ ├── Scenario.java │ │ ├── ScenarioDefinition.java │ │ ├── ScenarioOutline.java │ │ ├── Step.java │ │ ├── TableCell.java │ │ ├── TableRow.java │ │ └── Tag.java │ ├── cli/ │ │ └── Main.java │ ├── events/ │ │ ├── AttachmentEvent.java │ │ ├── CucumberEvent.java │ │ ├── GherkinDocumentEvent.java │ │ ├── PickleEvent.java │ │ └── SourceEvent.java │ ├── pickles/ │ │ ├── Argument.java │ │ ├── Compiler.java │ │ ├── Pickle.java │ │ ├── PickleCell.java │ │ ├── PickleLocation.java │ │ ├── PickleRow.java │ │ ├── PickleStep.java │ │ ├── PickleString.java │ │ ├── PickleTable.java │ │ └── PickleTag.java │ └── stream/ │ ├── GherkinEvents.java │ ├── SourceEvents.java │ └── Stdio.java └── settings.gradle
Condensed preview — 95 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (425K chars).
[
{
"path": ".gitignore",
"chars": 82,
"preview": "*.iml\ngradle.properties\n.gradle\n/.idea\n/local.properties\n/greencoffee/build\n/build"
},
{
"path": "CHANGELOG.md",
"chars": 2475,
"preview": "# Change Log\nAll notable changes to this project are documented in this file.\n\n## [3.6.0] - 2021-02-15\n### Changed\n- Rem"
},
{
"path": "LICENSE.md",
"chars": 1072,
"preview": "MIT License\n\nCopyright (c) 2021 Mauricio Togneri\n\nPermission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "README.md",
"chars": 3928,
"preview": "[](https://github.com/mauriciotogneri/green-coffee/blob/ma"
},
{
"path": "build.gradle",
"chars": 507,
"preview": "buildscript\n{\n repositories\n {\n google()\n mavenCentral()\n maven\n {\n url 'ht"
},
{
"path": "gradle/wrapper/gradle-wrapper.properties",
"chars": 230,
"preview": "#Mon Feb 15 21:58:43 CET 2021\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
},
{
"path": "gradlew",
"chars": 4971,
"preview": "#!/usr/bin/env bash\n\n##############################################################################\n##\n## Gradle start "
},
{
"path": "gradlew.bat",
"chars": 2404,
"preview": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@r"
},
{
"path": "greencoffee/build.gradle",
"chars": 609,
"preview": "apply plugin: 'com.android.library'\n\nandroid\n{\n compileSdkVersion 30\n buildToolsVersion '30.0.3'\n\n defaultConfi"
},
{
"path": "greencoffee/src/main/AndroidManifest.xml",
"chars": 94,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest package=\"com.mauriciotogneri.greencoffee\" />\n"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/GreenCoffeeConfig.java",
"chars": 9211,
"preview": "package com.mauriciotogneri.greencoffee;\n\nimport com.mauriciotogneri.greencoffee.exceptions.InvalidExampleException;\n\nim"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/GreenCoffeeSteps.java",
"chars": 8195,
"preview": "package com.mauriciotogneri.greencoffee;\n\nimport android.support.annotation.IdRes;\nimport android.support.annotation.Str"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/GreenCoffeeTest.java",
"chars": 3396,
"preview": "package com.mauriciotogneri.greencoffee;\n\nimport com.mauriciotogneri.greencoffee.exceptions.DuplicatedStepDefinitionExce"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/Localization.java",
"chars": 3161,
"preview": "package com.mauriciotogneri.greencoffee;\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport an"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/Scenario.java",
"chars": 1202,
"preview": "package com.mauriciotogneri.greencoffee;\n\nimport java.util.Collections;\nimport java.util.List;\n\nimport gherkin.ast.Step;"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/ScenarioConfig.java",
"chars": 1342,
"preview": "package com.mauriciotogneri.greencoffee;\n\nimport java.util.Locale;\n\npublic class ScenarioConfig\n{\n private final Scen"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/ScreenCapture.java",
"chars": 2817,
"preview": "package com.mauriciotogneri.greencoffee;\n\nimport android.app.Activity;\nimport android.graphics.Bitmap;\nimport android.gr"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/ScreenshotProvider.java",
"chars": 1128,
"preview": "package com.mauriciotogneri.greencoffee;\n\nimport java.io.File;\nimport java.text.DateFormat;\nimport java.text.SimpleDateF"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/StepDefinition.java",
"chars": 4016,
"preview": "package com.mauriciotogneri.greencoffee;\n\nimport com.mauriciotogneri.greencoffee.exceptions.InvalidMethodSignatureExcept"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/TestLog.java",
"chars": 661,
"preview": "package com.mauriciotogneri.greencoffee;\n\nimport android.text.TextUtils;\n\nclass TestLog\n{\n void logScenario(Scenario "
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/TimedIdlingResource.java",
"chars": 1295,
"preview": "package com.mauriciotogneri.greencoffee;\n\nimport android.support.test.espresso.Espresso;\nimport android.support.test.esp"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/annotations/And.java",
"chars": 326,
"preview": "package com.mauriciotogneri.greencoffee.annotations;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotati"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/annotations/But.java",
"chars": 326,
"preview": "package com.mauriciotogneri.greencoffee.annotations;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotati"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/annotations/Given.java",
"chars": 328,
"preview": "package com.mauriciotogneri.greencoffee.annotations;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotati"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/annotations/Then.java",
"chars": 327,
"preview": "package com.mauriciotogneri.greencoffee.annotations;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotati"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/annotations/When.java",
"chars": 327,
"preview": "package com.mauriciotogneri.greencoffee.annotations;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotati"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/exceptions/DuplicatedStepDefinitionException.java",
"chars": 425,
"preview": "package com.mauriciotogneri.greencoffee.exceptions;\n\nimport java.lang.reflect.Method;\n\npublic class DuplicatedStepDefini"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/exceptions/InvalidExampleException.java",
"chars": 270,
"preview": "package com.mauriciotogneri.greencoffee.exceptions;\n\npublic class InvalidExampleException extends RuntimeException\n{\n "
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/exceptions/InvalidMethodSignatureException.java",
"chars": 472,
"preview": "package com.mauriciotogneri.greencoffee.exceptions;\n\nimport java.lang.reflect.Method;\n\npublic class InvalidMethodSignatu"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/exceptions/InvalidStepDefinitionException.java",
"chars": 405,
"preview": "package com.mauriciotogneri.greencoffee.exceptions;\n\nimport java.lang.reflect.Method;\n\npublic class InvalidStepDefinitio"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/exceptions/NoStepsDefinedException.java",
"chars": 218,
"preview": "package com.mauriciotogneri.greencoffee.exceptions;\n\npublic class NoStepsDefinedException extends RuntimeException\n{\n "
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/exceptions/StepDefinitionNotFoundException.java",
"chars": 298,
"preview": "package com.mauriciotogneri.greencoffee.exceptions;\n\npublic class StepDefinitionNotFoundException extends RuntimeExcepti"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/exceptions/StepFailureException.java",
"chars": 460,
"preview": "package com.mauriciotogneri.greencoffee.exceptions;\n\nimport java.lang.reflect.Method;\n\npublic class StepFailureException"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/interactions/ActionableData.java",
"chars": 1724,
"preview": "package com.mauriciotogneri.greencoffee.interactions;\n\nimport android.support.test.espresso.DataInteraction;\nimport andr"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/interactions/ActionableObject.java",
"chars": 7749,
"preview": "package com.mauriciotogneri.greencoffee.interactions;\n\nimport android.support.test.espresso.ViewAction;\nimport android.s"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/interactions/ActionableView.java",
"chars": 1724,
"preview": "package com.mauriciotogneri.greencoffee.interactions;\n\nimport android.support.test.espresso.UiController;\nimport android"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/interactions/DataMatcher.java",
"chars": 1726,
"preview": "package com.mauriciotogneri.greencoffee.interactions;\n\nimport android.support.annotation.IdRes;\nimport android.support.t"
},
{
"path": "greencoffee/src/main/java/com/mauriciotogneri/greencoffee/interactions/ObjectMatcher.java",
"chars": 542,
"preview": "package com.mauriciotogneri.greencoffee.interactions;\n\nimport org.hamcrest.BaseMatcher;\nimport org.hamcrest.Description;"
},
{
"path": "greencoffee/src/main/java/gherkin/AstBuilder.java",
"chars": 10064,
"preview": "package gherkin;\n\nimport gherkin.ast.Background;\nimport gherkin.ast.Comment;\nimport gherkin.ast.DataTable;\nimport gherki"
},
{
"path": "greencoffee/src/main/java/gherkin/AstNode.java",
"chars": 1426,
"preview": "package gherkin;\n\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.L"
},
{
"path": "greencoffee/src/main/java/gherkin/Func.java",
"chars": 61,
"preview": "package gherkin;\n\npublic interface Func<V> {\n V call();\n}\n"
},
{
"path": "greencoffee/src/main/java/gherkin/GenerateTokens.java",
"chars": 812,
"preview": "package gherkin;\n\nimport gherkin.stream.Stdio;\n\nimport java.io.FileInputStream;\nimport java.io.FileNotFoundException;\nim"
},
{
"path": "greencoffee/src/main/java/gherkin/GherkinDialect.java",
"chars": 1272,
"preview": "package gherkin;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Map;\n\npublic class GherkinDialect "
},
{
"path": "greencoffee/src/main/java/gherkin/GherkinDialectProvider.java",
"chars": 133984,
"preview": "package gherkin;\n\nimport java.util.List;\nimport java.util.Map;\n\nimport gherkin.ast.Location;\nimport gherkin.deps.com.goo"
},
{
"path": "greencoffee/src/main/java/gherkin/GherkinLanguageConstants.java",
"chars": 302,
"preview": "package gherkin;\n\npublic interface GherkinLanguageConstants {\n String TAG_PREFIX = \"@\";\n String COMMENT_PREFIX = \""
},
{
"path": "greencoffee/src/main/java/gherkin/GherkinLine.java",
"chars": 3835,
"preview": "package gherkin;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Scanner;\n\nimport static gherkin.St"
},
{
"path": "greencoffee/src/main/java/gherkin/GherkinLineSpan.java",
"chars": 716,
"preview": "package gherkin;\n\npublic class GherkinLineSpan {\n // One-based line position\n public final int column;\n\n // tex"
},
{
"path": "greencoffee/src/main/java/gherkin/IGherkinDialectProvider.java",
"chars": 201,
"preview": "package gherkin;\n\nimport gherkin.ast.Location;\n\npublic interface IGherkinDialectProvider {\n GherkinDialect getDefault"
},
{
"path": "greencoffee/src/main/java/gherkin/IGherkinLine.java",
"chars": 402,
"preview": "package gherkin;\n\nimport java.util.List;\n\npublic interface IGherkinLine {\n Integer indent();\n\n void detach();\n\n "
},
{
"path": "greencoffee/src/main/java/gherkin/Parser.java",
"chars": 112693,
"preview": "// This code was generated by Berp (http://https://github.com/gasparnagy/berp/).\n//\n// Changes to this file ma"
},
{
"path": "greencoffee/src/main/java/gherkin/ParserException.java",
"chars": 3780,
"preview": "package gherkin;\n\nimport gherkin.ast.Location;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class Parse"
},
{
"path": "greencoffee/src/main/java/gherkin/StringUtils.java",
"chars": 1048,
"preview": "package gherkin;\n\nimport java.util.List;\n\npublic class StringUtils {\n public static String join(String separator, Lis"
},
{
"path": "greencoffee/src/main/java/gherkin/SymbolCounter.java",
"chars": 215,
"preview": "package gherkin;\n\n// http://rosettacode.org/wiki/String_length#Java\npublic class SymbolCounter {\n public static int c"
},
{
"path": "greencoffee/src/main/java/gherkin/Token.java",
"chars": 904,
"preview": "package gherkin;\n\nimport gherkin.ast.Location;\n\nimport java.util.List;\n\npublic class Token {\n public final IGherkinLi"
},
{
"path": "greencoffee/src/main/java/gherkin/TokenFormatter.java",
"chars": 930,
"preview": "package gherkin;\n\npublic class TokenFormatter {\n private static final StringUtils.ToString<GherkinLineSpan> SPAN_TO_S"
},
{
"path": "greencoffee/src/main/java/gherkin/TokenFormatterBuilder.java",
"chars": 659,
"preview": "package gherkin;\n\npublic class TokenFormatterBuilder implements Parser.Builder<String> {\n private final TokenFormatte"
},
{
"path": "greencoffee/src/main/java/gherkin/TokenMatcher.java",
"chars": 7101,
"preview": "package gherkin;\n\nimport gherkin.ast.Location;\n\nimport java.util.List;\nimport java.util.regex.Matcher;\nimport java.util."
},
{
"path": "greencoffee/src/main/java/gherkin/TokenScanner.java",
"chars": 1266,
"preview": "package gherkin;\n\nimport gherkin.ast.Location;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.i"
},
{
"path": "greencoffee/src/main/java/gherkin/ast/Background.java",
"chars": 277,
"preview": "package gherkin.ast;\n\nimport java.util.List;\n\npublic class Background extends ScenarioDefinition {\n public Background"
},
{
"path": "greencoffee/src/main/java/gherkin/ast/Comment.java",
"chars": 260,
"preview": "package gherkin.ast;\n\npublic class Comment extends Node {\n private final String text;\n\n public Comment(Location lo"
},
{
"path": "greencoffee/src/main/java/gherkin/ast/DataTable.java",
"chars": 370,
"preview": "package gherkin.ast;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class DataTable extends Node {\n pr"
},
{
"path": "greencoffee/src/main/java/gherkin/ast/DocString.java",
"chars": 452,
"preview": "package gherkin.ast;\n\npublic class DocString extends Node {\n private final String contentType;\n private final Stri"
},
{
"path": "greencoffee/src/main/java/gherkin/ast/Examples.java",
"chars": 1214,
"preview": "package gherkin.ast;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class Examples extends Node {\n pri"
},
{
"path": "greencoffee/src/main/java/gherkin/ast/Feature.java",
"chars": 1270,
"preview": "package gherkin.ast;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class Feature extends Node {\n priv"
},
{
"path": "greencoffee/src/main/java/gherkin/ast/GherkinDocument.java",
"chars": 556,
"preview": "package gherkin.ast;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class GherkinDocument extends Node {\n"
},
{
"path": "greencoffee/src/main/java/gherkin/ast/Location.java",
"chars": 327,
"preview": "package gherkin.ast;\n\npublic class Location {\n private final int line;\n private final int column;\n\n public Loca"
},
{
"path": "greencoffee/src/main/java/gherkin/ast/Node.java",
"chars": 299,
"preview": "package gherkin.ast;\n\npublic abstract class Node {\n private final String type = getClass().getSimpleName();\n priva"
},
{
"path": "greencoffee/src/main/java/gherkin/ast/Scenario.java",
"chars": 471,
"preview": "package gherkin.ast;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class Scenario extends ScenarioDefini"
},
{
"path": "greencoffee/src/main/java/gherkin/ast/ScenarioDefinition.java",
"chars": 837,
"preview": "package gherkin.ast;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic abstract class ScenarioDefinition ext"
},
{
"path": "greencoffee/src/main/java/gherkin/ast/ScenarioOutline.java",
"chars": 691,
"preview": "package gherkin.ast;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class ScenarioOutline extends Scenari"
},
{
"path": "greencoffee/src/main/java/gherkin/ast/Step.java",
"chars": 547,
"preview": "package gherkin.ast;\n\npublic class Step extends Node {\n private final String keyword;\n private final String text;\n"
},
{
"path": "greencoffee/src/main/java/gherkin/ast/TableCell.java",
"chars": 271,
"preview": "package gherkin.ast;\n\npublic class TableCell extends Node {\n private final String value;\n\n public TableCell(Locati"
},
{
"path": "greencoffee/src/main/java/gherkin/ast/TableRow.java",
"chars": 380,
"preview": "package gherkin.ast;\n\nimport java.util.Collections;\nimport java.util.List;\n\npublic class TableRow extends Node {\n pri"
},
{
"path": "greencoffee/src/main/java/gherkin/ast/Tag.java",
"chars": 253,
"preview": "package gherkin.ast;\n\npublic class Tag extends Node {\n private final String name;\n\n public Tag(Location location, "
},
{
"path": "greencoffee/src/main/java/gherkin/cli/Main.java",
"chars": 1739,
"preview": "package gherkin.cli;\n\nimport gherkin.stream.Stdio;\nimport gherkin.deps.com.google.gson.Gson;\nimport gherkin.deps.com.goo"
},
{
"path": "greencoffee/src/main/java/gherkin/events/AttachmentEvent.java",
"chars": 998,
"preview": "package gherkin.events;\n\npublic class AttachmentEvent implements CucumberEvent {\n private final String type = \"attach"
},
{
"path": "greencoffee/src/main/java/gherkin/events/CucumberEvent.java",
"chars": 60,
"preview": "package gherkin.events;\n\npublic interface CucumberEvent {\n}\n"
},
{
"path": "greencoffee/src/main/java/gherkin/events/GherkinDocumentEvent.java",
"chars": 386,
"preview": "package gherkin.events;\n\nimport gherkin.ast.GherkinDocument;\n\npublic class GherkinDocumentEvent implements CucumberEvent"
},
{
"path": "greencoffee/src/main/java/gherkin/events/PickleEvent.java",
"chars": 327,
"preview": "package gherkin.events;\n\nimport gherkin.pickles.Pickle;\n\npublic class PickleEvent implements CucumberEvent {\n private"
},
{
"path": "greencoffee/src/main/java/gherkin/events/SourceEvent.java",
"chars": 491,
"preview": "package gherkin.events;\n\npublic class SourceEvent implements CucumberEvent {\n private final String type = \"source\";\n "
},
{
"path": "greencoffee/src/main/java/gherkin/pickles/Argument.java",
"chars": 90,
"preview": "package gherkin.pickles;\n\npublic interface Argument {\n PickleLocation getLocation();\n}\n"
},
{
"path": "greencoffee/src/main/java/gherkin/pickles/Compiler.java",
"chars": 8238,
"preview": "package gherkin.pickles;\n\nimport gherkin.SymbolCounter;\nimport gherkin.ast.Background;\nimport gherkin.ast.DataTable;\nimp"
},
{
"path": "greencoffee/src/main/java/gherkin/pickles/Pickle.java",
"chars": 839,
"preview": "package gherkin.pickles;\n\nimport java.util.List;\n\nimport static java.util.Collections.unmodifiableList;\n\npublic class Pi"
},
{
"path": "greencoffee/src/main/java/gherkin/pickles/PickleCell.java",
"chars": 395,
"preview": "package gherkin.pickles;\n\npublic class PickleCell {\n private final PickleLocation location;\n private final String "
},
{
"path": "greencoffee/src/main/java/gherkin/pickles/PickleLocation.java",
"chars": 343,
"preview": "package gherkin.pickles;\n\npublic class PickleLocation {\n private final int line;\n private final int column;\n\n p"
},
{
"path": "greencoffee/src/main/java/gherkin/pickles/PickleRow.java",
"chars": 345,
"preview": "package gherkin.pickles;\n\nimport java.util.List;\n\nimport static java.util.Collections.unmodifiableList;\n\npublic class Pi"
},
{
"path": "greencoffee/src/main/java/gherkin/pickles/PickleStep.java",
"chars": 709,
"preview": "package gherkin.pickles;\n\nimport java.util.List;\n\nimport static java.util.Collections.unmodifiableList;\n\npublic class Pi"
},
{
"path": "greencoffee/src/main/java/gherkin/pickles/PickleString.java",
"chars": 445,
"preview": "package gherkin.pickles;\n\npublic class PickleString implements Argument {\n private final PickleLocation location;\n "
},
{
"path": "greencoffee/src/main/java/gherkin/pickles/PickleTable.java",
"chars": 483,
"preview": "package gherkin.pickles;\n\nimport java.util.List;\n\nimport static java.util.Collections.unmodifiableList;\n\npublic class Pi"
},
{
"path": "greencoffee/src/main/java/gherkin/pickles/PickleTag.java",
"chars": 314,
"preview": "package gherkin.pickles;\n\npublic class PickleTag {\n private final PickleLocation location;\n private final String n"
},
{
"path": "greencoffee/src/main/java/gherkin/stream/GherkinEvents.java",
"chars": 2631,
"preview": "package gherkin.stream;\n\nimport gherkin.AstBuilder;\nimport gherkin.Parser;\nimport gherkin.ParserException;\nimport gherki"
},
{
"path": "greencoffee/src/main/java/gherkin/stream/SourceEvents.java",
"chars": 1677,
"preview": "package gherkin.stream;\n\nimport gherkin.events.SourceEvent;\n\nimport java.io.FileInputStream;\nimport java.io.IOException;"
},
{
"path": "greencoffee/src/main/java/gherkin/stream/Stdio.java",
"chars": 434,
"preview": "package gherkin.stream;\n\nimport java.io.OutputStreamWriter;\nimport java.io.PrintWriter;\nimport java.nio.charset.Charset;"
},
{
"path": "settings.gradle",
"chars": 22,
"preview": "include ':greencoffee'"
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the mauriciotogneri/green-coffee GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 95 files (372.6 KB), approximately 88.6k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.