BDD cucumber 01/55301/1
authorayalaben <ayala.benzvi@amdocs.com>
Sun, 24 Jun 2018 07:42:43 +0000 (10:42 +0300)
committerayalaben <ayala.benzvi@amdocs.com>
Sun, 24 Jun 2018 07:42:43 +0000 (10:42 +0300)
Change-Id: I34f9950dab1c15f8c19da5f696783d793ee3511f
Issue-ID: SDC-1442
Signed-off-by: ayalaben <ayala.benzvi@amdocs.com>
24 files changed:
workflow-bdd/.gitignore [new file with mode: 0644]
workflow-bdd/README.txt [new file with mode: 0644]
workflow-bdd/config.json [new file with mode: 0644]
workflow-bdd/cucumber.js [new file with mode: 0644]
workflow-bdd/features/Workflow_Create_Update.feature [new file with mode: 0644]
workflow-bdd/package.json [new file with mode: 0644]
workflow-bdd/plugins/README.md [new file with mode: 0644]
workflow-bdd/plugins/jsdoc_config.json [new file with mode: 0644]
workflow-bdd/plugins/reporter.js [new file with mode: 0644]
workflow-bdd/plugins/steps.js [new file with mode: 0644]
workflow-bdd/pom.xml [new file with mode: 0644]
workflow-bdd/resources/json/createVLM.json [new file with mode: 0644]
workflow-bdd/resources/json/createVSP.json [new file with mode: 0644]
workflow-bdd/stepDefinitions/Collaboration_Steps.js [new file with mode: 0644]
workflow-bdd/stepDefinitions/General_Steps.js [new file with mode: 0644]
workflow-bdd/stepDefinitions/InputData_steps.js [new file with mode: 0644]
workflow-bdd/stepDefinitions/InterfaceOperationSteps.js [new file with mode: 0644]
workflow-bdd/stepDefinitions/Item_steps.js [new file with mode: 0644]
workflow-bdd/stepDefinitions/REST_Steps.js [new file with mode: 0644]
workflow-bdd/stepDefinitions/Utils.js [new file with mode: 0644]
workflow-bdd/stepDefinitions/VLM_steps.js [new file with mode: 0644]
workflow-bdd/stepDefinitions/VSP_steps.js [new file with mode: 0644]
workflow-bdd/stepDefinitions/world.js [new file with mode: 0644]
workflow-designer-be/src/main/java/org/onap/sdc/workflow/services/impl/WorkflowManagerImpl.java

