├── .gitignore ├── build.gradle.kts ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── samples ├── .DS_Store ├── allure-migration │ ├── build.gradle.kts │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── index.html │ ├── settings.gradle.kts │ └── src │ │ ├── main │ │ └── java │ │ │ └── io │ │ │ └── eroshenkoam │ │ │ └── allure │ │ │ └── BasicSteps.java │ │ └── test │ │ └── java │ │ └── io │ │ └── eroshenkoam │ │ └── allure │ │ └── AddFavoritesAfterNoteTest.java ├── jira-import │ ├── build.gradle.kts │ ├── gradle │ │ └── wrapper │ │ │ ├── gradle-wrapper.jar │ │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── settings.gradle.kts │ └── src │ │ └── test │ │ └── java │ │ └── io │ │ └── eroshenkoam │ │ └── autotests │ │ └── AddFavoritesAfterNoteTest.java └── testcase-export │ ├── build.gradle.kts │ ├── gradle │ └── wrapper │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── index.html │ ├── settings.gradle.kts │ └── src │ ├── main │ └── java │ │ └── io │ │ └── eroshenkoam │ │ └── autotests │ │ └── BasicSteps.java │ └── test │ └── java │ └── io │ └── eroshenkoam │ └── autotests │ └── AddFavoritesExportTest.java ├── settings.gradle.kts └── src └── main ├── java └── io │ └── eroshenkoam │ └── idea │ ├── AllureMigrationAction.java │ ├── Annotations.java │ ├── AuthenticationAction.java │ ├── BaseExportAction.java │ ├── JiraKeyImportAction.java │ ├── JiraLabelsImportAction.java │ ├── JiraTestCaseExportAction.java │ ├── PluginException.java │ ├── TestCaseExportAction.java │ ├── export │ ├── TestCase.java │ └── TestStep.java │ ├── jira │ ├── JiraClient.java │ ├── JiraClientBuilder.java │ ├── JiraFilter.java │ ├── JiraIssue.java │ ├── JiraIssueFields.java │ ├── JiraIssuetype.java │ ├── JiraProject.java │ └── JiraUser.java │ ├── retrofit │ ├── BasicAuthInterceptor.java │ └── DefaultCallAdapterFactory.java │ ├── ui │ ├── AuthenticationForm.form │ └── AuthenticationForm.java │ └── util │ ├── FreemarkerUtils.java │ └── PsiUtils.java └── resources ├── META-INF └── plugin.xml └── testcases.ftl /.gitignore: -------------------------------------------------------------------------------- 1 | # Idea 2 | .idea 3 | *.iml 4 | out 5 | 6 | # Gradle 7 | .gradle 8 | build 9 | 10 | -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.intellij.IntelliJPluginExtension 2 | import org.jetbrains.intellij.tasks.PatchPluginXmlTask 3 | 4 | buildscript { 5 | repositories { 6 | maven(url = "https://plugins.gradle.org/m2/") 7 | } 8 | 9 | dependencies { 10 | classpath("gradle.plugin.org.jetbrains.intellij.plugins:gradle-intellij-plugin:0.3.7") 11 | } 12 | } 13 | 14 | description = "Idea Plugin Sample" 15 | 16 | tasks.existing(Wrapper::class) { 17 | gradleVersion = "4.10.2" 18 | distributionType = Wrapper.DistributionType.ALL 19 | } 20 | 21 | plugins { 22 | id("java") 23 | id("org.jetbrains.intellij") version ("0.3.7") 24 | } 25 | 26 | tasks.withType(type = JavaCompile::class) { 27 | sourceCompatibility = "1.8" 28 | targetCompatibility = "1.8" 29 | options.encoding = "UTF-8" 30 | } 31 | 32 | repositories { 33 | mavenCentral() 34 | mavenLocal() 35 | } 36 | 37 | dependencies { 38 | compileOnly("org.projectlombok:lombok:1.18.4") 39 | 40 | compile("org.freemarker:freemarker:2.3.28") 41 | 42 | compile("commons-io:commons-io:2.6") 43 | compile("com.squareup.retrofit2:retrofit:2.4.0") 44 | compile("com.squareup.retrofit2:converter-jackson:2.4.0") 45 | compile("com.squareup.okhttp3:logging-interceptor:3.12.1") 46 | } 47 | 48 | configure { 49 | version = "2018.2.5" 50 | } 51 | 52 | tasks.withType(PatchPluginXmlTask::class) { 53 | changeNotes("Add change notes here.
most HTML tags may be used") 54 | } 55 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | version=1.0-SNAPSHOT 2 | org.gradle.daemon=false -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eroshenkoam/idea-plugin-sample/58a163b4b9c8dcdcead252de3c2a3edc5ccbc8c7/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /samples/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eroshenkoam/idea-plugin-sample/58a163b4b9c8dcdcead252de3c2a3edc5ccbc8c7/samples/.DS_Store -------------------------------------------------------------------------------- /samples/allure-migration/build.gradle.kts: -------------------------------------------------------------------------------- 1 | description = "Allure Migration Sample" 2 | 3 | tasks.existing(Wrapper::class) { 4 | gradleVersion = "4.10.2" 5 | distributionType = Wrapper.DistributionType.ALL 6 | } 7 | 8 | plugins { 9 | java 10 | } 11 | 12 | tasks.withType(type = JavaCompile::class) { 13 | sourceCompatibility = "1.8" 14 | targetCompatibility = "1.8" 15 | options.encoding = "UTF-8" 16 | } 17 | 18 | repositories { 19 | mavenCentral(); 20 | mavenLocal() 21 | } 22 | 23 | dependencies { 24 | compile("ru.yandex.qatools.allure:allure-junit-adaptor:1.4.23") 25 | compile("io.qameta.allure:allure-junit4:2.8.1") 26 | 27 | compile("org.junit.jupiter:junit-jupiter-api:5.3.1") 28 | testCompile("org.junit.jupiter:junit-jupiter-engine:5.3.1") 29 | } 30 | -------------------------------------------------------------------------------- /samples/allure-migration/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eroshenkoam/idea-plugin-sample/58a163b4b9c8dcdcead252de3c2a3edc5ccbc8c7/samples/allure-migration/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /samples/allure-migration/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /samples/allure-migration/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /samples/allure-migration/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /samples/allure-migration/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Test Cases 5 | 7 | 8 | 9 |
10 |
11 |

Test Cases