diff --git a/workflow-bdd/.gitignore b/workflow-bdd/.gitignore
new file mode 100644 (file)
index 0000000..316e398
--- /dev/null
@@ -0,0 +1,11 @@
+.idea
+.vscode
+.history
+debug.log
+dist
+docs
+node_modules
+.npmrc
+npm-debug.log
+devConfig.json
+jenkinsConfig.json
diff --git a/workflow-bdd/README.txt b/workflow-bdd/README.txt
new file mode 100644 (file)
index 0000000..35250ed
--- /dev/null
@@ -0,0 +1,4 @@
+In order to setup the project:
+
+Run "mvn install -DskipTests", this will create the documentation under the "docs".
+Open the index.html under the docs directory and continue from there.
\ No newline at end of file
diff --git a/workflow-bdd/config.json b/workflow-bdd/config.json
new file mode 100644 (file)
index 0000000..260f285
--- /dev/null
@@ -0,0 +1,28 @@
+{
+  "protocol" : "http",
+
+  "onboarding" : {
+    "port" : 8285,
+    "prefix" : "sdc1/feProxy/onboarding-api/v1.0",
+    "server" : "onboarding.server",
+    "user" : "user"
+  },
+  "vf" : {
+    "port" : 8285,
+    "prefix" : "sdc1/feProxy/rest/v1",
+    "server" : "vf.server",
+    "user" : "user"
+  },
+  "workflow" : {
+    "port" : 8080,
+    "prefix" : "wf",
+    "server" : "",
+    "user" : "user"
+  },
+  "activity_spec" : {
+    "port" : 8080,
+    "prefix" : "activity-spec-api/v1.0",
+    "server" : "activity_spec.server",
+    "user" : "user"
+  }
+}
diff --git a/workflow-bdd/cucumber.js b/workflow-bdd/cucumber.js
new file mode 100644 (file)
index 0000000..4ade9b1
--- /dev/null
@@ -0,0 +1,3 @@
+module.exports = {
+       "default" : "--require stepDefinitions -f summary -r ./features -f json:report/report.json"
+};
\ No newline at end of file
diff --git a/workflow-bdd/features/Workflow_Create_Update.feature b/workflow-bdd/features/Workflow_Create_Update.feature
new file mode 100644 (file)
index 0000000..04a64bf
--- /dev/null
@@ -0,0 +1,27 @@
+Feature: Workflow Example File
+
+  Scenario: Create and get workflow
+    When I want to create input data
+    Then I want to update the input property "name" with a random value
+    Then I want to update the input property "description" with value "workflow desc"
+    Then I want to update the input property "category" with value "workflow category"
+
+    Then I want to create for path "/workflows" with the input data from the context
+    Then I want to copy to property "workflowId" from response data path "id"
+    When I want to get path "/workflows"
+    Then I want to check that element in the response list with "id" equals to value of saved property "workflowId" exists
+
+
+  Scenario: Update workflow
+    When I want to create input data
+    Then I want to update the input property "name" with a random value
+    Then I want to update the input property "description" with value "workflow desc"
+    Then I want to update the input property "category" with value "workflow category"
+    Then I want to create for path "/workflows" with the input data from the context
+    Then I want to copy to property "workflowId" from response data path "id"
+
+    Then I want to update the input property "description" with value "workflow desc updated"
+    Then I want to set property "desc" to value "workflow desc updated"
+    Then I want to update for path "/workflows/{workflowId}" with the input data from the context
+    Then I want to get path "/workflows/{workflowId}"
+    Then I want to check that property "description" in the response equals to value of saved property "desc"
diff --git a/workflow-bdd/package.json b/workflow-bdd/package.json
new file mode 100644 (file)
index 0000000..e8841bc
--- /dev/null
@@ -0,0 +1,31 @@
+{
+  "name": "sdctests",
+  "version": "1.0.0",
+  "description": "SDC Cucumber testing",
+  "main": "reporter.js",
+  "directories": {
+    "doc": "docs"
+  },
+  "scripts": {
+    "test": "cucumber-js",
+    "test-and-report": "npm-run-all -c -s test cucumber-html-report",
+    "cucumber-html-report": "node plugins/reporter.js",
+    "cucumber-docs": "jsdoc ./stepDefinitions  -c plugins/jsdoc_config.json --readme plugins/README.md"
+  },
+  "author": "",
+  "license": "SEE LICENSE IN LICENSE.TXT",
+  "dependencies": {
+    "assert": "^1.4.1",
+    "cucumber": "^3.2.1",
+    "cucumber-html-reporter": "^3.0.4",
+    "docdash": "^0.4.0",
+    "jsdoc": "^3.5.5",
+    "jsdoc-one-page": "0.0.5",
+    "lodash": "^4.17.4",
+    "node-zip": "^1.1.1",
+    "normalize-newline": "^3.0.0",
+    "npm-run-all": "^4.1.2",
+    "request": "^2.83.0",
+    "yamljs": "^0.3.0"
+  }
+}
diff --git a/workflow-bdd/plugins/README.md b/workflow-bdd/plugins/README.md
new file mode 100644 (file)
index 0000000..956fe77
--- /dev/null
@@ -0,0 +1,23 @@
+<br>
+<h1>Welcome!</h1>
+This is the documentation for using the BDD testing framework for SDC.<br>
+The Modules on the left contains all steps for particalar aress and/or explanations of what they do.<br>
+<br><br>
+<h3>How to set the server configuration</h3>
+<li> Copy the config.json to devConfig.json
+<li> Replace the server and user values with the correct values
+<h3>How to run with Maven</h3>
+<li>"mvn install" will install npm if needed, download all modules and create the documentation under the "docs" folder
+<li>"mvn test-and-report" will run all  tests in the features folder and create an HTML report under the "reports" folder
+<h3>How to develop tests</h3>
+You can open the project in IntelliJ and Webstorm to run and develop scenarios.<br>
+<li><b>You will need to install the Cucumber.Js plugin</b> In order to install, go to "Settings/Plugins". If cucumber.js in not on the list, go to "Browse repositories.." and install .
+<li>First time only: Right click on feature file and try to run. Now go to "Run/edit configurations" and set the "executable path" to the "node_modules\.bin\cucumber-js.cmd" under your current project.
+<li>Now you can run the feature files by right clicking on the file and selecting "Run" from IDEA.<br>
+<li>Add to existing scenarios or create new files under the "features" directory for additional tests
+<br>
+<li>You can also run a specific test from the command line by running "npm run test -- [features/path to file]
+<h3>More Information</h3>
+<li> More on <a href="https://cucumber.io/docs/reference">Cucumber</a>
+<li> More on <a herf="https://github.com/cucumber/cucumber/wiki/Gherkin">Gherkin</a>
+<li> More on <a href="https://github.com/cucumber/cucumber-js">Cucumber-js</a>
diff --git a/workflow-bdd/plugins/jsdoc_config.json b/workflow-bdd/plugins/jsdoc_config.json
new file mode 100644 (file)
index 0000000..a5a608e
--- /dev/null
@@ -0,0 +1,15 @@
+{
+  "tags": {
+    "allowUnknownTags": true
+  },
+  "templates": {
+    "default": {
+      "outputSourceFiles": false
+    }
+  },
+  "plugins": ["plugins/steps"],
+  "opts": {
+    "template": "node_modules/jsdoc-one-page",
+    "destination": "docs/"
+  }
+}
\ No newline at end of file
diff --git a/workflow-bdd/plugins/reporter.js b/workflow-bdd/plugins/reporter.js
new file mode 100644 (file)
index 0000000..8913789
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright © 2016-2017 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+var reporter = require('cucumber-html-reporter');
+
+var options = {
+       theme: 'bootstrap',
+       jsonFile: 'report/report.json',
+       output: 'report/report.html',
+       reportSuiteAsScenarios: true,
+       launchReport: false,
+       metadata: {
+               "ONAP" : "Some build",
+               "Executed": "Local"
+       }
+};
+
+reporter.generate(options);
+
diff --git a/workflow-bdd/plugins/steps.js b/workflow-bdd/plugins/steps.js
new file mode 100644 (file)
index 0000000..2faa7ef
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright © 2016-2017 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @module plugins/steptag
+ */
+'use strict';
+
+
+exports.handlers = {
+       /**
+        * Support @step tag.
+        *
+        * @step description
+        */
+       newDoclet: function(e) {
+               var tags = e.doclet.tags;
+               var tag;
+               var value;
+
+               // any user-defined tags in this doclet?
+               if (typeof tags !== 'undefined') {
+
+                       tags = tags.filter(function($) {
+                               return $.title === 'step' || $.title === 'examplefile';
+                       });
+
+                       if (tags.length) {
+                               // take the first one
+                               tag = tags[0];
+                               let step = null;
+                               let exampleFile = null;
+                               for (tag in tags) {
+                                       if (tags[tag].title === "step") {
+                                               step = "<b>" + tags[tag].value + "</b><br>";
+                                       }
+                                       if (tags[tag].title === "examplefile") {
+                                               exampleFile = "<i> Example Features File: " + tags[tag].value + "</i><br>";
+                                       }
+                               }
+                               if (exampleFile !== null) {
+                                       step += exampleFile;
+                               }
+                               e.doclet.meta = e.doclet.meta || {};
+                               if (e.doclet.description !== undefined) {
+                                       e.doclet.description =  step +  e.doclet.description;
+                               } else {
+                                       e.doclet.description =  step;
+                               }
+                       }
+               }
+       }
+};
\ No newline at end of file
diff --git a/workflow-bdd/pom.xml b/workflow-bdd/pom.xml
new file mode 100644 (file)
index 0000000..111fe39
--- /dev/null
@@ -0,0 +1,173 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.openecomp.sdc</groupId>
+    <artifactId>workflow-cucumber</artifactId>
+    <name>cucumber-report</name>
+    <version>1.2.0-SNAPSHOT</version>
+
+    <parent>
+        <groupId>org.onap.sdc.sdc-workflow-designer</groupId>
+        <artifactId>sdc-workflow-designer</artifactId>
+        <version>1.2.0-SNAPSHOT</version>
+           </parent>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-clean-plugin</artifactId>
+                <version>2.6.1</version>
+                <executions>
+                    <execution>
+                        <id>clean.dist.folder</id>
+                        <phase>clean</phase>
+                        <goals>
+                            <goal>clean</goal>
+                        </goals>
+                        <configuration>
+                            <filesets>
+                                <fileset>
+                                    <directory>${basedir}/report</directory>
+                                    <includes>
+                                        <include>**/*</include>
+                                    </includes>
+                                </fileset>
+                                <fileset>
+                                    <directory>${basedir}/resources/downloads</directory>
+                                    <includes>
+                                        <include>**/*</include>
+                                    </includes>
+                                </fileset>
+                              <fileset>
+                                <directory>${basedir}/docs</directory>
+                                <includes>
+                                  <include>**/*</include>
+                                </includes>
+                              </fileset>
+                                <fileset>
+                                    <directory>${basedir}</directory>
+                                    <includes>
+                                        <include>jenkinsConfig.json</include>
+                                    </includes>
+                                </fileset>
+
+                            </filesets>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+
+            <plugin>
+                <artifactId>maven-antrun-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>create-reporting-folders</id>
+                        <phase>generate-sources</phase>
+                        <configuration>
+                            <tasks>
+                                <echo message="Generate reports and downloads folders"/>
+                                <mkdir dir="${basedir}/report"/>
+                                <mkdir dir="${basedir}/resources/downloads"/>
+                            </tasks>
+                        </configuration>
+                        <goals>
+                            <goal>run</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <!-- ============================================= -->
+            <!-- Build the UI module node code -->
+            <!-- ============================================= -->
+            <plugin>
+                <groupId>com.github.eirslett</groupId>
+                <artifactId>frontend-maven-plugin</artifactId>
+                <version>1.6</version>
+
+                <configuration>
+                    <installDirectory>${project.parent.parent.basedir}</installDirectory>
+                </configuration>
+
+                <executions>
+
+                    <execution>
+                        <id>install node and yarn</id>
+                        <goals>
+                            <goal>install-node-and-yarn</goal>
+                        </goals>
+                        <configuration>
+                            <nodeVersion>v9.4.0</nodeVersion>
+                            <yarnVersion>v1.3.2</yarnVersion>
+                        </configuration>
+                    </execution>
+
+                    <execution>
+                        <id>yarn run install</id>
+                        <goals>
+                            <goal>yarn</goal>
+                        </goals>
+                        <configuration>
+                            <arguments>install</arguments>
+                        </configuration>
+                    </execution>
+                  <execution>
+                    <id>yarn run cucumber docs</id>
+                    <goals>
+                      <goal>yarn</goal>
+                    </goals>
+                    <configuration>
+                        <yarnInheritsProxyConfigFromMaven>false</yarnInheritsProxyConfigFromMaven>
+                      <arguments>run cucumber-docs</arguments>
+                    </configuration>
+                  </execution>
+
+                  <execution>
+                    <id>yarn run cucumber test</id>
+                    <goals>
+                      <goal>yarn</goal>
+                    </goals>
+                    <configuration>
+                        <yarnInheritsProxyConfigFromMaven>false</yarnInheritsProxyConfigFromMaven>
+                      <arguments>run test-and-report</arguments>
+                    </configuration>
+                    <phase>test</phase>
+                  </execution>
+
+
+                </executions>
+            </plugin>
+
+            <plugin>
+                <artifactId>maven-resources-plugin</artifactId>
+                <version>2.6</version>
+                <executions>
+                    <execution>
+                        <id>copy-config</id>
+                        <phase>validate</phase>
+                        <goals>
+                            <goal>copy-resources</goal>
+                        </goals>
+                        <configuration>
+                            <outputDirectory>${basedir}</outputDirectory>
+                            <resources>
+                                <resource>
+                                    <directory>${basedir}/resources</directory>
+                                    <includes>
+                                        <include>jenkinsConfig.json</include>
+                                    </includes>
+                                    <filtering>true</filtering>
+                                </resource>
+                            </resources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+
+        </plugins>
+    </build>
+
+</project>
diff --git a/workflow-bdd/resources/json/createVLM.json b/workflow-bdd/resources/json/createVLM.json
new file mode 100644 (file)
index 0000000..9431c07
--- /dev/null
@@ -0,0 +1 @@
+{"vendorName":"RANDOM","description":"VLM Description","iconRef":"icon"}
diff --git a/workflow-bdd/resources/json/createVSP.json b/workflow-bdd/resources/json/createVSP.json
new file mode 100644 (file)
index 0000000..6f63261
--- /dev/null
@@ -0,0 +1,11 @@
+{
+        "vendorId":"REPLACE",
+        "name": "RANDOM",
+        "category":"resourceNewCategory.generic",
+        "subCategory":"resourceNewCategory.generic.abstract",
+        "onboardingMethod":"REPLACE",
+        "description":"for testing",
+        "vendorName":"REPLACE",
+        "icon":"icon",
+        "licensingData":{}
+}
diff --git a/workflow-bdd/stepDefinitions/Collaboration_Steps.js b/workflow-bdd/stepDefinitions/Collaboration_Steps.js
new file mode 100644 (file)
index 0000000..c4de758
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright © 2016-2017 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+const {Then, When, Given} = require('cucumber');
+const assert = require('assert');
+const util = require('./Utils.js');
+
+/**
+ * @module Collaboration
+ * @description Adds the user with the given user ID as a contributor on the item
+ * @exampleFile Example_Collaboration.feature
+ * @step I want to add user {string} as a contributor to this Item
+ **/
+When('I want to add user {string} as a contributor to this Item', function(string)  {
+       let path = '/items/' + this.context.item.id + '/permissions/Contributor';
+       let inputData = {removedUsersIds:[],addedUsersIds:[string]};
+       return util.request(this.context, 'PUT', path, inputData);
+});
+
+/**
+ * @module Collaboration
+ * @description Adds the user with the given user ID as a contributor on the item
+ * @exampleFile Example_Collaboration.feature
+ * @step I want to remove user {string} as a contributor to this Item
+ **/
+When('I want to remove user {string} as a contributor to this Item', function(string)  {
+       let path = '/items/' + this.context.item.id + '/permissions/Contributor';
+       let inputData = {removedUsersIds:[string],addedUsersIds:[]};
+       return util.request(this.context, 'PUT', path, inputData);
+});
+
+/**
+ * @module Collaboration
+ * @description Changes the owner to the given User ID
+ * @exampleFile Example_Collaboration.feature
+ * @step I want to change the owner to user {string} on this Item
+ **/
+When('I want to change the owner to user {string} on this Item', function(string)  {
+       let path = '/items/' + this.context.item.id + '/permissions/Owner';
+       let inputData = {removedUsersIds:[],addedUsersIds:[string]};
+       return util.request(this.context, 'PUT', path, inputData);
+});
+
+
+/**
+ * @module Collaboration
+ * @description Checks the role for a user on the item by User id and Role can be either: Contributor/Owner
+ * @exampleFile Example_Collaboration.feature
+ * @step I want check user {string} has role {string} on this Item
+ **/
+When('I want to check user {string} has role {string} on this Item', function(string, string2)  {
+       let path = '/items/' + this.context.item.id + '/permissions';
+       return util.request(this.context, 'GET', path).then(results => {
+               for (i in results.data.results) {
+                       if (results.data.results[i].userId === string) {
+                               assert.equal(string2.toLowerCase(), results.data.results[i].permission.toLowerCase());
+                               return;
+                       }
+               }
+               assert.fail('User not found');
+       });
+});
+
+/**
+ * @module Collaboration
+ * @description Checks the user wth this Id has no permissions on this item
+ * @exampleFile Example_Collaboration.feature
+ * @step I want check user {string} has rno permissions on this Item
+ **/
+When('I want to check user {string} has no permissions on this Item', function(string)  {
+       let path = '/items/' + this.context.item.id + '/permissions';
+       return util.request(this.context, 'GET', path).then(results => {
+               for (i in results.data.results) {
+                       if (results.data.results[i].userId === string) {
+                               assert.fail('Found', null, 'User should not have permissions');
+                               return;
+                       }
+               }
+       });
+});
+
+/**
+ * @module Collaboration
+ * @description Gets the permissions for the Item
+ * @exampleFile Example_Collaboration.feature
+ * @step I want to get the permissions for this Item
+ **/
+When('I want to get the permissions for this Item', function()  {
+       let path = '/items/' + this.context.item.id + '/permissions';
+       return util.request(this.context, 'GET', path);
+});
+
+/**
+ * @module Collaboration
+ * @description Changes the user for the Rest calls
+ * @exampleFile Example_Collaboration.feature
+ * @step I want to set the user to {string}
+ **/
+When('I want to set the user to {string}', function(string)  {
+       this.context.headers['onboarding'].USER_ID = string;
+});
diff --git a/workflow-bdd/stepDefinitions/General_Steps.js b/workflow-bdd/stepDefinitions/General_Steps.js
new file mode 100644 (file)
index 0000000..448c97f
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+ * Copyright © 2016-2017 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+const {Then, When, Given} = require('cucumber');
+const assert = require('assert');
+const _ = require('lodash');
+const normalizeNewline = require('normalize-newline');
+require('node-zip');
+YAML = require('yamljs');
+const fs = require('fs');
+const util = require('./Utils.js');
+
+function getPath(path, context) {
+       let compiled = _.template(path);
+       return compiled(context);
+}
+
+/**
+ * @module ContextData
+ * @description  Use with "Given". Use ONLY for local testing when you know the value of the Item you want to use
+ * instead of creating a new one.
+ * @step Item {string} and version Id {string}
+ **/
+Given('Item {string} and version Id {string}', function (string, string2) {
+       this.context.item.id = string;
+       this.context.item.versionId = string2;
+});
+/**
+ * @module ContextData
+ * @exampleFile Example_ResponseData_CheckAndManipulation.feature
+ * @description Response Data::<br>
+ *     """<br>
+ *         {jsonObject}<br>
+ *             """<br>
+ * @step  Use with "Given". Use ONLY for local testing, creates a response data object
+ **/
+Given('Response Data:', function (docString) {
+       this.context.responseData = JSON.parse(docString);
+});
+
+/**
+ * @module ContextData
+ * @description Copy a property from the response data to context Item/VLM/VSP data, example: vsp.componentId
+ * @step I want to save on the context for {string} property {string} with value {string}
+ **/
+Then('I want to save on the context for {string} property {string} with value {string}', function(string, string1, string2)  {
+       assert.equal(_.includes(['VLM', 'VSP', 'Item'], string), true);
+       let val = _.get(this.context.responseData, string2);
+       _.set(this.context, string1, val);
+});
+/**
+ * @module ContextData
+ * @description Copy a property from the response data to saved data on the context. Example: save newly generated IDs. Response data value can be from a path, xample: results[0].id
+ * @exampleFile Example_Rest_Calls.feature
+ * @step I want to save to property {string} from response data path {string}
+ **/
+Then('I want to copy to property {string} from response data path {string}', function(string, string2)  {
+       let val = _.get(this.context.responseData, string2);
+       _.set(this.context, string, val);
+});
+/**
+ * @module ContextData
+ * @description This will set the value of a saved property on the context
+ * @exampleFile Example_Rest_Calls.feature
+ * @step I want to set property {string} to value {string}
+ **/
+Then('I want to set property {string} to value {string}', function(string, string2)  {
+       _.set(this.context, string, string2);
+});
+
+/**
+ * @module ResponseData
+ * @description Will check the output data for a property and a value. property can be a path (example: results[0].id)
+ * @exampleFile Example_ResponseData_CheckAndManipulation.feature
+ * @step I want to check property {string} for value {string}
+ **/
+Then('I want to check property {string} for value {string}', function(string, string2)  {
+       assert.equal(_.get(this.context.responseData, string), string2);
+});
+/**
+ * @module ResponseData
+ * @description Will check the output data for a property and a value. property can be a path
+ * (example: results[0].id). Supports comparison to a long String by allowing a line break
+ * @exampleFile VirtualMachineInterfaceValidationHeatResourceMissingProperties.feature
+ * @step I want to check property {string} for value {string}
+ **/
+
+Then('I want to check property {string} for value:', function(string, docString)  {
+       assert.equal(_.get(this.context.responseData, string), docString.trim());
+});
+/**
+ * @module ResponseData
+ * @description Will check the output data for a property and a integer. property can be a path (example: results[0].id)
+ * @exampleFile Example_ResponseData_CheckAndManipulation.feature
+ * @step I want to check property {string} for value {int}
+ **/
+Then('I want to check property {string} for value {int}', function(string, int)  {
+       assert.equal(_.get(this.context.responseData, string), int);
+});
+/**
+ * @module ResponseData
+ * @description Will check the output data for a property and a boolean. property can be a path (example: results[0].id)
+ * @exampleFile Example_ResponseData_CheckAndManipulation.feature
+ * @step I want to check property {string} to be "True/False"
+ **/
+Then('I want to check property {string} to be {word}', function(string, string2)  {
+    assert.equal(_.get(this.context.responseData, string), string2.toLowerCase() == "true");
+});
+/**
+ * @module ResponseData
+ * @description Will check the output data for a property and a boolean. property can be a path (example: results[0].id)
+ * @exampleFile Example_ResponseData_CheckAndManipulation.feature
+ * @step I want to check property {string} to have length {int}
+ **/
+Then('I want to check property {string} to have length {int}', function(string, intLength)  {
+       let arrayProp = _.get(this.context.responseData, string);
+       assert.equal(arrayProp.length, intLength);
+});
+/**
+ * @module ResponseData
+ * @description Will check the output data for a property and make sure it exists
+ * @exampleFile Example_ResponseData_CheckAndManipulation.feature
+ * @step I want to check property {string} exists
+ **/
+Then('I want to check property {string} exists', function(string)  {
+       assert.equal(_.has(this.context.responseData, string), true);
+});
+/**
+ * @module ResponseData
+ * @description Will check the output data for a property and make sure it does not exist
+ * @exampleFile Example_ResponseData_CheckAndManipulation.feature
+ * @step I want to check property {string} does not exist
+ **/
+Then('I want to check property {string} does not exist', function(string)  {
+       assert.equal(_.has(this.context.responseData, string), false);
+});
+
+/**
+* @module ContextData
+* @description Use during development to see what is on the context
+ * @exampleFile Example_ResponseData_CheckAndManipulation.feature
+* @step I want to print context data
+**/
+Then('I want to print the context data', function()  {
+       console.log('------------ context ---------------');
+       console.log(JSON.stringify(this.context, null, 2));
+       console.log('--------------------------------------');
+});
+/**
+ * @module ContextData
+ * @description Set this in order to check that the following Rest call will not have response code 200
+ * @exampleFile Example_Rest_Calls.feature
+ * @step I want the following to fail
+ **/
+Then('I want the following to fail', function()  {
+       this.context.shouldFail = true;
+});
+
+/**
+ * @module ContextData
+ * @description Set this in order to check that the following Rest call will have the error code on the return data
+ * @exampleFile Example_VSP.feature
+ * @step I want the following to fail with error code {string}
+ **/
+Then('I want the following to fail with error code {string}', function(string)  {
+       this.context.shouldFail = true;
+       this.context.errorCode = string;
+});
+
+
+/**
+ * @module ContextData
+ * @description Set this in order to check that the following Rest call will have the error message on the return data
+ * @exampleFile DeleteVLMCertified.feature
+ * @step I want the following to fail with error message {string}
+ **/
+Then('I want the following to fail with error message {string}', function(string)  {
+       this.context.shouldFail = true;
+       let errorMessage = getPath(string, this.context);
+       this.context.errorMessage = errorMessage;
+});
+
+/**
+ * @module ZipData
+ * @description Use this in order to extract a file from a zip file and to compare it to a local file (string comparison).
+ * @exampleFile Example_VSP.feature
+ * @step I want to compare the content of the entry {string} in the zip {string} with file {string}
+ **/
+Then ('I want to compare the content of the entry {string} in the zip {string} with file {string}', function (string, string2, string3) {
+       let zipFile = fs.readFileSync(string2, 'binary');
+       let zip = new JSZip(zipFile, {base64: false, checkCRC32: true});
+       let fileData = zip.files[string]._data;
+       let compareFileData = fs.readFileSync(string3, {encoding: 'ascii'});
+       assert.equal(normalizeNewline(compareFileData), normalizeNewline(fileData));
+});
+
+/**
+ * @module ZipData
+ * @description Loads the yaml from zip file onto the context responseData as JSON for running checks on the output
+ * @exampleFile Example_VSP.feature
+ * @step I want to load the yaml content of the entry {string} in the zip {string} to context
+ **/
+Then ('I want to load the yaml content of the entry {string} in the zip {string} to context', function (string, string2, callback) {
+       let zipFile = fs.readFileSync(string2, 'binary');
+       let zip = new JSZip(zipFile, {base64: false, checkCRC32: true});
+       let fileData = zip.files[string]._data;
+       let nativeObject = YAML.parse(fileData);
+       this.context.responseData = nativeObject;
+       callback();
+});
+
+
+/**
+ * @module ZipData
+ * @description Loads the json from zip file onto the context responseData for running check son the output
+ * @exampleFile Example_VSP.feature
+ * @step I want to load the json content of the entry {string} in the zip {string} to context
+ **/
+When('I want to load the json content of the entry {string} in the zip {string} to context', function (string, string2, callback) {
+       let zipFile = fs.readFileSync(string2, 'binary');
+       let zip = new JSZip(zipFile, {base64: false, checkCRC32: true});
+       let str = zip.files[string]._data;
+       this.context.responseData = JSON.parse(str);
+       callback();
+});
+
+/**
+ * @module ResponseData
+ * @description Check that the result list doesn't contain an element with property x which has value
+ * equals to saved property y
+ * @exampleFile ListItemsFilters.feature
+ * @step I want to check that element in the response list with {string} equals to value of saved property {string} does not exist
+ **/
+Then('I want to check that element in the response list with {string} equals to value of saved property {string} does not exist', function (propertyPath, valueProperty) {
+    const results = this.context.responseData.results;
+    assert.equal(results.find(result => this.context[valueProperty] === _.get(result, propertyPath)), undefined);
+});
+
+/**
+ * @module ResponseData
+ * @description Check that the result list contains an element with property x which has value
+ * equals to saved property y
+ * @exampleFile ListItemsFilters.feature
+ * @step I want to check that element in the response list with {string} equals to value of saved property {string} exists
+ **/
+Then('I want to check that element in the response list with {string} equals to value of saved property {string} exists', function(propertyPath, valueProperty) {
+    const results = this.context.responseData.results;
+    assert.notEqual(results.find(result => this.context[valueProperty] === _.get(result, propertyPath)), undefined);
+});
+
+
+Then('I want to check that property {string} in the response equals to value of saved property {string}', function(propertyPath, valueProperty) {
+    const results = this.context.responseData;
+    assert.equal(results[propertyPath],this.context[valueProperty]);
+});
+
+/**
+ * @module ResponseData
+ * @description Check that the itemId from context exits in result of responseData
+ * exampleFile ArchiveItem.feature
+ * step I want to check that item exits in response
+ **/
+Then('I want to check that item exits in response', function() {
+
+  const id = this.context.item.id;
+  const results = this.context.responseData.results;
+  var testResult = false;
+
+  for(var i=0; i< results.length; i++){
+     if ( id == results[i].id){
+            testResult = true;
+     }
+  }
+
+   assert.equal(testResult,true);
+});
+
+
+/**
+ * @module ResponseData
+ * @description Check that the itemId from context does NOT exits in result of responseData
+ * exampleFile ArchiveItem.feature
+ * step I want to check that item does not exits in response
+ **/
+Then('I want to check that item does not exits in response', function() {
+
+  const id = this.context.item.id;
+  const results = this.context.responseData.results;
+  var testResult = false;
+
+  for(var i=0; i< results.length; i++){
+     if ( id == results[i].id){
+            testResult = true;
+     }
+  }
+
+   assert.equal(testResult,false);
+});
\ No newline at end of file
diff --git a/workflow-bdd/stepDefinitions/InputData_steps.js b/workflow-bdd/stepDefinitions/InputData_steps.js
new file mode 100644 (file)
index 0000000..73695d0
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright © 2016-2017 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+const {Then, When, Given} = require('cucumber');
+const assert = require('assert');
+const _ = require('lodash');
+const fs = require('fs');
+const util = require('./Utils.js');
+
+/**
+ * @module InputData
+ * @description creates an ampty input data object
+ * @exampleFile Example_Rest_Calls.feature, Example_VLM.feature
+ * @step I want to create input data
+ **/
+When('I want to create input data', function () {
+       this.context.inputData = {};
+});
+
+/**
+ * @module InputData
+ * @exampleFile Example_Heat.feature
+ * @description I want to set the input data to:<br>
+ *     """<br>
+ *         {jsonObject}<br>
+ *             """<br>
+ * @step creates an input data element with the given json object
+ **/
+When('I want to set the input data to:', function (docString) {
+       this.context.inputData = JSON.parse(docString);
+});
+
+/**
+ * @module InputData
+ * @description creates an input data object from the json in the given file
+ * @exampleFile Example_Rest_Calls.feature
+ * @step I want to set the input data to file {string}
+ **/
+When('I want to set the input data to file {string}', function (string) {
+       this.context.inputData = util.getJSONFromFile(string);
+});
+
+/**
+ * @module InputData
+ * @description sets the property on the input data to the given value
+ * @exampleFile Example_Rest_Calls.feature, Example_VLM.feature
+ * @step I want to update the input property {string} with value {string}
+ **/
+Then('I want to update the input property {string} with value {string}', function(string, string2)  {
+       _.set(this.context.inputData, string, string2);
+});
+
+/**
+ * @module InputData
+ * @description removes a property from the input data object
+ * @exampleFile Example_Rest_Calls.feature
+ * @step I want to remove {string} from the input data
+ **/
+Then('I want to remove {string} from the input data', function(string)  {
+       delete this.context.inputData[string];
+});
+
+/**
+ * @module InputData
+ * @description sets the input data property to a random value
+ * @exampleFile Example_Rest_Calls.feature
+ * @step I want to update the input property {string} with a random value
+ **/
+Then('I want to update the input property {string} with a random value', function(string)  {
+       _.set(this.context.inputData, string, util.random());
+});
diff --git a/workflow-bdd/stepDefinitions/InterfaceOperationSteps.js b/workflow-bdd/stepDefinitions/InterfaceOperationSteps.js
new file mode 100644 (file)
index 0000000..4c00deb
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * Copyright © 2016-2017 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+const {Then, When} = require('cucumber');
+const assert = require('assert');
+const util = require('./Utils.js');
+
+
+When('I want to create a VF', function()  {
+    let inputData = util.getJSONFromFile('resources/json/operation/createVF_From_Catalog.json');
+
+    inputData.name =  util.random();
+    inputData.tags[0] = util.random();
+
+    let path = '/catalog/resources';
+    return util.request(this.context, 'POST', path,  inputData, false, 'vf').then(result => {
+        this.context.item = {uniqueId : result.data.uniqueId, id : result.data.inputs[0].uniqueId, name : result.data.inputs[0].name};
+        this.context.vf = {uniqueId : result.data.uniqueId, id : result.data.inputs[0].uniqueId, name : result.data.inputs[0].name};
+});
+});
+
+function makeType() {
+    var text = "";
+    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+    for (var i = 0; i < 5; i++)
+        text += possible.charAt(Math.floor(Math.random() * possible.length));
+
+    return text;
+}
+
+When('I want to create an Operation', function()  {
+    let inputData = util.getJSONFromFile('resources/json/operation/createOperation.json');
+    //let path = '/catalog/resources/f3dc81bb-85e9-4dfd-bd1b-37f5dc5e5534/interfaceOperations';
+    let path = '/catalog/resources/' + this.context.vf.uniqueId +'/interfaceOperations';
+
+    inputData.interfaceOperations.create.operationType = makeType();
+    inputData.interfaceOperations.create.inputParams.listToscaDataDefinition[0].paramName = util.random();
+    inputData.interfaceOperations.create.inputParams.listToscaDataDefinition[0].paramId = this.context.vf.id;
+
+    return util.request(this.context, 'POST', path, inputData, false, 'vf').then(result => {
+    this.context.item = {uniqueId : result.data.uniqueId, operationType : result.data.operationType};
+    this.context.operation = {uniqueId : result.data.uniqueId, operationType : result.data.operationType};
+});
+});
+
+
+
+When('I want to list Operations', function () {
+    let path = '/catalog/resources/' + this.context.vf.uniqueId + '/filteredDataByParams?include=interfaces';
+    return util.request(this.context, 'GET', path, null, false, 'vf').then((result)=> {
+});
+});
+
+
+When('I want to get an Operation by Id', function () {
+    let path = '/catalog/resources/' + this.context.vf.uniqueId + '/interfaceOperations/' + this.context.operation.uniqueId;
+    return util.request(this.context, 'GET', path, null, false, 'vf').then((result)=> {
+        this.context.item ={uniqueId : result.data.uniqueId, operationType: result.data.operationType};
+        this.context.operation = {uniqueId : result.data.uniqueId, operationType : result.data.operationType};
+});
+});
+
+
+When('I want to update an Operation', function () {
+    let inputData = util.getJSONFromFile('resources/json/operation/updateOperation.json');
+    let path = '/catalog/resources/' + this.context.vf.uniqueId + '/interfaceOperations/';
+    inputData.interfaceOperations.create.uniqueId = this.context.operation.uniqueId;
+    inputData.interfaceOperations.create.operationType = this.context.operation.operationType;
+    inputData.interfaceOperations.create.inputParams.listToscaDataDefinition[0].paramName = util.random();
+    inputData.interfaceOperations.create.inputParams.listToscaDataDefinition[0].paramId = this.context.vf.id;
+    return util.request(this.context, 'PUT', path, inputData, false, 'vf').then((result)=> {
+        this.context.item ={uniqueId : result.data.uniqueId, operationType: result.data.operationType};
+        this.context.operation = {uniqueId : result.data.uniqueId, operationType : result.data.operationType};
+});
+});
+
+
+When('I want to delete an Operation', function()  {
+    let path = '/catalog/resources/' + this.context.vf.uniqueId + '/interfaceOperations/' + this.context.operation.uniqueId;
+    return util.request(this.context, 'DELETE', path, null, false, 'vf');
+});
+
+
+When('I want to checkin this VF', function () {
+    let path = '/catalog/resources/' + this.context.vf.uniqueId + '/lifecycleState/CHECKIN' ;
+    let inputData = {userRemarks: 'checkin'};
+    return util.request(this.context, 'POST', path, inputData, false, 'vf').then((result)=> {
+        this.context.item ={uniqueId : result.data.uniqueId};
+    this.context.vf = {uniqueId : result.data.uniqueId};
+});
+});
+
+
+Then('I want to submit this VF', function () {
+    let path = '/catalog/resources/' + this.context.vf.uniqueId + '/lifecycleState/certificationRequest' ;
+    let inputData = {userRemarks: 'submit'};
+    return util.request(this.context, 'POST', path, inputData, false, 'vf').then((result)=> {
+        this.context.item ={uniqueId : result.data.uniqueId};
+    this.context.vf = {uniqueId : result.data.uniqueId};
+});
+});
+
+
+
+
diff --git a/workflow-bdd/stepDefinitions/Item_steps.js b/workflow-bdd/stepDefinitions/Item_steps.js
new file mode 100644 (file)
index 0000000..3ff7f20
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright © 2016-2017 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+const {Then, When} = require('cucumber');
+const assert = require('assert');
+const util = require('./Utils.js');
+/**
+ * @module Item
+ * @description uses item id and version id from context
+ * @exampleFile Example_VSP.feature, Example_VLM.feature
+ * @step I want to make sure this Item has status {string}
+ **/
+Then('I want to make sure this Item has status {string}', function (string) {
+       let path = '/items/' + this.context.item.id + '/versions';
+       return util.request(this.context, 'GET', path).then(result => {
+               assert.equal(result.data.results[0].id, this.context.item.versionId);
+               assert.equal(result.data.results[0].status, string);
+       });
+});
+/**
+ * @module Item
+ * @description uses item id and version id from context
+ * @exampleFile Example_VSP.feature, Example_VLM.feature
+ * @step I want to commit this Item
+ **/
+Then('I want to commit this Item', function () {
+       let path = '/items/' + this.context.item.id + '/versions/' + this.context.item.versionId + '/actions';
+       let inputData = {action: 'Commit', commitRequest: {message: '00Behave'}};
+       return util.request(this.context, 'PUT', path, inputData);
+});
+/**
+ * @module Item
+ * @description creates a new major version. item id and version id from context
+ * @exampleFile Example_VLM.feature
+ * @step I want to create a new version for this Item
+ **/
+Then('I want to create a new version for this Item', function () {
+       let path = '/items/' + this.context.item.id + '/versions/' + this.context.item.versionId;
+       let inputData = {description: 'Behave Version', creationMethod: 'major'};
+       return util.request(this.context, 'POST', path, inputData).then(result => {
+               assert.equal(result.data.status, 'Draft');
+       });
+});
+/**
+ * @module Item
+ * @description reverts to a revision with a given saved property. Should be set from the revision list first
+ * @exampleFile Example_VLM.feature
+ * @step I want to commit this Item
+ **/
+Then('I want to revert this Item to the revision with the value from saved property {string}', function (string) {
+       let path = '/items/' + this.context.item.id + '/versions/' + this.context.item.versionId + '/actions';
+       let inputData = {action: 'Revert', revisionRequest: {revisionId: this.context[string]}};
+       return util.request(this.context, 'PUT', path, inputData);
+});
+
+
+/**
+ * @module Item
+ * @exampleFile ArchiveItem.feature
+ * @step I want to archive this item
+ **/
+Then('I want to archive this item', function()  {
+    let path = '/items/' + this.context.item.id + '/actions'
+    let inputData = {action: 'ARCHIVE'};
+       return util.request(this.context, 'PUT', path, inputData);
+});
+
+
+/**
+ * @module Item
+ * @exampleFile ArchiveItem.feature
+ * @step I want to restore this item
+ **/
+Then('I want to restore this item', function()  {
+    let path = '/items/' + this.context.item.id + '/actions'
+    let inputData = {action: 'RESTORE'};
+       return util.request(this.context, 'PUT', path, inputData);
+});
+
diff --git a/workflow-bdd/stepDefinitions/REST_Steps.js b/workflow-bdd/stepDefinitions/REST_Steps.js
new file mode 100644 (file)
index 0000000..c384412
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2016-2018 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+const {When} = require('cucumber');
+const _ = require('lodash');
+const util = require('./Utils.js');
+_.templateSettings.interpolate = /{([\s\S]+?)}/g;
+
+function getPath(path, context) {
+       let compiled = _.template(path);
+       return compiled(context);
+}
+/**
+ * @module Rest_Calls
+ * @description makes a GET request to the given path (path is appended after the "onboarding-api/v1.0" prefix)<br>
+ * @exampleFile Example_Rest_Calls.feature
+ * @step I want to get path {string}
+ **/
+When('I want to get path {string}', function(string)  {
+       let path = getPath(string, this.context);
+       return util.request(this.context, 'GET', path);
+});
+
+/**
+ * @module Rest_Calls
+ * @description makes a DELETE request to the given path and appends the saved property (path is appended after the "onboarding-api/v1.0" prefix)<br>
+ * @exampleFile Example_Rest_Calls.feature
+ * @step I want to delete for path {string} with the value from saved property {string}
+ **/
+When('I want to delete for path {string} with the value from saved property {string}', function(string, string2)  {
+       let path = getPath(string, this.context);
+       path += '/' + this.context[string2];
+       return util.request(this.context, 'DELETE', path);
+});
+
+/**
+ * @module Rest_Calls
+ * @description makes a DELETE request to the given path and appends the saved property (path is appended after the "onboarding-api/v1.0" prefix)<br>
+ * @exampleFile Example_Rest_Calls.feature
+ * @step I want to delete for path {string} with the value from saved property {string}
+ **/
+When('I want to delete for path {string}', function (string) {
+    let path = getPath(string, this.context);
+    //path += '/' + this.context[string2];
+    return util.request(this.context, 'DELETE', path);
+});
+
+/**
+ * @module Rest_Calls
+ * @description makes a PUT request to the given path and sends the input data from the context (path is appended after the "onboarding-api/v1.0" prefix)<br>
+ *     @exampleFile Example_Rest_Calls.feature
+ * @step I want to update for path {string} with the input data from the context
+ **/
+When('I want to update for path {string} with the input data from the context', function(string)  {
+       let path = getPath(string, this.context);
+       return util.request(this.context, 'PUT', path, this.context.inputData);
+});
+
+/**
+ * @module Rest_Calls
+ * @description makes a POST request to the given path and sends the input data from the context (path is appended after the "onboarding-api/v1.0" prefix)<br>
+ *     @exampleFile Example_Rest_Calls.feature
+ * @step I want to create for path {string} with the input data from the context
+ **/
+When('I want to create for path {string} with the input data from the context', function(string)  {
+       let path = getPath(string, this.context);
+       return util.request(this.context, 'POST', path, this.context.inputData);
+});
diff --git a/workflow-bdd/stepDefinitions/Utils.js b/workflow-bdd/stepDefinitions/Utils.js
new file mode 100644 (file)
index 0000000..66e959f
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright © 2016-2017 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+const request = require('request');
+const fs = require('fs');
+require('node-zip');
+
+function _request(context, method, path, data, isBinary=false, type='onboarding') {
+       let server = context.getUrlForType(type);
+
+       let options = {
+               method: method,
+               url: server + path,
+               headers: context.headers[type]
+       };
+       console.log('--> Calling REST ' + options.method +' url: ' + options.url);
+
+       return new Promise(function (resolve, reject) {
+               if (method === 'POST' || method === 'PUT') {
+                       if (isBinary) {
+                               var formData = {
+                                       upload: fs.createReadStream(data),
+                               };
+                               options.formData = formData;
+                       } else {
+                               options.json = data;
+                       }
+               }
+               request(options, function (err, result, data) {
+                       context.inputData = null;
+                       if (err) {
+                               console.error('Request URL: ' + result.request.uri.href);
+                               console.error('Request Method: ' + result.request.method);
+                               console.error('Response Status Code: ' +result.statusCode);
+                               console.log(err);
+                               reject(err);
+                       } else {
+                               let isExpected = (context.shouldFail) ? (result.statusCode != 200 && result.statusCode != 201) : (result.statusCode == 200 || result.statusCode == 201);
+                               if (!isExpected) {
+                                       console.error('Request URL: ' + result.request.uri.href);
+                                       console.error('Request Method: ' + result.request.method);
+                                       console.error('Response Status Code: ' +result.statusCode);
+                                       console.error(result.body);
+                                       reject('Status Code was ' + result.statusCode);
+                               }
+                               if (context.shouldFail && context.errorCode) {
+                    if (typeof data === 'string' && data) {
+                        data = JSON.parse(data);
+                    }
+                                       let errorCode = data.errorCode;
+                                       let contextErrorCode = context.errorCode;
+                                       context.errorCode = null;
+                                       if (errorCode !== contextErrorCode) {
+                                               reject('Error Code was ' + errorCode + ' instead of ' + contextErrorCode);
+                                       }
+                               }
+                               if (context.shouldFail && context.errorMessage) {
+                                   if (typeof data === 'string' && data) {
+                        data = JSON.parse(data);
+                    }
+                    let errorMessage = data.message;
+                    let contextErrorMessage = context.errorMessage;
+                    context.errorMessage = null;
+                    if (errorMessage !== contextErrorMessage) {
+                       reject('Error Message was ' + errorMessage + ' instead of ' + contextErrorMessage);
+                    }
+                }
+                               if (context.shouldFail) {
+                                       context.shouldFail = false;
+                                       resolve({statusCode: result.statusCode, data: {}});
+                                       return;
+                               }
+                               if (method === 'GET' && isBinary) {
+                                       // downloading (NetworkPackage) files
+                                       return ({
+                                               blob: blobUtil.createBlob([data], {type: 'text/plain'}),
+                                               headers: result.headers
+                                       });
+                               } else {
+                                       if (typeof data === 'string' && data) {
+                                               data = JSON.parse(data);
+                                       }
+                                       context.responseData = data;
+                                       context.inputData = data;
+                                       resolve({statusCode: result.statusCode, data: data});
+                               }
+                       }
+               });
+       });
+}
+
+function download(context, path, filePath,  callback, type='onboarding') {
+       let server = context.getUrlForType(type);
+       let options = {
+                       method: 'GET',
+                       url: server + path,
+                       headers: context.headers[type]
+               };
+       console.log('--> Calling REST download url: ' + options.url);
+
+       var file = fs.createWriteStream(filePath);
+               var r = request(options).pipe(file);
+               r.on('error', function (err) {
+                       console.log(err);
+                       callback(err);
+               });
+               r.on('finish', function () {
+                       file.close();
+                       let zipFile = fs.readFileSync(filePath, 'binary');
+                       let zip = new JSZip(zipFile, {base64: false, checkCRC32: true});
+                       if (zip.files['MANIFEST.json']) {
+                               let manifestData = zip.files['MANIFEST.json']._data;
+                               manifestData = manifestData.replace(/\\n/g, '');
+                               context.responseData = JSON.parse(manifestData);
+                       }
+                       callback();
+               });
+
+};
+
+function _random() {
+       let d = new Date();
+       return d.getTime().toString().split('').reverse().join('');
+}
+
+function _getJSONFromFile(file) {
+       return JSON.parse(fs.readFileSync(file, 'utf8'));
+}
+
+
+module.exports = {
+       request: _request,
+       random : _random,
+       getJSONFromFile: _getJSONFromFile,
+       download: download
+};
diff --git a/workflow-bdd/stepDefinitions/VLM_steps.js b/workflow-bdd/stepDefinitions/VLM_steps.js
new file mode 100644 (file)
index 0000000..35e78b2
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * Copyright © 2016-2017 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+const {Then, When, Given} = require('cucumber');
+const assert = require('assert');
+const util = require('./Utils.js');
+
+/**
+ * @module VLM
+ * @description Creates a new VLM with a random name and saves the id and versionId on the context item object and the context vlm object<br>
+ *     Input data  will be taken from the 'resources/json/createVLM.json' file.
+ *@exampleFile Example_VLM.feature
+ * @step I want to create a VLM
+ **/
+When('I want to create a VLM', function()  {
+       let inputData = util.getJSONFromFile('resources/json/createVLM.json');
+       inputData.vendorName = util.random();
+       let path = '/vendor-license-models';
+       return util.request(this.context, 'POST', path, inputData).then(result => {
+               this.context.item ={id : result.data.itemId, versionId: result.data.version.id};
+               this.context.vlm = {id : result.data.itemId, name : inputData.vendorName};
+       });
+});
+
+/**
+ * @module VLM
+ * @exampleFile Example_VLM.feature
+ * @step I want to submit this VLM
+ **/
+Then('I want to submit this VLM', function()  {
+       let inputData = {action: 'Submit'};
+       let path = '/vendor-license-models/' + this.context.item.id + '/versions/' + this.context.item.versionId + '/actions';
+       return util.request(this.context, 'PUT', path, inputData);
+});
+
+/**
+ * @module VLM
+ * @exampleFile DeleteVLMDraft.feature
+ * @step I want to delete this VLM
+ **/
+Then('I want to delete this VLM', function()  {
+       let path = '/vendor-license-models/' + this.context.item.id ;
+       return util.request(this.context, 'DELETE', path);
+});
+
+
+/**
+ * @module VLM
+ * @exampleFile ArchiveItem.feature
+ * @step I want to list Archived VLMs
+ **/
+Then('I want to list Archived VLMs', function()  {
+       let path = '/vendor-license-models/?Status=ARCHIVED';
+       return util.request(this.context, 'GET', path);
+});
+
+/**
+ * @module VLM
+ * @exampleFile ArchiveItem.feature
+ * @step I want to list Active VLMs
+ **/
+Then('I want to list Active VLMs', function()  {
+       let path = '/vendor-license-models';
+       return util.request(this.context, 'GET', path);
+});
+
+
diff --git a/workflow-bdd/stepDefinitions/VSP_steps.js b/workflow-bdd/stepDefinitions/VSP_steps.js
new file mode 100644 (file)
index 0000000..1f753fe
--- /dev/null
@@ -0,0 +1,182 @@
+/*
+ * Copyright © 2016-2017 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+const {Then, When} = require('cucumber');
+const assert = require('assert');
+const util = require('./Utils.js');
+const _ = require('lodash');
+
+
+/**
+ * @module VSP
+ * @description Creates a new VSP with a random name and saves the id and versionId on the context item object and the context vsp object<br>
+ *     Input data will be taken from the 'resources/json/createVSP.json' file.
+ *     Vendor id and name are taken from the vlm on the context (requires a VLM to be created first).
+ *     @exampleFile Example_VSP.feature
+ * @step I want to create a VSP with onboarding type {string}
+ **/
+When('I want to create a VSP with onboarding type {string}', function(string)  {
+       let inputData = util.getJSONFromFile('resources/json/createVSP.json');
+       inputData.onboardingMethod = string;
+       inputData.vendorName = this.context.vlm.name;
+       inputData.vendorId = this.context.vlm.id;
+       inputData.name = util.random();
+       let path = '/vendor-software-products';
+       return util.request(this.context, 'POST', path, inputData).then(result => {
+               this.context.item = {id : result.data.itemId, versionId: result.data.version.id};
+               this.context.vsp = {id : result.data.itemId, versionId: result.data.version.id};
+       });
+});
+
+/**
+ * @module VSP
+ * @description Creates a new VSP with the 'NetowrkPackage' onboarding type and with a random name and saves the id and versionId on the context item object and the context vsp object<br>
+ *     Input data will be taken from the 'resources/json/createVSP.json' file.
+ *     Vendor id and name are taken from the vlm on the context (requires a VLM to be created first).
+ *     @exampleFile Example_VSP.feature
+ * @step I want to create a VSP with onboarding type {string}
+ **/
+When('I want to create a VSP', function()  {
+       let inputData = util.getJSONFromFile('resources/json/createVSP.json');
+       inputData.vendorName = this.context.vlm.name;
+       inputData.vendorId = this.context.vlm.id;
+       inputData.name = util.random();
+       let path = '/vendor-software-products';
+       return util.request(this.context, 'POST', path, inputData).then(result => {
+               this.context.item = {id : result.data.itemId, versionId: result.data.version.id};
+               this.context.vsp = {id : result.data.itemId, versionId: result.data.version.id};
+       });
+});
+
+
+/**
+ * @module VSP
+ * @exampleFile Example_VSP.feature
+ * @step I want to submit this VSP
+ **/
+Then('I want to submit this VSP', function () {
+       let path = '/vendor-software-products/' + this.context.item.id + '/versions/' + this.context.item.versionId + '/actions';
+       let inputData = {action: 'Submit'};
+       return util.request(this.context, 'PUT', path, inputData);
+});
+
+/**
+ * @module VSP
+ * @exampleFile Example_VSP.feature
+ * @step I want to package this VSP
+ **/
+Then('I want to package this VSP', function () {
+       let path = '/vendor-software-products/' + this.context.item.id + '/versions/' + this.context.item.versionId + '/actions';
+       let inputData = {action: 'Create_Package'};
+       return util.request(this.context, 'PUT', path, inputData);
+});
+
+/**
+ * @module VSP
+ * @description Adds a component to the current item
+ * @exampleFile Example_VSP.feature
+ * @step I want to add a component
+ **/
+Then('I want to add a component', function () {
+       let path = '/vendor-software-products/' + this.context.item.id + '/versions/' + this.context.item.versionId + '/components';
+       let inputData = {name: 'Cucumber Name', displayName: 'Cucumber', description: 'Cucumber Description'};
+       return util.request(this.context, 'POST', path, inputData).then(result => {
+               this.context.componentId = result.data.vfcId;
+       });
+});
+
+
+/**
+ * @module VSP
+ * @description Downloads the packaged file for this component to the given path
+ * @exampleFile Example_VSP.feature
+ * @step I want to get the package for this Item to path {string}
+ **/
+When('I want to get the package for this Item to path {string}', function (string, callback) {
+       let path =  '/vendor-software-products/packages/' + this.context.item.id;
+       return [util.download(this.context, path, string, callback)];
+});
+
+
+/**
+ * @module VSP
+ * @exampleFile DeleteVSPDraft.feature
+ * @step I want to delete this VSP
+ **/
+Then('I want to delete this VSP', function()  {
+       let path = '/vendor-software-products/' + this.context.item.id ;
+       return util.request(this.context, 'DELETE', path);
+});
+
+/**
+ * @module VSP
+ * @exampleFile ArchiveItem.feature
+ * @step I want to list Archived VSPs
+ **/
+Then('I want to list Archived VSPs', function()  {
+       let path = '/vendor-software-products/?Status=ARCHIVED';
+       return util.request(this.context, 'GET', path);
+});
+
+/**
+ * @module VSP
+ * @exampleFile ArchiveItem.feature
+ * @step I want to list Active VSPs
+ **/
+Then('I want to list Active VSPs', function()  {
+       let path = '/vendor-software-products';
+       return util.request(this.context, 'GET', path);
+});
+
+
+/**
+ * @module VSP
+ * @exampleFile FilterArchivedVSPpackage.feature
+ * @step I want to list Archived VSPs packages
+ **/
+Then('I want to list Archived VSPs packages', function()  {
+       let path = '/vendor-software-products/packages?Status=ARCHIVED';
+       return util.request(this.context, 'GET', path);
+});
+
+/**
+ * @module VSP
+ * @exampleFile FilterArchivedVSPpackage.feature
+ * @step I want to list Active VSPs packages
+ **/
+Then('I want to list Active VSPs packages', function()  {
+       let path = '/vendor-software-products/packages';
+       return util.request(this.context, 'GET', path);
+
+});
+
+/**
+ * @module VSP
+ * @exampleFile FilterArchivedVSPpackage.feature
+ * @step I want to check that VSP package exits in response
+ **/
+Then('I want to check that VSP package exits in response', function()  {
+
+      const packages = this.context.responseData.results;
+      const id = this.context.item.id;
+      var testResult = false;
+
+      for(var i=0; i< packages.length; i++){
+          if (id == packages[i].packageId){
+               testResult = true;
+          }
+      }
+      assert.equal(testResult,true);
+});
\ No newline at end of file
diff --git a/workflow-bdd/stepDefinitions/world.js b/workflow-bdd/stepDefinitions/world.js
new file mode 100644 (file)
index 0000000..4ef0381
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * Copyright © 2016-2017 European Support Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+const { setWorldConstructor } = require('cucumber');
+const _ = require('lodash');
+
+let config = require('../config.json');
+let localConfig = {};
+try {
+       localConfig = require('../devConfig.json');
+} catch (e) {
+       try {
+               localConfig = require('../jenkinsConfig.json');
+       } catch (e) {
+               console.error("no env configuration was found!");
+       }
+}
+
+config = _.merge(config, localConfig);
+var {setDefaultTimeout} = require('cucumber');
+
+
+/**
+ * @module Context
+ * @description Context that is used per feature file and can be accessed as 'this.context' in all steps.<Br>
+ *<Br>
+ * Contains the following items:<br>
+ * <li>this.context.server <ul>REST server and onboarding prefix including version. set either in configuration file or from the command line or SERVER environment variable</ul>
+ * <li>this.context.vlm <ul>When a VLM has been created, this has the an id and versionId set to the correct IDs.</ul>
+ * <li>this.context.vsp <ul>When a VSP has been created, this has the an id and versionId and componentId set to the correct IDs.</ul>
+ * <li>this.context.item <ul>When a VLM or VSP has been created, this has the an id and versionId set to the correct IDs.</ul>
+ * <li>this.context <ul>Object with properties that were saved in the steps.</ul>
+ * <li>this.context.inputdata <ul><b>Automatically updated with the last responseData from the Rest call</b><br>Object with properties that were prepares in the steps.</ul>
+ * <li>this.context.responseData <ul>Response from the last REST call.</ul>
+ **/
+class CustomWorld {
+       constructor(options) {
+               this.context = {};
+               this.context.headers = {};
+               let typeName;
+               for (typeName in config) {
+                       this.context.headers[typeName] = {};
+                       if (config[typeName].user) {
+                               this.context.headers[typeName]['USER_ID'] = config[typeName].user;
+                       }
+               }
+
+               this.context.vlm = {id: null, versionId: null};
+               this.context.vsp = {id: null, versionId: null};
+               this.context.item = {id: null, versionId: null, componentId: null};
+
+               this.context.shouldFail = false;
+               this.context.errorCode = null;
+               this.context.inputData = null;
+               this.context.responseData = null;
+
+               this.context.defaultServerType = 'workflow';
+
+               this.config = config;
+
+               let context = this.context;
+               this.context.getUrlForType = (function(type) {
+                       var _server = context.server;
+                       var _config = config;
+                       return function(type) {
+                               let typeData = _config["workflow"];
+                               let _url = _config.protocol + '://' +
+                                       typeData.server + ':' +
+                                       typeData.port + '/' +
+                                       typeData.prefix;
+                               return _url;
+                       }
+               })();
+
+               setDefaultTimeout(60 * 1000);
+       }
+}
+
+
+setWorldConstructor(CustomWorld);
index d5d9851..aa4bb6f 100644 (file)
@@ -50,6 +50,7 @@ public class WorkflowManagerImpl implements WorkflowManager {
     public void create(Workflow workflow) {
         Item item = workflowMapper.workflowToItem(workflow);
         item.setStatus(ItemStatus.ACTIVE);
+        item.setType(WORKFLOW_TYPE);
 
         uniqueValueService.validateUniqueValue(WORKFLOW_NAME_UNIQUE_TYPE, new String[]{workflow.getName()});
         workflow.setId(itemManager.create(item).getId());
@@ -69,7 +70,7 @@ public class WorkflowManagerImpl implements WorkflowManager {
         item.setId(workflow.getId());
         item.setStatus(retrievedItem.getStatus());
         item.setVersionStatusCounters(retrievedItem.getVersionStatusCounters());
-
+        item.setType(retrievedItem.getType());
         itemManager.update(item);
     }
 }