12 |
13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /samples/allure-migration/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "allure-migration" 2 | -------------------------------------------------------------------------------- /samples/allure-migration/src/main/java/io/eroshenkoam/allure/BasicSteps.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.allure; 2 | 3 | import io.qameta.allure.Step; 4 | 5 | /** 6 | * @author eroshenkoam (Artem Eroshenko). 7 | */ 8 | public class BasicSteps { 9 | 10 | @Step("Открываем главную страницу") 11 | public void openMainPage() { 12 | 13 | } 14 | 15 | @Step("Открываем страницу машины марки {mark}") 16 | public void openAutoCardPage(String mark) { 17 | 18 | } 19 | 20 | @Step("Добавляем заметку {text} к машине") 21 | public void addNotesToAutoCard(String text) { 22 | 23 | } 24 | 25 | @Step("Открываем страницу избранного") 26 | public void openFavoritesPage() { 27 | 28 | } 29 | 30 | @Step("Проверяем что список избранного сожержит марку {mark}") 31 | public void checkFavoritesListContains(String mark) { 32 | 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /samples/allure-migration/src/test/java/io/eroshenkoam/allure/AddFavoritesAfterNoteTest.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.allure; 2 | 3 | import io.qameta.allure.Feature; 4 | import io.qameta.allure.Features; 5 | import io.qameta.allure.Stories; 6 | import io.qameta.allure.Story; 7 | import io.qameta.allure.TmsLink; 8 | import org.junit.jupiter.api.DisplayName; 9 | import org.junit.jupiter.api.Test; 10 | 11 | /** 12 | * @author eroshenkoam (Artem Eroshenko). 13 | */ 14 | public class AddFavoritesAfterNoteTest { 15 | 16 | private BasicSteps steps; 17 | 18 | @Test 19 | @TmsLink("AE-5") 20 | @DisplayName("") 21 | @Features({@Feature("First Feature"), @Feature("Second Feature")}) 22 | @Stories({@Story("First Story"), @Story("Second Story")}) 23 | public void shouldAddToFavoriteAfterNodeTest() { 24 | steps.openMainPage(); 25 | steps.openAutoCardPage("Volvo XC90"); 26 | steps.addNotesToAutoCard("в хорошем состоянии"); 27 | steps.openFavoritesPage(); 28 | steps.checkFavoritesListContains("Volvo XC90"); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /samples/jira-import/build.gradle.kts: -------------------------------------------------------------------------------- 1 | description = "Jira Import Sample" 2 | 3 | tasks.existing(Wrapper::class) { 4 | gradleVersion = "4.10.2" 5 | distributionType = Wrapper.DistributionType.ALL 6 | } 7 | 8 | plugins { 9 | java 10 | } 11 | 12 | tasks.withType(type = JavaCompile::class) { 13 | sourceCompatibility = "1.8" 14 | targetCompatibility = "1.8" 15 | options.encoding = "UTF-8" 16 | } 17 | 18 | repositories { 19 | mavenCentral(); 20 | mavenLocal() 21 | } 22 | 23 | dependencies { 24 | compile("io.qameta.allure:allure-junit4:2.8.1") 25 | 26 | compile("org.junit.jupiter:junit-jupiter-api:5.3.1") 27 | testCompile("org.junit.jupiter:junit-jupiter-engine:5.3.1") 28 | } 29 | -------------------------------------------------------------------------------- /samples/jira-import/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eroshenkoam/idea-plugin-sample/58a163b4b9c8dcdcead252de3c2a3edc5ccbc8c7/samples/jira-import/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /samples/jira-import/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /samples/jira-import/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /samples/jira-import/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /samples/jira-import/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "jira-import" 2 | -------------------------------------------------------------------------------- /samples/jira-import/src/test/java/io/eroshenkoam/autotests/AddFavoritesAfterNoteTest.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.autotests; 2 | 3 | import io.qameta.allure.TmsLink; 4 | import org.junit.jupiter.api.DisplayName; 5 | import org.junit.jupiter.api.Tag; 6 | import org.junit.jupiter.api.Tags; 7 | import org.junit.jupiter.api.Test; 8 | 9 | public class AddFavoritesAfterNoteTest { 10 | 11 | @Test 12 | @TmsLink("AE-5") 13 | @Tags({@Tag("favorites"), @Tag("regress")}) 14 | @DisplayName("Добавление в избранное после создания заметки") 15 | public void shouldAddToFavoriteAfterNodeTest() { 16 | } 17 | 18 | @Test 19 | @TmsLink("AE-4") 20 | @Tags({@Tag("critical"), @Tag("favorites"), @Tag("regress")}) 21 | @DisplayName("Удаление из избранного после удаления заметки") 22 | public void shouldDeleteToFavoriteAfterNodeTest() { 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /samples/testcase-export/build.gradle.kts: -------------------------------------------------------------------------------- 1 | description = "Jira Import Sample" 2 | 3 | tasks.existing(Wrapper::class) { 4 | gradleVersion = "4.10.2" 5 | distributionType = Wrapper.DistributionType.ALL 6 | } 7 | 8 | plugins { 9 | java 10 | } 11 | 12 | tasks.withType(type = JavaCompile::class) { 13 | sourceCompatibility = "1.8" 14 | targetCompatibility = "1.8" 15 | options.encoding = "UTF-8" 16 | } 17 | 18 | repositories { 19 | mavenCentral(); 20 | mavenLocal() 21 | } 22 | 23 | dependencies { 24 | compile("io.qameta.allure:allure-junit4:2.8.1") 25 | 26 | compile("org.junit.jupiter:junit-jupiter-api:5.3.1") 27 | testCompile("org.junit.jupiter:junit-jupiter-engine:5.3.1") 28 | } 29 | -------------------------------------------------------------------------------- /samples/testcase-export/gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eroshenkoam/idea-plugin-sample/58a163b4b9c8dcdcead252de3c2a3edc5ccbc8c7/samples/testcase-export/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /samples/testcase-export/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /samples/testcase-export/gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /samples/testcase-export/gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /samples/testcase-export/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Test Cases 5 | 7 | 8 | 9 |
10 |
11 |

Test Cases

12 |

AE-5 Добавление в избранное после создания заметки

13 |
14 |
Features
15 |
"Favorites", "Notes"
16 |
Stories
17 |
"Add to favorites after adding note"
18 |
19 |

Scenario

20 |
    21 |
  1. Открываем главную страницу
  2. 22 |
  3. Открываем страницу машины марки {mark}
  4. 23 |
  5. Добавляем заметку {text} к машине
  6. 24 |
  7. Открываем страницу избранного
  8. 25 |
  9. Проверяем что марка {mark} находится в избранных
  10. 26 |
27 |
28 |
29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /samples/testcase-export/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "testcase-export" 2 | -------------------------------------------------------------------------------- /samples/testcase-export/src/main/java/io/eroshenkoam/autotests/BasicSteps.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.autotests; 2 | 3 | import io.qameta.allure.Step; 4 | 5 | public class BasicSteps { 6 | 7 | @Step("Открываем главную страницу") 8 | public void openMainPage() { 9 | } 10 | 11 | @Step("Открываем страницу машины марки {mark}") 12 | public void openAutoCardPage(String mark) { 13 | } 14 | 15 | @Step("Добавляем заметку {text} к машине") 16 | public void addNotesToAutoCard(String text) { 17 | } 18 | 19 | @Step("Открываем страницу избранного") 20 | public void openFavoritesPage() { 21 | } 22 | 23 | @Step("Проверяем что марка {mark} находится в избранных") 24 | public void checkFavoritesListContains(String mark) { 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /samples/testcase-export/src/test/java/io/eroshenkoam/autotests/AddFavoritesExportTest.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.autotests; 2 | 3 | import io.qameta.allure.*; 4 | import org.junit.jupiter.api.DisplayName; 5 | import org.junit.jupiter.api.Test; 6 | 7 | public class AddFavoritesExportTest { 8 | 9 | private BasicSteps steps; 10 | 11 | @Test 12 | @TmsLink("NEW-2") 13 | @Features({@Feature("Favorites"), @Feature("Notes")}) 14 | @Stories({@Story("Add to favorites after adding note")}) 15 | @DisplayName("Добавление в избранное после создания заметки") 16 | public void shouldAddToFavoriteAfterNodeTest() { 17 | steps.openMainPage(); 18 | steps.openAutoCardPage("Volvo XC90"); 19 | steps.addNotesToAutoCard("в хорошем состоянии"); 20 | steps.openFavoritesPage(); 21 | steps.checkFavoritesListContains("Volvo XC90"); 22 | } 23 | 24 | @Test 25 | @TmsLink("NEW-3") 26 | @Features({@Feature("Favorites"), @Feature("Notes")}) 27 | @Stories({@Story("Delete from favorites after deleting note")}) 28 | @DisplayName("Удаление из избранного после удаления заметки") 29 | public void shouldDeleteToFavoriteAfterNodeTest() { 30 | steps.openMainPage(); 31 | steps.openAutoCardPage("Volvo XC90"); 32 | steps.addNotesToAutoCard("в хорошем состоянии"); 33 | steps.openFavoritesPage(); 34 | steps.checkFavoritesListContains("Volvo XC90"); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "idea-plugin-sample" 2 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/AllureMigrationAction.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea; 2 | 3 | import com.intellij.codeInsight.AnnotationUtil; 4 | import com.intellij.lang.jvm.JvmNamedElement; 5 | import com.intellij.openapi.actionSystem.AnAction; 6 | import com.intellij.openapi.actionSystem.AnActionEvent; 7 | import com.intellij.openapi.actionSystem.PlatformDataKeys; 8 | import com.intellij.openapi.application.ApplicationManager; 9 | import com.intellij.openapi.command.CommandProcessor; 10 | import com.intellij.openapi.project.Project; 11 | import com.intellij.psi.PsiAnnotation; 12 | import com.intellij.psi.PsiAnnotationMemberValue; 13 | import com.intellij.psi.PsiArrayInitializerMemberValue; 14 | import com.intellij.psi.PsiClass; 15 | import com.intellij.psi.PsiElement; 16 | import com.intellij.psi.PsiMethod; 17 | import io.eroshenkoam.idea.util.PsiUtils; 18 | 19 | import java.util.Arrays; 20 | import java.util.List; 21 | import java.util.Optional; 22 | import java.util.stream.Collectors; 23 | 24 | import static io.eroshenkoam.idea.Annotations.ALLURE1_FEATURES_ANNOTATION; 25 | import static io.eroshenkoam.idea.Annotations.ALLURE1_STEP_ANNOTATION; 26 | import static io.eroshenkoam.idea.Annotations.ALLURE1_STORIES_ANNOTATION; 27 | import static io.eroshenkoam.idea.Annotations.ALLURE1_TESTCASEID_ANNOTATION; 28 | import static io.eroshenkoam.idea.Annotations.ALLURE2_FEATURES_ANNOTATION; 29 | import static io.eroshenkoam.idea.Annotations.ALLURE2_FEATURE_ANNOTATION; 30 | import static io.eroshenkoam.idea.Annotations.ALLURE2_STEP_ANNOTATION; 31 | import static io.eroshenkoam.idea.Annotations.ALLURE2_STORIES_ANNOTATION; 32 | import static io.eroshenkoam.idea.Annotations.ALLURE2_STORY_ANNOTATION; 33 | import static io.eroshenkoam.idea.Annotations.ALLURE2_TMS_LINK_ANNOTATION; 34 | import static io.eroshenkoam.idea.Annotations.JUNIT_TEST_ANNOTATION; 35 | import static io.eroshenkoam.idea.util.PsiUtils.createAnnotation; 36 | 37 | /** 38 | * @author eroshenkoam (Artem Eroshenko). 39 | */ 40 | public class AllureMigrationAction extends AnAction { 41 | 42 | @Override 43 | public void actionPerformed(AnActionEvent event) { 44 | final PsiElement element = event.getData(PlatformDataKeys.PSI_ELEMENT); 45 | if (element instanceof PsiClass) { 46 | Arrays.stream(((PsiClass) element).getMethods()) 47 | .filter(m -> m.hasAnnotation(JUNIT_TEST_ANNOTATION)) 48 | .forEach(this::migrateTestAnnotations); 49 | 50 | Arrays.stream(((PsiClass) element).getMethods()) 51 | .filter(m -> m.hasAnnotation(ALLURE1_STEP_ANNOTATION)) 52 | .forEach(this::migrateStepAnnotation); 53 | } 54 | } 55 | 56 | private void migrateTestAnnotations(final PsiMethod testMethod) { 57 | migrateTestCaseId(testMethod); 58 | migrateFeaturesAnnotation(testMethod); 59 | migrateStoriesAnnotation(testMethod); 60 | migrateStepAnnotation(testMethod); 61 | } 62 | 63 | private void migrateTestCaseId(final PsiMethod testMethod) { 64 | Optional.ofNullable(testMethod.getAnnotation(ALLURE1_TESTCASEID_ANNOTATION)).ifPresent(testCaseId -> { 65 | final String id = testCaseId.findAttributeValue("value").getText(); 66 | 67 | final String tmsLinkText = String.format("@%s(%s)", ALLURE2_TMS_LINK_ANNOTATION, id); 68 | final PsiAnnotation tmsLink = createAnnotation(tmsLinkText, testMethod); 69 | final Project project = testMethod.getProject(); 70 | CommandProcessor.getInstance().executeCommand(project, () -> ApplicationManager.getApplication().runWriteAction(() -> { 71 | PsiUtils.addImport(testMethod.getContainingFile(), ALLURE2_TMS_LINK_ANNOTATION); 72 | 73 | testMethod.getModifierList().addAfter(tmsLink, testCaseId); 74 | testCaseId.delete(); 75 | 76 | PsiUtils.optimizeImports(testMethod.getContainingFile()); 77 | }), "Migrate Allure TestCaseId", null); 78 | }); 79 | } 80 | 81 | private void migrateFeaturesAnnotation(final PsiMethod testMethod) { 82 | Optional.ofNullable(testMethod.getAnnotation(ALLURE1_FEATURES_ANNOTATION)).ifPresent(oldFeaturesAnnotation -> { 83 | final PsiArrayInitializerMemberValue value = (PsiArrayInitializerMemberValue) oldFeaturesAnnotation 84 | .findDeclaredAttributeValue("value"); 85 | 86 | final List features = Arrays.stream(value.getInitializers()) 87 | .map(PsiAnnotationMemberValue::getText) 88 | .collect(Collectors.toList()); 89 | 90 | final String featuresText = getFeaturesAnnotationText(features); 91 | final PsiAnnotation featureAnnotation = createAnnotation(featuresText, testMethod); 92 | 93 | final Project project = testMethod.getProject(); 94 | CommandProcessor.getInstance().executeCommand(project, () -> ApplicationManager.getApplication().runWriteAction(() -> { 95 | PsiUtils.addImport(testMethod.getContainingFile(), ALLURE2_FEATURE_ANNOTATION); 96 | PsiUtils.addImport(testMethod.getContainingFile(), ALLURE2_FEATURES_ANNOTATION); 97 | 98 | testMethod.getModifierList().addAfter(featureAnnotation, oldFeaturesAnnotation); 99 | oldFeaturesAnnotation.delete(); 100 | 101 | PsiUtils.optimizeImports(testMethod.getContainingFile()); 102 | }), "Migrate Allure Features", null); 103 | }); 104 | } 105 | 106 | private void migrateStoriesAnnotation(final PsiMethod testMethod) { 107 | Optional.ofNullable(testMethod.getAnnotation(ALLURE1_STORIES_ANNOTATION)).ifPresent(oldStoriesAnnotation -> { 108 | final PsiArrayInitializerMemberValue value = (PsiArrayInitializerMemberValue) oldStoriesAnnotation 109 | .findDeclaredAttributeValue("value"); 110 | 111 | final List stories = Arrays.stream(value.getInitializers()) 112 | .map(PsiAnnotationMemberValue::getText) 113 | .collect(Collectors.toList()); 114 | 115 | final String storiesText = getStoriesAnnotationText(stories); 116 | final PsiAnnotation storiesAnnotation = createAnnotation(storiesText, testMethod); 117 | 118 | final Project project = testMethod.getProject(); 119 | CommandProcessor.getInstance().executeCommand(project, () -> ApplicationManager.getApplication().runWriteAction(() -> { 120 | PsiUtils.addImport(testMethod.getContainingFile(), ALLURE2_STORY_ANNOTATION); 121 | PsiUtils.addImport(testMethod.getContainingFile(), ALLURE2_STORIES_ANNOTATION); 122 | 123 | testMethod.getModifierList().addAfter(storiesAnnotation, oldStoriesAnnotation); 124 | oldStoriesAnnotation.delete(); 125 | 126 | PsiUtils.optimizeImports(testMethod.getContainingFile()); 127 | }), "Migrate Allure Stories", null); 128 | }); 129 | } 130 | 131 | private void migrateStepAnnotation(final PsiMethod testMethod) { 132 | Optional.ofNullable(testMethod.getAnnotation(ALLURE1_STEP_ANNOTATION)).ifPresent(oldStepAnnotation -> { 133 | final String oldStepValue = AnnotationUtil.getDeclaredStringAttributeValue(oldStepAnnotation, "value"); 134 | 135 | final String[] params = Arrays.stream(testMethod.getParameters()) 136 | .map(JvmNamedElement::getName) 137 | .toArray(String[]::new); 138 | 139 | final String stepValue = convert(oldStepValue, params); 140 | final String stepText = String.format("@%s(\"%s\")", ALLURE2_STEP_ANNOTATION, stepValue); 141 | 142 | final PsiAnnotation stepAnnotation = createAnnotation(stepText, testMethod); 143 | 144 | final Project project = testMethod.getProject(); 145 | CommandProcessor.getInstance().executeCommand(project, () -> ApplicationManager.getApplication().runWriteAction(() -> { 146 | PsiUtils.addImport(testMethod.getContainingFile(), ALLURE2_STEP_ANNOTATION); 147 | testMethod.getModifierList().addAfter(stepAnnotation, oldStepAnnotation); 148 | oldStepAnnotation.delete(); 149 | PsiUtils.optimizeImports(testMethod.getContainingFile()); 150 | }), "Migrate Allure Steps", null); 151 | }); 152 | } 153 | 154 | private String getFeaturesAnnotationText(final List features) { 155 | final String body = features.stream() 156 | .map(label -> String.format("@%s(%s)", ALLURE2_FEATURE_ANNOTATION, label)) 157 | .collect(Collectors.joining(",")); 158 | return String.format("@%s({%s})", ALLURE2_FEATURES_ANNOTATION, body); 159 | } 160 | 161 | private String getStoriesAnnotationText(final List features) { 162 | final String body = features.stream() 163 | .map(label -> String.format("@%s(%s)", ALLURE2_STORY_ANNOTATION, label)) 164 | .collect(Collectors.joining(",")); 165 | return String.format("@%s({%s})", ALLURE2_STORIES_ANNOTATION, body); 166 | } 167 | 168 | private String convert(final String stepValue, final String[] params) { 169 | String result = stepValue; 170 | for (int i = 0; i < params.length; i++) { 171 | result = result.replace("{" + i + "}", "{" + params[i] + "}"); 172 | } 173 | return result; 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/Annotations.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea; 2 | 3 | /** 4 | * @author eroshenkoam (Artem Eroshenko). 5 | */ 6 | public final class Annotations { 7 | 8 | public static final String JUNIT_TEST_ANNOTATION = "org.junit.jupiter.api.Test"; 9 | public static final String JUNIT_DISPLAY_NAME_ANNOTATION = "org.junit.jupiter.api.DisplayName"; 10 | 11 | public static final String JUNIT_TAGS_ANNOTATION = "org.junit.jupiter.api.Tags"; 12 | public static final String JUNIT_TAG_ANNOTATION = "org.junit.jupiter.api.Tag"; 13 | 14 | public static final String ALLURE2_TMS_LINK_ANNOTATION = "io.qameta.allure.TmsLink"; 15 | public static final String ALLURE2_STEP_ANNOTATION = "io.qameta.allure.Step"; 16 | public static final String ALLURE2_FEATURE_ANNOTATION = "io.qameta.allure.Feature"; 17 | public static final String ALLURE2_FEATURES_ANNOTATION = "io.qameta.allure.Features"; 18 | public static final String ALLURE2_STORY_ANNOTATION = "io.qameta.allure.Story"; 19 | public static final String ALLURE2_STORIES_ANNOTATION = "io.qameta.allure.Stories"; 20 | 21 | public static final String ALLURE1_STEP_ANNOTATION = "ru.yandex.qatools.allure.annotations.Step"; 22 | public static final String ALLURE1_FEATURES_ANNOTATION = "ru.yandex.qatools.allure.annotations.Features"; 23 | public static final String ALLURE1_STORIES_ANNOTATION = "ru.yandex.qatools.allure.annotations.Stories"; 24 | public static final String ALLURE1_TESTCASEID_ANNOTATION = "ru.yandex.qatools.allure.annotations.TestCaseId"; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/AuthenticationAction.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea; 2 | 3 | import com.intellij.openapi.actionSystem.AnAction; 4 | import com.intellij.openapi.actionSystem.AnActionEvent; 5 | import io.eroshenkoam.idea.ui.AuthenticationForm; 6 | 7 | /** 8 | * @author eroshenkoam (Artem Eroshenko). 9 | */ 10 | public class AuthenticationAction extends AnAction { 11 | 12 | @Override 13 | public void actionPerformed(final AnActionEvent e) { 14 | final AuthenticationForm form = new AuthenticationForm(); 15 | form.setVisible(true); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/BaseExportAction.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea; 2 | 3 | import com.intellij.codeInsight.AnnotationUtil; 4 | import com.intellij.openapi.actionSystem.AnAction; 5 | import com.intellij.openapi.actionSystem.AnActionEvent; 6 | import com.intellij.openapi.actionSystem.PlatformDataKeys; 7 | import com.intellij.psi.PsiAnnotation; 8 | import com.intellij.psi.PsiAnnotationMemberValue; 9 | import com.intellij.psi.PsiArrayInitializerMemberValue; 10 | import com.intellij.psi.PsiClass; 11 | import com.intellij.psi.PsiCodeBlock; 12 | import com.intellij.psi.PsiElement; 13 | import com.intellij.psi.PsiMethod; 14 | import com.intellij.psi.PsiMethodCallExpression; 15 | import com.intellij.psi.PsiStatement; 16 | import io.eroshenkoam.idea.export.TestCase; 17 | import io.eroshenkoam.idea.export.TestStep; 18 | 19 | import java.util.Arrays; 20 | import java.util.List; 21 | import java.util.Map; 22 | import java.util.Objects; 23 | import java.util.Optional; 24 | import java.util.stream.Collectors; 25 | 26 | import static io.eroshenkoam.idea.Annotations.ALLURE2_FEATURES_ANNOTATION; 27 | import static io.eroshenkoam.idea.Annotations.ALLURE2_STEP_ANNOTATION; 28 | import static io.eroshenkoam.idea.Annotations.ALLURE2_STORIES_ANNOTATION; 29 | import static io.eroshenkoam.idea.Annotations.ALLURE2_TMS_LINK_ANNOTATION; 30 | import static io.eroshenkoam.idea.Annotations.JUNIT_DISPLAY_NAME_ANNOTATION; 31 | import static io.eroshenkoam.idea.Annotations.JUNIT_TEST_ANNOTATION; 32 | 33 | /** 34 | * @author eroshenkoam (Artem Eroshenko). 35 | */ 36 | public abstract class BaseExportAction extends AnAction { 37 | 38 | public abstract void exportTestCases(final AnActionEvent event, final Map testCaseMap); 39 | 40 | @Override 41 | public void actionPerformed(final AnActionEvent event) { 42 | final PsiElement element = event.getData(PlatformDataKeys.PSI_ELEMENT); 43 | if (element instanceof PsiClass) { 44 | final PsiClass psiClass = (PsiClass) element; 45 | final Map testCaseMap = Arrays.stream(psiClass.getMethods()) 46 | .filter(m -> m.hasAnnotation(JUNIT_TEST_ANNOTATION)) 47 | .collect(Collectors.toMap(m -> m, this::exportTestCaseFromMethod)); 48 | exportTestCases(event, testCaseMap); 49 | } 50 | } 51 | 52 | private TestCase exportTestCaseFromMethod(final PsiMethod method) { 53 | final TestCase testCase = new TestCase(); 54 | getId(method).ifPresent(testCase::setId); 55 | testCase.setName(getName(method)); 56 | testCase.setFeatures(getValues(method, ALLURE2_FEATURES_ANNOTATION)); 57 | testCase.setStories(getValues(method, ALLURE2_STORIES_ANNOTATION)); 58 | testCase.setSteps(getSteps(method)); 59 | return testCase; 60 | } 61 | 62 | private static Optional getId(final PsiMethod method) { 63 | return Optional.ofNullable(method.getAnnotation(ALLURE2_TMS_LINK_ANNOTATION)) 64 | .map(a -> AnnotationUtil.getStringAttributeValue(a, "value")); 65 | } 66 | 67 | private static String getName(final PsiMethod method) { 68 | return AnnotationUtil.getStringAttributeValue(method.getAnnotation(JUNIT_DISPLAY_NAME_ANNOTATION), "value"); 69 | } 70 | 71 | private static List getSteps(final PsiMethod method) { 72 | final PsiStatement[] statements = Optional.ofNullable(method.getBody()) 73 | .map(PsiCodeBlock::getStatements) 74 | .orElse(new PsiStatement[]{}); 75 | 76 | final List methodCallExpressions = Arrays.stream(statements) 77 | .map(PsiElement::getChildren) 78 | .flatMap(Arrays::stream) 79 | .filter(PsiMethodCallExpression.class::isInstance) 80 | .map(PsiMethodCallExpression.class::cast) 81 | .collect(Collectors.toList()); 82 | 83 | return methodCallExpressions.stream() 84 | .map(PsiMethodCallExpression::resolveMethod) 85 | .filter(Objects::nonNull) 86 | .filter(BaseExportAction::isStepMethod) 87 | .map(m -> m.getAnnotation(ALLURE2_STEP_ANNOTATION)) 88 | .map(s -> AnnotationUtil.getStringAttributeValue(s, "value")) 89 | .map(s -> new TestStep().setName(s)) 90 | .collect(Collectors.toList()); 91 | 92 | } 93 | 94 | private List getValues(final PsiMethod method, final String annotationText) { 95 | final PsiAnnotation annotation = method.getAnnotation(annotationText); 96 | final PsiArrayInitializerMemberValue value = (PsiArrayInitializerMemberValue) annotation 97 | .findDeclaredAttributeValue("value"); 98 | return Arrays.stream(value.getInitializers()) 99 | .map(PsiAnnotation.class::cast) 100 | .map(a -> a.findDeclaredAttributeValue("value")) 101 | .map(PsiAnnotationMemberValue::getText) 102 | .map(text -> text.substring(1, text.length() -1)) 103 | .collect(Collectors.toList()); 104 | } 105 | 106 | private static boolean isStepMethod(final PsiMethod method) { 107 | return method.hasAnnotation(ALLURE2_STEP_ANNOTATION); 108 | } 109 | 110 | } 111 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/JiraKeyImportAction.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea; 2 | 3 | import com.intellij.openapi.actionSystem.AnAction; 4 | import com.intellij.openapi.actionSystem.AnActionEvent; 5 | import com.intellij.openapi.actionSystem.PlatformDataKeys; 6 | import com.intellij.openapi.application.ApplicationManager; 7 | import com.intellij.openapi.command.CommandProcessor; 8 | import com.intellij.openapi.project.Project; 9 | import com.intellij.psi.PsiAnnotation; 10 | import com.intellij.psi.PsiClass; 11 | import com.intellij.psi.PsiElement; 12 | import com.intellij.psi.PsiMethod; 13 | import io.eroshenkoam.idea.jira.JiraClient; 14 | import io.eroshenkoam.idea.jira.JiraClientBuilder; 15 | import io.eroshenkoam.idea.jira.JiraIssue; 16 | import io.eroshenkoam.idea.util.PsiUtils; 17 | 18 | import java.util.Arrays; 19 | import java.util.Optional; 20 | 21 | import static io.eroshenkoam.idea.Annotations.ALLURE2_TMS_LINK_ANNOTATION; 22 | import static io.eroshenkoam.idea.Annotations.JUNIT_DISPLAY_NAME_ANNOTATION; 23 | import static io.eroshenkoam.idea.Annotations.JUNIT_TEST_ANNOTATION; 24 | 25 | /** 26 | * @author eroshenkoam (Artem Eroshenko). 27 | */ 28 | public class JiraKeyImportAction extends AnAction { 29 | 30 | @Override 31 | public void actionPerformed(final AnActionEvent event) { 32 | final PsiElement element = event.getData(PlatformDataKeys.PSI_ELEMENT); 33 | if (element instanceof PsiClass) { 34 | final PsiClass psiClass = (PsiClass) element; 35 | Arrays.stream(psiClass.getMethods()) 36 | .filter(m -> m.hasAnnotation(JUNIT_DISPLAY_NAME_ANNOTATION)) 37 | .filter(m -> m.hasAnnotation(JUNIT_TEST_ANNOTATION)) 38 | .forEach(this::createTmsLinkAnnotation); 39 | } 40 | } 41 | 42 | private void createTmsLinkAnnotation(final PsiMethod method) { 43 | final String name = Optional.ofNullable(method.getAnnotation(JUNIT_DISPLAY_NAME_ANNOTATION)) 44 | .map(a -> a.findDeclaredAttributeValue("value")) 45 | .map(PsiElement::getText) 46 | .get(); 47 | 48 | final JiraClient jiraClient = createJiraClient(); 49 | final String key = jiraClient.findIssue(String.format("text ~ %s", name)).getIssues().stream() 50 | .map(JiraIssue::getKey) 51 | .findFirst().get(); 52 | 53 | final Project project = method.getProject(); 54 | CommandProcessor.getInstance().executeCommand(project, () -> ApplicationManager.getApplication().runWriteAction(() -> { 55 | PsiUtils.addImport(method.getContainingFile(), ALLURE2_TMS_LINK_ANNOTATION); 56 | 57 | Optional.ofNullable(method.getAnnotation(ALLURE2_TMS_LINK_ANNOTATION)).ifPresent(PsiAnnotation::delete); 58 | PsiAnnotation tmsLinks = createTmsIssueAnnotation(method, key); 59 | method.getModifierList().addAfter(tmsLinks, method.getAnnotation(JUNIT_TEST_ANNOTATION)); 60 | 61 | PsiUtils.optimizeImports(method.getContainingFile()); 62 | }), "Import Jira keys", null); 63 | } 64 | 65 | private PsiAnnotation createTmsIssueAnnotation(final PsiMethod method, final String key) { 66 | return PsiUtils.createAnnotation(String.format("@%s(\"%s\")", ALLURE2_TMS_LINK_ANNOTATION, key), method); 67 | } 68 | 69 | private JiraClient createJiraClient() { 70 | return new JiraClientBuilder() 71 | .endpoint("http://localhost:2990/jira/rest/") 72 | .username("admin") 73 | .password("admin") 74 | .build(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/JiraLabelsImportAction.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea; 2 | 3 | import com.intellij.codeInsight.AnnotationUtil; 4 | import com.intellij.openapi.actionSystem.AnAction; 5 | import com.intellij.openapi.actionSystem.AnActionEvent; 6 | import com.intellij.openapi.actionSystem.PlatformDataKeys; 7 | import com.intellij.openapi.application.ApplicationManager; 8 | import com.intellij.openapi.command.CommandProcessor; 9 | import com.intellij.openapi.project.Project; 10 | import com.intellij.psi.PsiAnnotation; 11 | import com.intellij.psi.PsiClass; 12 | import com.intellij.psi.PsiElement; 13 | import com.intellij.psi.PsiMethod; 14 | import io.eroshenkoam.idea.jira.JiraClient; 15 | import io.eroshenkoam.idea.jira.JiraClientBuilder; 16 | import io.eroshenkoam.idea.util.PsiUtils; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Arrays; 20 | import java.util.List; 21 | import java.util.Optional; 22 | import java.util.stream.Collectors; 23 | 24 | import static io.eroshenkoam.idea.Annotations.ALLURE2_TMS_LINK_ANNOTATION; 25 | import static io.eroshenkoam.idea.Annotations.JUNIT_TAGS_ANNOTATION; 26 | import static io.eroshenkoam.idea.Annotations.JUNIT_TAG_ANNOTATION; 27 | import static io.eroshenkoam.idea.Annotations.JUNIT_TEST_ANNOTATION; 28 | 29 | /** 30 | * @author eroshenkoam (Artem Eroshenko). 31 | */ 32 | public class JiraLabelsImportAction extends AnAction { 33 | 34 | 35 | @Override 36 | public void actionPerformed(final AnActionEvent event) { 37 | final PsiElement element = event.getData(PlatformDataKeys.PSI_ELEMENT); 38 | if (element instanceof PsiClass) { 39 | final PsiClass psiClass = (PsiClass) element; 40 | Arrays.stream(psiClass.getMethods()) 41 | .filter(m -> m.hasAnnotation(ALLURE2_TMS_LINK_ANNOTATION)) 42 | .filter(m -> m.hasAnnotation(JUNIT_TEST_ANNOTATION)) 43 | .forEach(this::createTagsAnnotation); 44 | } 45 | } 46 | 47 | private void createTagsAnnotation(final PsiMethod method) { 48 | final String issueKey = AnnotationUtil 49 | .getStringAttributeValue(method.getAnnotation(ALLURE2_TMS_LINK_ANNOTATION), "value"); 50 | 51 | final JiraClient jiraClient = createJiraClient(); 52 | Optional.ofNullable(jiraClient.getIssue(issueKey)).ifPresent(issue -> { 53 | final List tags = Optional.ofNullable(issue.getFields().getLabels()) 54 | .orElseGet(ArrayList::new); 55 | 56 | final String tagsAnnotationText = getTagsAnnotationText(tags); 57 | final PsiAnnotation tagsAnnotation = PsiUtils.createAnnotation(tagsAnnotationText, method); 58 | 59 | final Project project = method.getProject(); 60 | final PsiAnnotation tmsLinkAnnotation = method.getAnnotation(ALLURE2_TMS_LINK_ANNOTATION); 61 | 62 | CommandProcessor.getInstance().executeCommand(project, () -> ApplicationManager.getApplication().runWriteAction(() -> { 63 | Optional.ofNullable(method.getAnnotation(JUNIT_TAGS_ANNOTATION)).ifPresent(PsiAnnotation::delete); 64 | Optional.ofNullable(method.getAnnotation(JUNIT_TAG_ANNOTATION)).ifPresent(PsiAnnotation::delete); 65 | 66 | PsiUtils.addImport(method.getContainingFile(), JUNIT_TAGS_ANNOTATION); 67 | PsiUtils.addImport(method.getContainingFile(), JUNIT_TAG_ANNOTATION); 68 | 69 | method.getModifierList().addAfter(tagsAnnotation, tmsLinkAnnotation); 70 | PsiUtils.optimizeImports(method.getContainingFile()); 71 | }), "Insert Jira labels", null); 72 | }); 73 | 74 | } 75 | 76 | private String getTagsAnnotationText(final List labels) { 77 | final String body = labels.stream() 78 | .map(label -> String.format("@%s(\"%s\")", JUNIT_TAG_ANNOTATION, label)) 79 | .collect(Collectors.joining(",")); 80 | return String.format("@%s({%s})", JUNIT_TAGS_ANNOTATION, body); 81 | } 82 | 83 | private JiraClient createJiraClient() { 84 | return new JiraClientBuilder() 85 | .endpoint("http://localhost:2990/jira/rest/") 86 | .username("admin") 87 | .password("admin") 88 | .build(); 89 | } 90 | 91 | } 92 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/JiraTestCaseExportAction.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea; 2 | 3 | import com.intellij.openapi.actionSystem.AnActionEvent; 4 | import com.intellij.openapi.application.ApplicationManager; 5 | import com.intellij.openapi.command.CommandProcessor; 6 | import com.intellij.openapi.project.Project; 7 | import com.intellij.psi.PsiAnnotation; 8 | import com.intellij.psi.PsiMethod; 9 | import io.eroshenkoam.idea.export.TestCase; 10 | import io.eroshenkoam.idea.export.TestStep; 11 | import io.eroshenkoam.idea.jira.JiraClient; 12 | import io.eroshenkoam.idea.jira.JiraClientBuilder; 13 | import io.eroshenkoam.idea.jira.JiraIssue; 14 | import io.eroshenkoam.idea.jira.JiraIssueFields; 15 | import io.eroshenkoam.idea.jira.JiraIssuetype; 16 | import io.eroshenkoam.idea.jira.JiraProject; 17 | import io.eroshenkoam.idea.util.PsiUtils; 18 | 19 | import java.util.List; 20 | import java.util.Map; 21 | import java.util.Optional; 22 | import java.util.stream.Collectors; 23 | 24 | import static io.eroshenkoam.idea.Annotations.ALLURE2_TMS_LINK_ANNOTATION; 25 | import static io.eroshenkoam.idea.Annotations.JUNIT_TEST_ANNOTATION; 26 | 27 | /** 28 | * @author eroshenkoam (Artem Eroshenko). 29 | */ 30 | public class JiraTestCaseExportAction extends BaseExportAction { 31 | 32 | @Override 33 | public void exportTestCases(final AnActionEvent event, final Map testCasesMap) { 34 | final JiraClient client = createJiraClient(); 35 | 36 | testCasesMap.forEach((method, testCase) -> { 37 | final JiraIssueFields fields = new JiraIssueFields() 38 | .setSummary(testCase.getName()) 39 | .setDescription(toScenario(testCase.getSteps())) 40 | .setProject(new JiraProject().setKey("NEW")) 41 | .setIssuetype(new JiraIssuetype().setName("Задача")) 42 | .setFeatures(toLabels(testCase.getFeatures())) 43 | .setStories(toLabels(testCase.getStories())); 44 | final JiraIssue issue = client.createIssue(new JiraIssue().setFields(fields)); 45 | createTmsLink(method, issue.getKey()); 46 | }); 47 | } 48 | 49 | private void createTmsLink(final PsiMethod method, String key) { 50 | final Project project = method.getProject(); 51 | CommandProcessor.getInstance().executeCommand(project, () -> ApplicationManager.getApplication().runWriteAction(() -> { 52 | PsiUtils.addImport(method.getContainingFile(), ALLURE2_TMS_LINK_ANNOTATION); 53 | 54 | Optional.ofNullable(method.getAnnotation(ALLURE2_TMS_LINK_ANNOTATION)).ifPresent(PsiAnnotation::delete); 55 | 56 | PsiAnnotation tmsLinks = createTmsIssueAnnotation(method, key); 57 | method.getModifierList().addAfter(tmsLinks, method.getAnnotation(JUNIT_TEST_ANNOTATION)); 58 | 59 | PsiUtils.optimizeImports(method.getContainingFile()); 60 | }), "Import Jira keys", null); 61 | } 62 | 63 | private PsiAnnotation createTmsIssueAnnotation(final PsiMethod method, final String key) { 64 | return PsiUtils.createAnnotation(String.format("@%s(\"%s\")", ALLURE2_TMS_LINK_ANNOTATION, key), method); 65 | } 66 | 67 | private String toScenario(final List steps) { 68 | steps.forEach(step -> System.out.println(step.getName())); 69 | return steps.stream() 70 | .map(TestStep::getName) 71 | .map(step -> step.replace("{", "\\{")) 72 | .map(step -> "# " + step) 73 | .collect(Collectors.joining("\r\n")); 74 | } 75 | 76 | private List toLabels(final List values) { 77 | return values.stream() 78 | .map(value -> value.replace(" ", "_")) 79 | .collect(Collectors.toList()); 80 | } 81 | 82 | private JiraClient createJiraClient() { 83 | return new JiraClientBuilder() 84 | .endpoint("http://localhost:2990/jira/rest/") 85 | .username("admin") 86 | .password("admin") 87 | .build(); 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/PluginException.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea; 2 | 3 | import java.util.function.Supplier; 4 | 5 | /** 6 | * @author eroshenkoam (Artem Eroshenko). 7 | */ 8 | public class PluginException extends RuntimeException { 9 | 10 | public PluginException(final String message) { 11 | super(message); 12 | } 13 | 14 | public PluginException(final String message, final Throwable e) { 15 | super(message, e); 16 | } 17 | 18 | public static Supplier notFound(final String message) { 19 | return () -> new PluginException(String.format("%s not found", message)); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/TestCaseExportAction.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea; 2 | 3 | import com.intellij.openapi.actionSystem.AnActionEvent; 4 | import com.intellij.openapi.project.Project; 5 | import com.intellij.psi.PsiMethod; 6 | import io.eroshenkoam.idea.export.TestCase; 7 | import io.eroshenkoam.idea.util.FreemarkerUtils; 8 | 9 | import java.io.IOException; 10 | import java.nio.file.Files; 11 | import java.nio.file.Path; 12 | import java.nio.file.Paths; 13 | import java.util.Map; 14 | 15 | /** 16 | * @author eroshenkoam (Artem Eroshenko). 17 | */ 18 | public class TestCaseExportAction extends BaseExportAction { 19 | 20 | @Override 21 | public void exportTestCases(final AnActionEvent event, final Map testCasesMap) { 22 | final Project project = event.getProject(); 23 | final Path exportPath = Paths.get(project.getBasePath()).resolve("index.html"); 24 | try { 25 | Files.write(exportPath, FreemarkerUtils.processTemplate("testcases.ftl", testCasesMap.values()).getBytes()); 26 | } catch (IOException e) { 27 | throw new RuntimeException(e); 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/export/TestCase.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea.export; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author eroshenkoam (Artem Eroshenko). 7 | */ 8 | public class TestCase { 9 | 10 | private String id; 11 | private String name; 12 | private String description; 13 | 14 | private List links; 15 | 16 | private List features; 17 | private List stories; 18 | 19 | private List steps; 20 | 21 | 22 | public String getId() { 23 | return id; 24 | } 25 | 26 | public void setId(String id) { 27 | this.id = id; 28 | } 29 | 30 | public String getName() { 31 | return name; 32 | } 33 | 34 | public void setName(String name) { 35 | this.name = name; 36 | } 37 | 38 | public String getDescription() { 39 | return description; 40 | } 41 | 42 | public void setDescription(String description) { 43 | this.description = description; 44 | } 45 | 46 | public List getLinks() { 47 | return links; 48 | } 49 | 50 | public void setLinks(List links) { 51 | this.links = links; 52 | } 53 | 54 | public List getFeatures() { 55 | return features; 56 | } 57 | 58 | public void setFeatures(List features) { 59 | this.features = features; 60 | } 61 | 62 | public List getStories() { 63 | return stories; 64 | } 65 | 66 | public void setStories(List stories) { 67 | this.stories = stories; 68 | } 69 | 70 | public List getSteps() { 71 | return steps; 72 | } 73 | 74 | public void setSteps(List steps) { 75 | this.steps = steps; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/export/TestStep.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea.export; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * @author eroshenkoam (Artem Eroshenko). 7 | */ 8 | public class TestStep { 9 | 10 | private String name; 11 | 12 | private List steps; 13 | 14 | public String getName() { 15 | return name; 16 | } 17 | 18 | public TestStep setName(String name) { 19 | this.name = name; 20 | return this; 21 | } 22 | 23 | public List getSteps() { 24 | return steps; 25 | } 26 | 27 | public TestStep setSteps(List steps) { 28 | this.steps = steps; 29 | return this; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/jira/JiraClient.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea.jira; 2 | 3 | import retrofit2.http.Body; 4 | import retrofit2.http.GET; 5 | import retrofit2.http.POST; 6 | import retrofit2.http.Path; 7 | import retrofit2.http.Query; 8 | 9 | /** 10 | * @author eroshenkoam (Artem Eroshenko). 11 | */ 12 | public interface JiraClient { 13 | 14 | @GET("api/2/myself") 15 | JiraUser getUser(); 16 | 17 | @GET("api/2/search") 18 | JiraFilter findIssue(@Query(value = "jql", encoded = true) String jql); 19 | 20 | @GET("api/2/issue/{key}") 21 | JiraIssue getIssue(@Path("key") String key); 22 | 23 | @POST("api/2/issue") 24 | JiraIssue createIssue(@Body JiraIssue issue); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/jira/JiraClientBuilder.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea.jira; 2 | 3 | import io.eroshenkoam.idea.retrofit.BasicAuthInterceptor; 4 | import io.eroshenkoam.idea.retrofit.DefaultCallAdapterFactory; 5 | import okhttp3.OkHttpClient; 6 | import okhttp3.logging.HttpLoggingInterceptor; 7 | import retrofit2.Retrofit; 8 | import retrofit2.converter.jackson.JacksonConverterFactory; 9 | 10 | import java.util.Objects; 11 | 12 | /** 13 | * @author eroshenkoam (Artem Eroshenko). 14 | */ 15 | public class JiraClientBuilder { 16 | 17 | private String endpoint; 18 | 19 | private String username; 20 | 21 | private String password; 22 | 23 | public JiraClientBuilder endpoint(String endpoint) { 24 | Objects.requireNonNull(endpoint); 25 | this.endpoint = endpoint; 26 | return this; 27 | } 28 | 29 | public JiraClientBuilder username(String username) { 30 | Objects.requireNonNull(username); 31 | this.username = username; 32 | return this; 33 | } 34 | 35 | public JiraClientBuilder password(String password) { 36 | Objects.requireNonNull(password); 37 | this.password = password; 38 | return this; 39 | } 40 | 41 | public JiraClient build() { 42 | HttpLoggingInterceptor logger = new HttpLoggingInterceptor(); 43 | logger.setLevel(HttpLoggingInterceptor.Level.BODY); 44 | 45 | final OkHttpClient client = new OkHttpClient.Builder() 46 | .addInterceptor(new BasicAuthInterceptor(username, password)) 47 | .addInterceptor(logger) 48 | .build(); 49 | 50 | final Retrofit retrofit = new Retrofit.Builder() 51 | .addCallAdapterFactory(new DefaultCallAdapterFactory<>()) 52 | .addConverterFactory(JacksonConverterFactory.create()) 53 | .baseUrl(endpoint) 54 | .client(client) 55 | .build(); 56 | 57 | return retrofit.create(JiraClient.class); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/jira/JiraFilter.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea.jira; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | 5 | import java.io.Serializable; 6 | import java.util.List; 7 | 8 | /** 9 | * @author eroshenkoam (Artem Eroshenko). 10 | */ 11 | @JsonIgnoreProperties(ignoreUnknown = true) 12 | public class JiraFilter implements Serializable { 13 | 14 | private static final long serialVersionUID = 1L; 15 | 16 | private List issues; 17 | 18 | public List getIssues() { 19 | return issues; 20 | } 21 | 22 | public void setIssues(List issues) { 23 | this.issues = issues; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/jira/JiraIssue.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea.jira; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.Data; 5 | import lombok.experimental.Accessors; 6 | 7 | import java.io.Serializable; 8 | 9 | /** 10 | * @author eroshenkoam (Artem Eroshenko). 11 | */ 12 | @Data 13 | @Accessors(chain = true) 14 | @JsonIgnoreProperties(ignoreUnknown = true) 15 | public class JiraIssue implements Serializable { 16 | 17 | private static final long serialVersionUID = 1L; 18 | 19 | private String key; 20 | private JiraIssueFields fields; 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/jira/JiraIssueFields.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea.jira; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Data; 6 | import lombok.experimental.Accessors; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * @author eroshenkoam (Artem Eroshenko). 12 | */ 13 | @Data 14 | @Accessors(chain = true) 15 | @JsonIgnoreProperties(ignoreUnknown = true) 16 | public class JiraIssueFields { 17 | 18 | private String summary; 19 | private String description; 20 | 21 | private JiraProject project; 22 | private JiraIssuetype issuetype; 23 | 24 | private List labels; 25 | 26 | @JsonProperty("customfield_10002") 27 | private List features; 28 | 29 | @JsonProperty("customfield_10003") 30 | private List stories; 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/jira/JiraIssuetype.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea.jira; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.Data; 5 | import lombok.experimental.Accessors; 6 | 7 | /** 8 | * @author eroshenkoam (Artem Eroshenko). 9 | */ 10 | @Data 11 | @Accessors(chain = true) 12 | @JsonIgnoreProperties(ignoreUnknown = true) 13 | public class JiraIssuetype { 14 | 15 | private String name; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/jira/JiraProject.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea.jira; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | import lombok.Data; 5 | import lombok.experimental.Accessors; 6 | 7 | /** 8 | * @author eroshenkoam (Artem Eroshenko). 9 | */ 10 | @Data 11 | @Accessors(chain = true) 12 | @JsonIgnoreProperties(ignoreUnknown = true) 13 | public class JiraProject { 14 | 15 | private String key; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/jira/JiraUser.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea.jira; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 4 | 5 | /** 6 | * @author eroshenkoam (Artem Eroshenko). 7 | */ 8 | @JsonIgnoreProperties(ignoreUnknown = true) 9 | public class JiraUser { 10 | 11 | private String name; 12 | 13 | public String getName() { 14 | return name; 15 | } 16 | 17 | public void setName(String name) { 18 | this.name = name; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/retrofit/BasicAuthInterceptor.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea.retrofit; 2 | 3 | import okhttp3.Credentials; 4 | import okhttp3.Interceptor; 5 | import okhttp3.Request; 6 | import okhttp3.Response; 7 | 8 | import java.io.IOException; 9 | 10 | /** 11 | * @author eroshenkoam (Artem Eroshenko). 12 | */ 13 | public final class BasicAuthInterceptor implements Interceptor { 14 | 15 | private final String credentials; 16 | 17 | public BasicAuthInterceptor(final String user, final String password) { 18 | this.credentials = Credentials.basic(user, password); 19 | } 20 | 21 | @Override 22 | public Response intercept(final Chain chain) throws IOException { 23 | final Request request = chain.request(); 24 | final Request authenticatedRequest = request.newBuilder() 25 | .header("Authorization", credentials).build(); 26 | return chain.proceed(authenticatedRequest); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/retrofit/DefaultCallAdapterFactory.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea.retrofit; 2 | 3 | import io.eroshenkoam.idea.PluginException; 4 | import okhttp3.ResponseBody; 5 | import retrofit2.Call; 6 | import retrofit2.CallAdapter; 7 | import retrofit2.Retrofit; 8 | 9 | import java.io.IOException; 10 | import java.lang.annotation.Annotation; 11 | import java.lang.reflect.ParameterizedType; 12 | import java.lang.reflect.Type; 13 | import java.util.Objects; 14 | 15 | /** 16 | * Default call adapter factory. 17 | * 18 | * @param return type. 19 | */ 20 | public final class DefaultCallAdapterFactory extends CallAdapter.Factory { 21 | 22 | @Override 23 | public CallAdapter get(final Type returnType, final Annotation[] annotations, final Retrofit retrofit) { 24 | if (returnType.getTypeName().startsWith(Call.class.getName())) { 25 | return null; 26 | } 27 | if (returnType.getTypeName().startsWith(retrofit2.Response.class.getName())) { 28 | return new ResponseCallAdapter(((ParameterizedType) returnType).getActualTypeArguments()[0]); 29 | } 30 | return new InstanceCallAdapter(returnType); 31 | } 32 | 33 | private static String getErrorMessage(final retrofit2.Response response) { 34 | final ResponseBody errorBody = response.errorBody(); 35 | final String errorMessage; 36 | try { 37 | errorMessage = Objects.isNull(errorBody) ? response.message() : errorBody.string(); 38 | } catch (IOException e) { 39 | throw new PluginException("could not read error body", e); 40 | } 41 | return errorMessage; 42 | } 43 | 44 | /** 45 | * Call adapter factory for Response<...>. 46 | */ 47 | private class ResponseCallAdapter implements CallAdapter> { 48 | 49 | private final Type returnType; 50 | 51 | ResponseCallAdapter(final Type returnType) { 52 | this.returnType = returnType; 53 | } 54 | 55 | @Override 56 | public Type responseType() { 57 | return returnType; 58 | } 59 | 60 | @Override 61 | public retrofit2.Response adapt(final Call call) { 62 | final retrofit2.Response response; 63 | try { 64 | response = call.execute(); 65 | } catch (IOException e) { 66 | throw new PluginException("Could not execute request", e); 67 | } 68 | 69 | if (!response.isSuccessful()) { 70 | throw new PluginException(getErrorMessage(response)); 71 | } 72 | return response; 73 | } 74 | } 75 | 76 | /** 77 | * Call adapter factory for instances. 78 | */ 79 | private class InstanceCallAdapter implements CallAdapter { 80 | 81 | private static final int NOT_FOUND = 404; 82 | 83 | private final Type returnType; 84 | 85 | InstanceCallAdapter(final Type returnType) { 86 | this.returnType = returnType; 87 | } 88 | 89 | @Override 90 | public Type responseType() { 91 | return returnType; 92 | } 93 | 94 | @Override 95 | public Object adapt(final Call call) { 96 | final retrofit2.Response response; 97 | try { 98 | response = call.execute(); 99 | } catch (IOException e) { 100 | throw new PluginException("Could not get request body", e); 101 | } 102 | if (!response.isSuccessful()) { 103 | if (response.code() == NOT_FOUND) { 104 | return null; 105 | } 106 | throw new PluginException(getErrorMessage(response)); 107 | } 108 | return response.body(); 109 | } 110 | } 111 | 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/ui/AuthenticationForm.form: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 |
151 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/ui/AuthenticationForm.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea.ui; 2 | 3 | import com.intellij.ide.util.PropertiesComponent; 4 | import com.intellij.openapi.diagnostic.DefaultLogger; 5 | import com.intellij.openapi.diagnostic.Logger; 6 | import io.eroshenkoam.idea.jira.JiraClient; 7 | import io.eroshenkoam.idea.jira.JiraClientBuilder; 8 | import org.apache.commons.lang3.StringUtils; 9 | 10 | import javax.swing.*; 11 | import java.awt.*; 12 | import java.util.Optional; 13 | 14 | /** 15 | * @author eroshenkoam (Artem Eroshenko). 16 | */ 17 | public class AuthenticationForm extends JDialog { 18 | 19 | private static final Logger LOGGER = new DefaultLogger(AuthenticationForm.class.getName()); 20 | 21 | private static final String ENDPOINT_KEY = "eroshenkoam.jira.endpoint"; 22 | private static final String USERNAME_KEY = "eroshenkoam.jira.username"; 23 | private static final String PASSWORD_KEY = "eroshenkoam.jira.password"; 24 | 25 | private JButton saveButton; 26 | private JButton testButton; 27 | private JButton cancelButton; 28 | private JPanel rootPanel; 29 | 30 | private JTextField endpointField; 31 | private JTextField usernameField; 32 | private JPasswordField passwordField; 33 | private JTextField statusField; 34 | 35 | public AuthenticationForm() { 36 | setTitle("Authentication Credentials"); 37 | setSize(400, 200); 38 | add(rootPanel); 39 | 40 | Dimension dim = Toolkit.getDefaultToolkit().getScreenSize(); 41 | setLocation(dim.width / 2 - getSize().width / 2, dim.height / 2 - getSize().height / 2); 42 | 43 | cancelButton.addActionListener(e -> handleCancelButton()); 44 | testButton.addActionListener(e -> handleTestButton()); 45 | saveButton.addActionListener(e -> handleOkButton()); 46 | 47 | endpointField.setText(PropertiesComponent.getInstance().getValue(ENDPOINT_KEY)); 48 | usernameField.setText(PropertiesComponent.getInstance().getValue(USERNAME_KEY)); 49 | passwordField.setText(PropertiesComponent.getInstance().getValue(PASSWORD_KEY)); 50 | 51 | statusField.setText("press 'Test' button"); 52 | } 53 | 54 | private void handleCancelButton() { 55 | setVisible(false); 56 | } 57 | 58 | private void handleTestButton() { 59 | Optional username = getJiraUsername(); 60 | if (username.isPresent()) { 61 | statusField.setText(String.format("authorized as '%s'", username.get())); 62 | } else { 63 | statusField.setText("Bad credentials"); 64 | } 65 | } 66 | 67 | private void handleOkButton() { 68 | Optional username = getJiraUsername(); 69 | if (username.isPresent()) { 70 | PropertiesComponent.getInstance().setValue(ENDPOINT_KEY, endpointField.getText()); 71 | PropertiesComponent.getInstance().setValue(USERNAME_KEY, usernameField.getText()); 72 | PropertiesComponent.getInstance().setValue(PASSWORD_KEY, String.valueOf(passwordField.getPassword())); 73 | setVisible(false); 74 | } else { 75 | statusField.setText("Bad credentials"); 76 | } 77 | } 78 | 79 | private Optional getJiraUsername() { 80 | if (isEmpty(endpointField) && isEmpty(usernameField) && isEmpty(passwordField)) { 81 | return Optional.empty(); 82 | } 83 | final JiraClient client = getJiraClient(); 84 | try { 85 | return Optional.of(client.getUser().getName()); 86 | } catch (Exception e) { 87 | LOGGER.error(e); 88 | return Optional.empty(); 89 | } 90 | } 91 | 92 | private boolean isEmpty(final JTextField field) { 93 | return StringUtils.isBlank(field.getText()); 94 | } 95 | 96 | private boolean isEmpty(final JPasswordField field) { 97 | return StringUtils.isBlank(String.copyValueOf(field.getPassword())); 98 | } 99 | 100 | private JiraClient getJiraClient() { 101 | return new JiraClientBuilder() 102 | .endpoint(endpointField.getText()) 103 | .username(usernameField.getText()) 104 | .password(String.copyValueOf(passwordField.getPassword())) 105 | .build(); 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/util/FreemarkerUtils.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea.util; 2 | 3 | import freemarker.template.Configuration; 4 | import freemarker.template.Template; 5 | import freemarker.template.TemplateException; 6 | 7 | import java.io.IOException; 8 | import java.io.StringWriter; 9 | import java.io.Writer; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | /** 14 | * @author eroshenkoam (Artem Eroshenko). 15 | */ 16 | public final class FreemarkerUtils { 17 | 18 | private final static String TEMPLATES = "templates"; 19 | 20 | private FreemarkerUtils() { 21 | } 22 | 23 | public static String processTemplate(final String path, final Object object) { 24 | final Configuration configuration = new Configuration(Configuration.VERSION_2_3_28); 25 | 26 | configuration.setClassForTemplateLoading(FreemarkerUtils.class, "/"); 27 | configuration.setDefaultEncoding("UTF-8"); 28 | 29 | try { 30 | final Map data = new HashMap<>(); 31 | data.put("data", object); 32 | 33 | final Writer writer = new StringWriter(); 34 | final Template template = configuration.getTemplate(path); 35 | template.process(data, writer); 36 | return writer.toString(); 37 | } catch (IOException | TemplateException e) { 38 | throw new RuntimeException(e); 39 | } 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/io/eroshenkoam/idea/util/PsiUtils.java: -------------------------------------------------------------------------------- 1 | package io.eroshenkoam.idea.util; 2 | 3 | import com.intellij.openapi.project.Project; 4 | import com.intellij.psi.JavaPsiFacade; 5 | import com.intellij.psi.PsiAnnotation; 6 | import com.intellij.psi.PsiClass; 7 | import com.intellij.psi.PsiElement; 8 | import com.intellij.psi.PsiElementFactory; 9 | import com.intellij.psi.PsiFile; 10 | import com.intellij.psi.PsiJavaFile; 11 | import com.intellij.psi.codeStyle.JavaCodeStyleManager; 12 | import com.intellij.psi.search.GlobalSearchScope; 13 | 14 | import java.util.Optional; 15 | 16 | /** 17 | * @author eroshenkoam (Artem Eroshenko). 18 | */ 19 | public final class PsiUtils { 20 | 21 | private PsiUtils() { 22 | } 23 | 24 | public static PsiAnnotation createAnnotation(final String annotation, final PsiElement context) { 25 | final PsiElementFactory factory = PsiElementFactory.SERVICE.getInstance(context.getProject()); 26 | return factory.createAnnotationFromText(annotation, context); 27 | } 28 | 29 | public static void optimizeImports(final PsiFile file) { 30 | if (file instanceof PsiJavaFile) { 31 | optimizeImports((PsiJavaFile) file); 32 | } 33 | } 34 | 35 | public static void optimizeImports(final PsiJavaFile file) { 36 | JavaCodeStyleManager.getInstance(file.getProject()).shortenClassReferences(file); 37 | JavaCodeStyleManager.getInstance(file.getProject()).removeRedundantImports(file); 38 | } 39 | 40 | public static void addImport(final PsiFile file, final String qualifiedName) { 41 | if (file instanceof PsiJavaFile) { 42 | addImport((PsiJavaFile) file, qualifiedName); 43 | } 44 | } 45 | 46 | public static void addImport(final PsiJavaFile file, final String qualifiedName) { 47 | final Project project = file.getProject(); 48 | Optional possibleClass = Optional.ofNullable(JavaPsiFacade.getInstance(project) 49 | .findClass(qualifiedName, GlobalSearchScope.everythingScope(project))); 50 | possibleClass.ifPresent(psiClass -> JavaCodeStyleManager.getInstance(project).addImport(file, psiClass)); 51 | } 52 | 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | io.eroshenkoam.idea.idea 3 | Artem Eroshenko 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 16 | 18 | 20 | 22 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /src/main/resources/testcases.ftl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Test Cases 5 | 7 | 8 | 9 |
10 |
11 |

Test Cases

12 | <#list data as testcase> 13 |

${testcase.id} ${testcase.name}

14 |
15 |
Features
16 |
${testcase.features?join(", ")}
17 |
Stories
18 |
${testcase.stories?join(", ")}
19 |
20 |

Scenario

21 |
    22 | <#list testcase.steps as step> 23 |
  1. ${step.name}
  2. 24 | 25 |
26 | 27 |
28 |
29 | 30 | 31 | 32 | --------------------------------------------------------------------------------