You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openwhisk.apache.org by cs...@apache.org on 2017/09/18 14:55:28 UTC

[incubator-openwhisk-cli] branch master updated (083cbe1 -> 2fc6865)

This is an automated email from the ASF dual-hosted git repository.

csantanapr pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git.


    from 083cbe1  Pull the openwhisk image instead of building it
     new 0eafc9b  CLI User Agent Header (#2591)
     new 8556b55  Correct unable to set apihost issue.
     new 326ffdb  Clarify WSK_CONFIG_FILE empty string behavior (#2357)
     new 1d97cc6  Add activation logs strip option. (#2620)
     new 38f4cdb  Use the stale parameter on listing activations. (#2632)
     new f48f7ea  Rename CliActivationResponse & CliActivation, and change them from (#2592)
     new 12a12ba  remove experimental web actions support
     new 0d50da1  Fix handing of binary content-types in webactions (#2683)
     new 6101281  API gw test cleanup (#2493)
     new 613e631  Restore throttle check before each CLI call. (#2702)
     new 5e39d4b  Apply standard scala formatting. (#2650)
     new 04908d5  Remove redundant test suite. Also remove some spurious log messages. (#2693)
     new 2038ba5  CLI User Agent Header (#2591)
     new a8e3016  Test change for api host setting which previously caused CLI to crash.
     new 30ba302  Clarify WSK_CONFIG_FILE empty string behavior (#2357)
     new 2fc6865  Add activation logs strip option. (#2620)

The 16 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .travis.yml                                        |    1 +
 Godeps/Godeps.json                                 |    4 +-
 commands/activation.go                             |    2 +-
 commands/commands.go                               |   10 +
 commands/flags.go                                  |    1 +
 commands/property.go                               |    7 +-
 commands/util.go                                   |   11 +-
 tests/dat/actions/corsHeaderMod.js                 |    2 +-
 tests/dat/actions/log.js                           |    7 +
 tests/dat/actions/multipleHeaders.js               |    2 +-
 tests/dat/actions/pngWeb.js                        |   13 +
 tests/src/integration/common/wsk.go                |    8 +-
 tests/src/integration/common/wskprops.go           |   55 -
 tests/src/integration/integration_test.go          |    8 +-
 .../apigw/healthtests/ApiGwEndToEndTests.scala     |  233 +-
 .../test/scala/system/basic/WskActionTests.scala   |  540 ++--
 .../test/scala/system/basic/WskBasicTests.scala    | 1629 +++++-----
 .../test/scala/system/basic/WskConsoleTests.scala  |   83 +-
 .../test/scala/system/basic/WskPackageTests.scala  |  169 +-
 .../src/test/scala/system/basic/WskRuleTests.scala |  706 +++--
 .../src/test/scala/system/basic/WskSdkTests.scala  |  152 +-
 .../test/scala/system/basic/WskSequenceTests.scala |  929 +++---
 .../scala/whisk/core/admin/WskAdminTests.scala     |  275 +-
 .../actions/test/ApiGwRoutemgmtActionTests.scala   |  781 +++--
 .../scala/whisk/core/cli/test/ApiGwTests.scala     | 1852 +++++------
 .../core/cli/test/WskActionSequenceTests.scala     |   81 +-
 .../whisk/core/cli/test/WskBasicUsageTests.scala   | 3215 ++++++++++----------
 .../scala/whisk/core/cli/test/WskConfigTests.scala |  471 +--
 .../whisk/core/cli/test/WskEntitlementTests.scala  |  557 ++--
 .../whisk/core/cli/test/WskWebActionsTests.scala   |  534 ++--
 wski18n/i18n_resources.go                          |   22 +-
 wski18n/resources/en_US.all.json                   |    4 +
 32 files changed, 6347 insertions(+), 6017 deletions(-)
 create mode 100644 tests/dat/actions/log.js
 create mode 100644 tests/dat/actions/pngWeb.js
 delete mode 100644 tests/src/integration/common/wskprops.go

-- 
To stop receiving notification emails like this one, please contact
['"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>'].

[incubator-openwhisk-cli] 05/16: Use the stale parameter on listing activations. (#2632)

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csantanapr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git

commit 38f4cdbb2c51773d2f984106b2349d78e64b2b11
Author: Christian Bickel <gi...@cbickel.de>
AuthorDate: Wed Aug 23 13:49:13 2017 +0200

    Use the stale parameter on listing activations. (#2632)
---
 tests/src/test/scala/system/basic/WskConsoleTests.scala | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/src/test/scala/system/basic/WskConsoleTests.scala b/tests/src/test/scala/system/basic/WskConsoleTests.scala
index 60a1dc0..1848733 100644
--- a/tests/src/test/scala/system/basic/WskConsoleTests.scala
+++ b/tests/src/test/scala/system/basic/WskConsoleTests.scala
@@ -72,7 +72,7 @@ class WskConsoleTests
                     val console = wsk.activation.console(10 seconds, since = duration)
                     println(console.stdout)
                     console.stdout should include(payload)
-        }
+            }
     }
 
     it should "show repeated activations" in withAssetCleaner(wskprops) {

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 16/16: Add activation logs strip option. (#2620)

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csantanapr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git

commit 2fc6865e26572128bda251b9dc131ac184ae1e5d
Author: David Liu <no...@126.com>
AuthorDate: Sat Sep 16 00:10:47 2017 +0800

    Add activation logs strip option. (#2620)
    
    * Add activation logs strip option.
    
    * Add proper test for strip option.
    
    * Remove dead code.
---
 .travis.yml                                        |   1 +
 Godeps/Godeps.json                                 |   2 +-
 commands/commands.go                               |   8 +
 commands/util.go                                   |   2 +-
 tests/dat/actions/corsHeaderMod.js                 |   2 +-
 tests/dat/actions/log.js                           |   7 +
 tests/dat/actions/multipleHeaders.js               |   2 +-
 tests/dat/actions/pngWeb.js                        |  13 ++
 tests/src/integration/common/wsk.go                |   8 +-
 tests/src/integration/common/wskprops.go           |  55 -------
 tests/src/integration/integration_test.go          |   8 +-
 .../apigw/healthtests/ApiGwEndToEndTests.scala     |   2 +-
 .../test/scala/system/basic/WskActionTests.scala   |  30 ++--
 .../test/scala/system/basic/WskBasicTests.scala    |  28 ++--
 .../test/scala/system/basic/WskConsoleTests.scala  |   4 +-
 .../test/scala/system/basic/WskPackageTests.scala  |   2 +-
 .../test/scala/system/basic/WskSequenceTests.scala |  25 ++-
 .../scala/whisk/core/cli/test/ApiGwTests.scala     |  46 +++---
 .../core/cli/test/WskActionSequenceTests.scala     |   4 +-
 .../whisk/core/cli/test/WskBasicUsageTests.scala   | 169 ++++++++-------------
 .../whisk/core/cli/test/WskEntitlementTests.scala  |  20 +--
 .../whisk/core/cli/test/WskWebActionsTests.scala   |  32 ++--
 wski18n/i18n_resources.go                          |  20 +--
 23 files changed, 214 insertions(+), 276 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index fe4ffe1..7864831 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -6,6 +6,7 @@ matrix:
     include:
         - os: linux
           sudo: required
+          group: deprecated-2017Q3
           go: 1.8
           env:
             secure: "Br0fD9CAKm8gqyEuwmltNJd4dGJCxPpj6feugHlO+CFFwfE/+kJKkpTlsDuRfrUzUDlWiETNPf0XGSjvPFqZExnLCE9XQh2+XF6u+S3YBWfM+rbbyRVAK6BlTwmt0u3jRJ2JP7spedTGZA+qfIWI+UkwoOexo7NcqtMPLahiZzheaaad8y3J+crHQCrB/kPrhLqKVMEOkIbveFdfV2QLfCOWgqP8e1LGZhPZ2N4QcNo0iB5uI4ZyYszTZDniXFKxz7kBs4tl4ZQDqRHqL02qKPsjbvjrZp83ql+PbC2dpgXi9YpaDuBEqKKX1rTQP5ppcwbobot5U3ItHWzpXbLCdsWxvbde/0enjMmOF1wwl71hPYIf7PkQmNAWXRtL2Z1TguO/dKCeXBLDER4YDQ79GYpikAMqnrRLou4rsyZrNUzg8aHbELzAHppDSpqEJN8ymGgWgmWBT8yPaWVwN5CjPFO [...]
diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index eb1b09c..998bfb4 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -64,7 +64,7 @@
 			"Rev": "0ca9ea5df5451ffdf184b4428c902747c2c11cd7"
 		},
         {
-            "ImportPath": "github.com/apache/incubator-openwhisk-client-go/...",
+            "ImportPath": "github.com/apache/incubator-openwhisk-client-go/whisk",
             "Rev": "d9d11f0b21f8c32b3d78cd632d41a69a818be200"
         }
 	]
diff --git a/commands/commands.go b/commands/commands.go
index d15eae5..0914a73 100644
--- a/commands/commands.go
+++ b/commands/commands.go
@@ -64,6 +64,14 @@ func setupClientConfig(cmd *cobra.Command, args []string) (error){
         UserAgent:  UserAgent + "/1.0 (" + Properties.CLIVersion + ")",
     }
 
+    if len(clientConfig.Host) == 0 {
+        config, _ := whisk.GetDefaultConfig()
+        clientConfig.Host = config.Host
+        if len(clientConfig.Host) == 0 {
+            clientConfig.Host = "openwhisk.ng.bluemix.net"
+        }
+    }
+
     // Setup client
     client, err = whisk.NewClient(http.DefaultClient, clientConfig)
 
diff --git a/commands/util.go b/commands/util.go
index e148470..96511c0 100644
--- a/commands/util.go
+++ b/commands/util.go
@@ -274,7 +274,7 @@ func printFullActivationList(activations []whisk.Activation) {
 
 func printActivationLogs(logs []string) {
     for _, log := range logs {
-        if (flags.activation.strip){
+        if (Flags.activation.strip){
             fmt.Printf("%s\n", log[39:])
         } else {
             fmt.Printf("%s\n", log)
diff --git a/tests/dat/actions/corsHeaderMod.js b/tests/dat/actions/corsHeaderMod.js
index a658160..df9b704 100644
--- a/tests/dat/actions/corsHeaderMod.js
+++ b/tests/dat/actions/corsHeaderMod.js
@@ -7,6 +7,6 @@ function main() {
             "Location": "openwhisk.org",
             "Set-Cookie": "cookie-cookie-cookie"
         },
-        code: 200
+        statusCode: 200
     }
 }
diff --git a/tests/dat/actions/log.js b/tests/dat/actions/log.js
new file mode 100644
index 0000000..bfbd513
--- /dev/null
+++ b/tests/dat/actions/log.js
@@ -0,0 +1,7 @@
+/**
+ * Emit strings to stdout/stderr.
+ */
+function main() {
+    console.log("this is stdout");
+    console.error("this is stderr");
+}
diff --git a/tests/dat/actions/multipleHeaders.js b/tests/dat/actions/multipleHeaders.js
index 06712c1..f19e236 100644
--- a/tests/dat/actions/multipleHeaders.js
+++ b/tests/dat/actions/multipleHeaders.js
@@ -3,6 +3,6 @@ function main() {
         headers: {
             "Set-Cookie": ["a=b", "c=d"]
         },
-        code: 200
+        statusCode: 200
     }
 }
diff --git a/tests/dat/actions/pngWeb.js b/tests/dat/actions/pngWeb.js
new file mode 100644
index 0000000..3a644b0
--- /dev/null
+++ b/tests/dat/actions/pngWeb.js
@@ -0,0 +1,13 @@
+function main() {
+    var png = "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAGCAYAAAD68A/GAAAA/klEQVQYGWNgAAEHBxaG//+ZQMyyn581Pfas+cRQnf1LfF" +
+        "Ljf+62smUgcUbt0FA2Zh7drf/ffMy9vLn3RurrW9e5hCU11i2azfD4zu1/DHz8TAy/foUxsXBrFzHzC7r8+M9S1vn1qxQT07" +
+        "dDjL9fdemrqKxlYGT6z8AIMo6hgeUfA0PUvy9fGFh5GWK3z7vNxSWt++jX99+8SoyiGQwsW38w8PJEM7x5v5SJ8f+/xv8MDA" +
+        "zffv9hevfkWjiXBGMpMx+j2awovjcMjFztDO8+7GF49LkbZDCDeXLTWnZO7qDfn1/+5jbw/8pjYWS4wZLztXnuEuYTk2M+Mz" +
+        "Iw/AcA36VewaD6fzsAAAAASUVORK5CYII="
+
+    return {
+        statusCode: 200,
+        headers: {'content-type': 'image/png'},
+        body: png
+    }
+}
diff --git a/tests/src/integration/common/wsk.go b/tests/src/integration/common/wsk.go
index aa7d87f..d0323c3 100644
--- a/tests/src/integration/common/wsk.go
+++ b/tests/src/integration/common/wsk.go
@@ -19,6 +19,7 @@ package common
 import (
     "os"
     "os/exec"
+    "github.com/apache/incubator-openwhisk-client-go/whisk"
 )
 
 const cmd = "wsk"
@@ -28,7 +29,7 @@ type Wsk struct {
     Path string
     Arg []string
     Dir string
-    Wskprops *Wskprops
+    Wskprops *whisk.Wskprops
 }
 
 func NewWsk() *Wsk {
@@ -40,7 +41,10 @@ func NewWskWithPath(path string) *Wsk {
     dep.Path = cmd
     dep.Arg = []string{arg}
     dep.Dir = path
-    dep.Wskprops = GetWskprops()
+    pi := whisk.PropertiesImp{
+        OsPackage: whisk.OSPackageImp{},
+    }
+    dep.Wskprops, _ = whisk.GetDefaultWskProp(pi)
     return &dep
 }
 
diff --git a/tests/src/integration/common/wskprops.go b/tests/src/integration/common/wskprops.go
deleted file mode 100644
index ab6a728..0000000
--- a/tests/src/integration/common/wskprops.go
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You 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.
- */
-package common
-
-import (
-    "github.com/spf13/viper"
-    "io/ioutil"
-    "os"
-)
-
-type Wskprops struct {
-    APIHost string
-    APIVersion string
-    AuthKey string
-    ControllerHost string
-    ControllerPort string
-}
-
-func GetWskprops() *Wskprops {
-    var dep Wskprops
-    dep.APIHost = ""
-    dep.AuthKey = ""
-    dep.APIVersion = "v1"
-
-    viper.SetConfigName("whisk")
-    viper.AddConfigPath(os.Getenv("OPENWHISK_HOME"))
-
-    err := viper.ReadInConfig()
-    if err == nil {
-        authPath := viper.GetString("testing.auth")
-
-        b, err := ioutil.ReadFile(authPath)
-        if err == nil {
-            dep.AuthKey = string(b)
-        }
-        dep.APIHost = viper.GetString("controller.hosts")
-        dep.ControllerHost = viper.GetString("controller.hosts")
-        dep.ControllerPort = viper.GetString("controller.host.basePort")
-    }
-    return &dep
-}
diff --git a/tests/src/integration/integration_test.go b/tests/src/integration/integration_test.go
index f2edbcb..7c377b9 100644
--- a/tests/src/integration/integration_test.go
+++ b/tests/src/integration/integration_test.go
@@ -25,6 +25,7 @@ import (
     "github.com/apache/incubator-openwhisk-cli/tests/src/integration/common"
     "os"
     "strings"
+    "fmt"
 )
 
 var invalidArgs []common.InvalidArg
@@ -341,6 +342,7 @@ func TestSetAPIHostAuthNamespace(t *testing.T) {
     namespace, _ := wsk.ListNamespaces()
     namespaces := strings.Split(strings.TrimSpace(string(namespace)), "\n")
     expectedNamespace := string(namespaces[len(namespaces) - 1])
+    fmt.Println(wsk.Wskprops.APIHost)
     if (wsk.Wskprops.APIHost != "" && wsk.Wskprops.APIHost != "") {
         stdout, err := wsk.RunCommand("property", "set", "--apihost", wsk.Wskprops.APIHost,
             "--auth", wsk.Wskprops.AuthKey, "--namespace", expectedNamespace)
@@ -364,7 +366,7 @@ func TestShowAPIBuildVersion(t *testing.T) {
     assert.Equal(t, os.Getenv("WSK_CONFIG_FILE"), tmpProp, "The environment variable WSK_CONFIG_FILE has not been set.")
 
     stdout, err := wsk.RunCommand("property", "set", "--apihost", wsk.Wskprops.APIHost,
-        "--apiversion", wsk.Wskprops.APIVersion)
+        "--apiversion", wsk.Wskprops.Apiversion)
     assert.Equal(t, nil, err, "The command property set --apihost --apiversion failed to run.")
     stdout, err = wsk.RunCommand("property", "get", "-i", "--apibuild")
     assert.Equal(t, nil, err, "The command property get -i --apibuild failed to run.")
@@ -402,7 +404,7 @@ func TestShowAPIBuildVersionHTTP(t *testing.T) {
     os.Setenv("WSK_CONFIG_FILE", tmpProp)
     assert.Equal(t, os.Getenv("WSK_CONFIG_FILE"), tmpProp, "The environment variable WSK_CONFIG_FILE has not been set.")
 
-    apihost := "http://" + wsk.Wskprops.ControllerHost + ":" + wsk.Wskprops.ControllerPort
+    apihost := wsk.Wskprops.APIHost
     stdout, err := wsk.RunCommand("property", "set", "--apihost", apihost)
     assert.Equal(t, nil, err, "The command property set --apihost failed to run.")
     stdout, err = wsk.RunCommand("property", "get", "-i", "--apibuild")
@@ -425,7 +427,7 @@ func TestRejectAuthCommNoKey(t *testing.T) {
     assert.Equal(t, os.Getenv("WSK_CONFIG_FILE"), tmpProp, "The environment variable WSK_CONFIG_FILE has not been set.")
 
     stdout, err := wsk.RunCommand("list", "--apihost", wsk.Wskprops.APIHost,
-        "--apiversion", wsk.Wskprops.APIVersion)
+        "--apiversion", wsk.Wskprops.Apiversion)
     assert.NotEqual(t, nil, err, "The command list should fail to run.")
     assert.Contains(t, common.RemoveRedundentSpaces(string(stdout)), "usage.",
         "The output of the command does not contain \"usage.\".")
diff --git a/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala b/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala
index 4c95bf5..d9a94b4 100644
--- a/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala
+++ b/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala
@@ -86,7 +86,7 @@ class ApiGwEndToEndTests
       println("cli namespace: " + clinamespace)
 
       // Create the action for the API.  It must be a "web-action" action.
-      val file = TestUtils.getTestActionFilename(s"echo-web-http.js")
+      val file = TestCLIUtils.getTestActionFilename(s"echo-web-http.js")
       wsk.action.create(
         name = actionName,
         artifact = Some(file),
diff --git a/tests/src/test/scala/system/basic/WskActionTests.scala b/tests/src/test/scala/system/basic/WskActionTests.scala
index fb65f2c..519f50b 100644
--- a/tests/src/test/scala/system/basic/WskActionTests.scala
+++ b/tests/src/test/scala/system/basic/WskActionTests.scala
@@ -48,7 +48,7 @@ class WskActionTests extends TestHelpers with WskTestHelpers with JsHelpers {
   it should "invoke an action returning a promise" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     val name = "hello promise"
     assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-      action.create(name, Some(TestUtils.getTestActionFilename("helloPromise.js")))
+      action.create(name, Some(TestCLIUtils.getTestActionFilename("helloPromise.js")))
     }
 
     val run = wsk.action.invoke(name)
@@ -62,7 +62,7 @@ class WskActionTests extends TestHelpers with WskTestHelpers with JsHelpers {
   it should "invoke an action with a space in the name" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     val name = "hello Async"
     assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-      action.create(name, Some(TestUtils.getTestActionFilename("helloAsync.js")))
+      action.create(name, Some(TestCLIUtils.getTestActionFilename("helloAsync.js")))
     }
 
     val run = wsk.action.invoke(name, Map("payload" -> testString.toJson))
@@ -80,7 +80,7 @@ class WskActionTests extends TestHelpers with WskTestHelpers with JsHelpers {
     assetHelper.withCleaner(wsk.action, name) { (action, _) =>
       action.create(
         name,
-        Some(TestUtils.getTestActionFilename("printParams.js")),
+        Some(TestCLIUtils.getTestActionFilename("printParams.js")),
         parameters = params.mapValues(_.toJson))
     }
 
@@ -107,7 +107,7 @@ class WskActionTests extends TestHelpers with WskTestHelpers with JsHelpers {
     }
 
     assetHelper.withCleaner(wsk.action, fullQualifiedName) {
-      val file = Some(TestUtils.getTestActionFilename("wc.js"))
+      val file = Some(TestCLIUtils.getTestActionFilename("wc.js"))
       (action, _) =>
         action.create(fullQualifiedName, file)
     }
@@ -132,7 +132,7 @@ class WskActionTests extends TestHelpers with WskTestHelpers with JsHelpers {
       val annots = Map("b" -> "B".toJson)
 
       assetHelper.withCleaner(wsk.action, origActionName) {
-        val file = Some(TestUtils.getTestActionFilename("wc.js"))
+        val file = Some(TestCLIUtils.getTestActionFilename("wc.js"))
         (action, _) =>
           action.create(origActionName, file, parameters = params, annotations = annots)
       }
@@ -171,7 +171,7 @@ class WskActionTests extends TestHelpers with WskTestHelpers with JsHelpers {
         JsObject("key" -> JsString("exec"), "value" -> JsString("nodejs:6")))
 
       assetHelper.withCleaner(wsk.action, origName) {
-        val file = Some(TestUtils.getTestActionFilename("echo.js"))
+        val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
         (action, _) =>
           action.create(origName, file, parameters = origParams, annotations = origAnnots)
       }
@@ -190,7 +190,7 @@ class WskActionTests extends TestHelpers with WskTestHelpers with JsHelpers {
   it should "recreate and invoke a new action with different code" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     val name = "recreatedAction"
     assetHelper.withCleaner(wsk.action, name, false) { (action, _) =>
-      action.create(name, Some(TestUtils.getTestActionFilename("wc.js")))
+      action.create(name, Some(TestCLIUtils.getTestActionFilename("wc.js")))
     }
 
     val run1 = wsk.action.invoke(name, Map("payload" -> testString.toJson))
@@ -201,7 +201,7 @@ class WskActionTests extends TestHelpers with WskTestHelpers with JsHelpers {
 
     wsk.action.delete(name)
     assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-      action.create(name, Some(TestUtils.getTestActionFilename("hello.js")))
+      action.create(name, Some(TestCLIUtils.getTestActionFilename("hello.js")))
     }
 
     val run2 = wsk.action.invoke(name, Map("payload" -> testString.toJson))
@@ -214,7 +214,7 @@ class WskActionTests extends TestHelpers with WskTestHelpers with JsHelpers {
   it should "fail to invoke an action with an empty file" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     val name = "empty"
     assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-      action.create(name, Some(TestUtils.getTestActionFilename("empty.js")))
+      action.create(name, Some(TestCLIUtils.getTestActionFilename("empty.js")))
     }
     val run = wsk.action.invoke(name)
     withActivation(wsk.activation, run) { activation =>
@@ -226,7 +226,7 @@ class WskActionTests extends TestHelpers with WskTestHelpers with JsHelpers {
   it should "create an action with an empty file" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     val name = "empty"
     assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-      action.create(name, Some(TestUtils.getTestActionFilename("empty.js")))
+      action.create(name, Some(TestCLIUtils.getTestActionFilename("empty.js")))
     }
     val rr = wsk.action.get(name)
     wsk.parseJsonString(rr.stdout).getFieldPath("exec", "code") shouldBe Some(JsString(""))
@@ -237,10 +237,10 @@ class WskActionTests extends TestHelpers with WskTestHelpers with JsHelpers {
     val child = "wc"
 
     assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-      action.create(name, Some(TestUtils.getTestActionFilename("wcbin.js")))
+      action.create(name, Some(TestCLIUtils.getTestActionFilename("wcbin.js")))
     }
     assetHelper.withCleaner(wsk.action, child) { (action, _) =>
-      action.create(child, Some(TestUtils.getTestActionFilename("wc.js")))
+      action.create(child, Some(TestCLIUtils.getTestActionFilename("wc.js")))
     }
 
     val run = wsk.action.invoke(name, Map("payload" -> testString.toJson), blocking = true)
@@ -255,7 +255,7 @@ class WskActionTests extends TestHelpers with WskTestHelpers with JsHelpers {
   it should "blocking invoke an asynchronous action" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     val name = "helloAsync"
     assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-      action.create(name, Some(TestUtils.getTestActionFilename("helloAsync.js")))
+      action.create(name, Some(TestCLIUtils.getTestActionFilename("helloAsync.js")))
     }
 
     val run = wsk.action.invoke(name, Map("payload" -> testString.toJson), blocking = true)
@@ -281,7 +281,7 @@ class WskActionTests extends TestHelpers with WskTestHelpers with JsHelpers {
   it should "not be able to use 'ping' in an action" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     val name = "ping"
     assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-      action.create(name, Some(TestUtils.getTestActionFilename("ping.js")))
+      action.create(name, Some(TestCLIUtils.getTestActionFilename("ping.js")))
     }
 
     val run = wsk.action.invoke(name, Map("payload" -> "google.com".toJson))
@@ -294,7 +294,7 @@ class WskActionTests extends TestHelpers with WskTestHelpers with JsHelpers {
   ignore should "support UTF-8 as input and output format" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     val name = "utf8Test"
     assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-      action.create(name, Some(TestUtils.getTestActionFilename("hello.js")))
+      action.create(name, Some(TestCLIUtils.getTestActionFilename("hello.js")))
     }
 
     val utf8 = "«ταБЬℓσö»: 1<2 & 4+1>³, now 20%€§$ off!"
diff --git a/tests/src/test/scala/system/basic/WskBasicTests.scala b/tests/src/test/scala/system/basic/WskBasicTests.scala
index 4ee00cb..f206e64 100644
--- a/tests/src/test/scala/system/basic/WskBasicTests.scala
+++ b/tests/src/test/scala/system/basic/WskBasicTests.scala
@@ -41,7 +41,7 @@ class WskBasicTests extends TestHelpers with WskTestHelpers {
 
   implicit val wskprops = WskProps()
   val wsk = new Wsk
-  val defaultAction = Some(TestUtils.getTestActionFilename("hello.js"))
+  val defaultAction = Some(TestCLIUtils.getTestActionFilename("hello.js"))
 
   behavior of "Wsk CLI"
 
@@ -185,7 +185,7 @@ class WskBasicTests extends TestHelpers with WskTestHelpers {
 
   it should "create, update, get and list an action" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     val name = "createAndUpdate"
-    val file = Some(TestUtils.getTestActionFilename("hello.js"))
+    val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
     val params = Map("a" -> "A".toJson)
     assetHelper.withCleaner(wsk.action, name) { (action, _) =>
       action.create(name, file, parameters = params)
@@ -204,7 +204,7 @@ class WskBasicTests extends TestHelpers with WskTestHelpers {
 
   it should "reject create of an action that already exists" in withAssetCleaner(wskprops) {
     val name = "dupeAction"
-    val file = Some(TestUtils.getTestActionFilename("echo.js"))
+    val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
 
     (wp, assetHelper) =>
       assetHelper.withCleaner(wsk.action, name) { (action, _) =>
@@ -256,7 +256,7 @@ class WskBasicTests extends TestHelpers with WskTestHelpers {
       assetHelper.withCleaner(wsk.action, name) {
         // this docker image will be need to be pulled from dockerhub and hence has to be published there first
         (action, _) =>
-          action.create(name, Some(TestUtils.getTestActionFilename("blackbox.zip")), kind = Some("native"))
+          action.create(name, Some(TestCLIUtils.getTestActionFilename("blackbox.zip")), kind = Some("native"))
       }
 
       val run = wsk.action.invoke(name, Map())
@@ -271,8 +271,8 @@ class WskBasicTests extends TestHelpers with WskTestHelpers {
 
   it should "create, and invoke an action using a parameter file" in withAssetCleaner(wskprops) {
     val name = "paramFileAction"
-    val file = Some(TestUtils.getTestActionFilename("argCheck.js"))
-    val argInput = Some(TestUtils.getTestActionFilename("validInput2.json"))
+    val file = Some(TestCLIUtils.getTestActionFilename("argCheck.js"))
+    val argInput = Some(TestCLIUtils.getTestActionFilename("validInput2.json"))
 
     (wp, assetHelper) =>
       assetHelper.withCleaner(wsk.action, name) { (action, _) =>
@@ -332,7 +332,7 @@ class WskBasicTests extends TestHelpers with WskTestHelpers {
     (wp, assetHelper) =>
       val name = "MALFORMED"
       assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-        action.create(name, Some(TestUtils.getTestActionFilename("malformed.js")))
+        action.create(name, Some(TestCLIUtils.getTestActionFilename("malformed.js")))
       }
 
       val run = wsk.action.invoke(name, Map("payload" -> "whatever".toJson))
@@ -351,7 +351,7 @@ class WskBasicTests extends TestHelpers with WskTestHelpers {
     val boolErrInput = Map("error" -> true.toJson)
 
     assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-      action.create(name, Some(TestUtils.getTestActionFilename("echo.js")))
+      action.create(name, Some(TestCLIUtils.getTestActionFilename("echo.js")))
     }
 
     Seq(strErrInput, numErrInput, boolErrInput) foreach { input =>
@@ -374,7 +374,7 @@ class WskBasicTests extends TestHelpers with WskTestHelpers {
     (wp, assetHelper) =>
       val name = "errorResponseObject"
       assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-        action.create(name, Some(TestUtils.getTestActionFilename("asyncError.js")))
+        action.create(name, Some(TestCLIUtils.getTestActionFilename("asyncError.js")))
       }
 
       val stderr = wsk.action.invoke(name, blocking = true, expectedExitCode = 246).stderr
@@ -386,7 +386,7 @@ class WskBasicTests extends TestHelpers with WskTestHelpers {
   it should "invoke a blocking action and get only the result" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     val name = "basicInvoke"
     assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-      action.create(name, Some(TestUtils.getTestActionFilename("wc.js")))
+      action.create(name, Some(TestCLIUtils.getTestActionFilename("wc.js")))
     }
 
     wsk.action
@@ -427,7 +427,7 @@ class WskBasicTests extends TestHelpers with WskTestHelpers {
       val name = "emptyJSONAction"
 
       assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-        action.create(name, Some(TestUtils.getTestActionFilename("emptyJSONResult.js")))
+        action.create(name, Some(TestCLIUtils.getTestActionFilename("emptyJSONResult.js")))
       }
 
       val stdout = wsk.action.invoke(name, result = true).stdout
@@ -440,7 +440,7 @@ class WskBasicTests extends TestHelpers with WskTestHelpers {
     val params = Map("payload" -> "100000".toJson)
     val allowedActionDuration = 120 seconds
     val res = assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-      action.create(name, Some(TestUtils.getTestActionFilename("timeout.js")), timeout = Some(allowedActionDuration))
+      action.create(name, Some(TestCLIUtils.getTestActionFilename("timeout.js")), timeout = Some(allowedActionDuration))
       action.invoke(name, parameters = params, result = true, expectedExitCode = ACCEPTED)
     }
 
@@ -520,8 +520,8 @@ class WskBasicTests extends TestHelpers with WskTestHelpers {
 
   it should "create, and fire a trigger using a parameter file" in withAssetCleaner(wskprops) {
     val name = "paramFileTrigger"
-    val file = Some(TestUtils.getTestActionFilename("argCheck.js"))
-    val argInput = Some(TestUtils.getTestActionFilename("validInput2.json"))
+    val file = Some(TestCLIUtils.getTestActionFilename("argCheck.js"))
+    val argInput = Some(TestCLIUtils.getTestActionFilename("validInput2.json"))
 
     (wp, assetHelper) =>
       assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
diff --git a/tests/src/test/scala/system/basic/WskConsoleTests.scala b/tests/src/test/scala/system/basic/WskConsoleTests.scala
index 7abbeeb..5252d0a 100644
--- a/tests/src/test/scala/system/basic/WskConsoleTests.scala
+++ b/tests/src/test/scala/system/basic/WskConsoleTests.scala
@@ -58,7 +58,7 @@ class WskConsoleTests extends TestHelpers with WskTestHelpers {
     }
 
     assetHelper.withCleaner(wsk.action, fullActionName) { (action, _) =>
-      action.create(fullActionName, Some(TestUtils.getTestActionFilename("hello.js")))
+      action.create(fullActionName, Some(TestCLIUtils.getTestActionFilename("hello.js")))
     }
 
     val duration = Some(30 seconds)
@@ -73,7 +73,7 @@ class WskConsoleTests extends TestHelpers with WskTestHelpers {
   it should "show repeated activations" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     val name = "countdown"
     assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-      action.create(name, Some(TestUtils.getTestActionFilename("countdown.js")))
+      action.create(name, Some(TestCLIUtils.getTestActionFilename("countdown.js")))
     }
 
     val start = Instant.now(Clock.systemUTC())
diff --git a/tests/src/test/scala/system/basic/WskPackageTests.scala b/tests/src/test/scala/system/basic/WskPackageTests.scala
index 1fae059..40c93e6 100644
--- a/tests/src/test/scala/system/basic/WskPackageTests.scala
+++ b/tests/src/test/scala/system/basic/WskPackageTests.scala
@@ -87,7 +87,7 @@ class WskPackageTests extends TestHelpers with WskTestHelpers {
     val packageParams = Map("key1a" -> "value1a".toJson, "key1b" -> "value1b".toJson)
     val bindParams = Map("key2a" -> "value2a".toJson, "key1b" -> "value2b".toJson)
     val actionParams = Map("key0" -> "value0".toJson)
-    val file = TestUtils.getTestActionFilename("printParams.js")
+    val file = TestCLIUtils.getTestActionFilename("printParams.js")
     assetHelper.withCleaner(wsk.pkg, packageName) { (pkg, _) =>
       pkg.create(packageName, packageParams)
     }
diff --git a/tests/src/test/scala/system/basic/WskSequenceTests.scala b/tests/src/test/scala/system/basic/WskSequenceTests.scala
index 1b90b6d..9ec21a7 100644
--- a/tests/src/test/scala/system/basic/WskSequenceTests.scala
+++ b/tests/src/test/scala/system/basic/WskSequenceTests.scala
@@ -32,8 +32,8 @@ import common.StreamLogging
 import common.TestHelpers
 import common.TestCLIUtils
 import common.TestUtils._
-import common.Wsk
 import common.WhiskProperties
+import common.Wsk
 import common.WskProps
 import common.WskTestHelpers
 
@@ -56,9 +56,6 @@ class WskSequenceTests extends TestHelpers with ScalatestRouteTest with WskTestH
   val allowedActionDuration = 120 seconds
   val shortDuration = 10 seconds
 
-  val whiskConfig = new WhiskConfig(Map(WhiskConfig.actionSequenceMaxLimit -> null))
-  assert(whiskConfig.isValid)
-
   behavior of "Wsk Sequence"
 
   it should "invoke a sequence with normal payload and payload with error field" in withAssetCleaner(wskprops) {
@@ -66,7 +63,7 @@ class WskSequenceTests extends TestHelpers with ScalatestRouteTest with WskTestH
       val name = "sequence"
       val actions = Seq("split", "sort", "head", "cat")
       for (actionName <- actions) {
-        val file = TestUtils.getTestActionFilename(s"$actionName.js")
+        val file = TestCLIUtils.getTestActionFilename(s"$actionName.js")
         assetHelper.withCleaner(wsk.action, actionName) { (action, _) =>
           action.create(name = actionName, artifact = Some(file), timeout = Some(allowedActionDuration))
         }
@@ -126,7 +123,7 @@ class WskSequenceTests extends TestHelpers with ScalatestRouteTest with WskTestH
     val actions = Seq("split") ++ inner_actions ++ Seq("cat")
     // create atomic actions
     for (actionName <- actions) {
-      val file = TestUtils.getTestActionFilename(s"$actionName.js")
+      val file = TestCLIUtils.getTestActionFilename(s"$actionName.js")
       assetHelper.withCleaner(wsk.action, actionName) { (action, _) =>
         action.create(name = actionName, artifact = Some(file), timeout = Some(allowedActionDuration))
       }
@@ -176,7 +173,7 @@ class WskSequenceTests extends TestHelpers with ScalatestRouteTest with WskTestH
     val echo = "echo"
 
     // create echo action
-    val file = TestUtils.getTestActionFilename(s"$echo.js")
+    val file = TestCLIUtils.getTestActionFilename(s"$echo.js")
     assetHelper.withCleaner(wsk.action, echo) { (action, actionName) =>
       action.create(name = actionName, artifact = Some(file), timeout = Some(allowedActionDuration))
     }
@@ -201,7 +198,7 @@ class WskSequenceTests extends TestHelpers with ScalatestRouteTest with WskTestH
       result.fields.get("payload") shouldBe Some(argsJson)
     }
     // update x with limit echo
-    val limit = whiskConfig.actionSequenceLimit.toInt
+    val limit = WhiskProperties.getProperty("limits.actions.sequence.maxLength").toInt
     val manyEcho = for (i <- 1 to limit) yield echo
 
     wsk.action.create(xName, Some(manyEcho.mkString(",")), kind = Some("sequence"), update = true)
@@ -236,7 +233,7 @@ class WskSequenceTests extends TestHelpers with ScalatestRouteTest with WskTestH
       val helloWithPkg = s"$pkgName/$helloName"
 
       // create hello action in package
-      val file = TestUtils.getTestActionFilename(s"$helloName.js")
+      val file = TestCLIUtils.getTestActionFilename(s"$helloName.js")
       val actionStr = "AtomicAction"
       assetHelper.withCleaner(wsk.action, helloWithPkg) { (action, actionName) =>
         action.create(
@@ -282,7 +279,7 @@ class WskSequenceTests extends TestHelpers with ScalatestRouteTest with WskTestH
       val packageParams = Map("key1a" -> "value1a".toJson, "key1b" -> "value1b".toJson)
       val bindParams = Map("key2a" -> "value2a".toJson, "key1b" -> "value2b".toJson)
       val actionParams = Map("key0" -> "value0".toJson)
-      val file = TestUtils.getTestActionFilename("printParams.js")
+      val file = TestCLIUtils.getTestActionFilename("printParams.js")
       assetHelper.withCleaner(wsk.pkg, packageName) { (pkg, _) =>
         pkg.create(packageName, packageParams)
       }
@@ -320,7 +317,7 @@ class WskSequenceTests extends TestHelpers with ScalatestRouteTest with WskTestH
       // create actions
       val actions = Seq(apperror, echo)
       for (actionName <- actions) {
-        val file = TestUtils.getTestActionFilename(s"$actionName.js")
+        val file = TestCLIUtils.getTestActionFilename(s"$actionName.js")
         assetHelper.withCleaner(wsk.action, actionName) { (action, actionName) =>
           action.create(name = actionName, artifact = Some(file), timeout = Some(allowedActionDuration))
         }
@@ -357,7 +354,7 @@ class WskSequenceTests extends TestHelpers with ScalatestRouteTest with WskTestH
       // timeouts for the action; make the one for initforever short
       val timeout = Map(echo -> allowedActionDuration, initforever -> shortDuration)
       for (actionName <- actions) {
-        val file = TestUtils.getTestActionFilename(s"$actionName.js")
+        val file = TestCLIUtils.getTestActionFilename(s"$actionName.js")
         assetHelper.withCleaner(wsk.action, actionName) { (action, actionName) =>
           action.create(name = actionName, artifact = Some(file), timeout = Some(timeout(actionName)))
         }
@@ -394,7 +391,7 @@ class WskSequenceTests extends TestHelpers with ScalatestRouteTest with WskTestH
     // create actions
     val actions = Seq(echo, sleep)
     for (actionName <- actions) {
-      val file = TestUtils.getTestActionFilename(s"$actionName.js")
+      val file = TestCLIUtils.getTestActionFilename(s"$actionName.js")
       assetHelper.withCleaner(wsk.action, actionName) { (action, actionName) =>
         action.create(name = actionName, artifact = Some(file), timeout = Some(allowedActionDuration))
       }
@@ -442,7 +439,7 @@ class WskSequenceTests extends TestHelpers with ScalatestRouteTest with WskTestH
       trigger.create(name, parameters = triggerPayload)
     }
     // action
-    val file = TestUtils.getTestActionFilename(s"$actionName.js")
+    val file = TestCLIUtils.getTestActionFilename(s"$actionName.js")
     assetHelper.withCleaner(wsk.action, actionName) { (action, actionName) =>
       action.create(name = actionName, artifact = Some(file), timeout = Some(allowedActionDuration))
     }
diff --git a/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala b/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
index 5b7c304..0d4b268 100644
--- a/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
@@ -275,7 +275,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
     try {
       println("cli namespace: " + clinamespace)
       // Create the action for the API.  It must be a "web-action" action.
-      val file = TestUtils.getTestActionFilename(s"echo.js")
+      val file = TestCLIUtils.getTestActionFilename(s"echo.js")
       wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
 
       var rr = apiCreate(
@@ -318,7 +318,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
       println("cli namespace: " + clinamespace)
 
       // Create the action for the API.  It must be a "web-action" action.
-      val file = TestUtils.getTestActionFilename(s"echo.js")
+      val file = TestCLIUtils.getTestActionFilename(s"echo.js")
       wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
 
       var rr = apiCreate(
@@ -352,7 +352,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
     val actionName = testName + "_action"
     try {
       // Create the action for the API.  It must be a "web-action" action.
-      val file = TestUtils.getTestActionFilename(s"echo.js")
+      val file = TestCLIUtils.getTestActionFilename(s"echo.js")
       wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
 
       var rr = apiCreate(
@@ -383,7 +383,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
     val actionName = testName + "_action"
     try {
       // Create the action for the API.  It must be a "web-action" action.
-      val file = TestUtils.getTestActionFilename(s"echo.js")
+      val file = TestCLIUtils.getTestActionFilename(s"echo.js")
       wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
 
       var rr = apiCreate(
@@ -411,7 +411,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
     val actionName = testName + "_action"
     try {
       // Create the action for the API.  It must be a "web-action" action.
-      val file = TestUtils.getTestActionFilename(s"echo.js")
+      val file = TestCLIUtils.getTestActionFilename(s"echo.js")
       wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
 
       var rr = apiCreate(
@@ -440,7 +440,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
     val newEndpoint = "/newEndpoint"
     try {
       // Create the action for the API.  It must be a "web-action" action.
-      val file = TestUtils.getTestActionFilename(s"echo.js")
+      val file = TestCLIUtils.getTestActionFilename(s"echo.js")
       wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
 
       var rr = apiCreate(
@@ -476,7 +476,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
     val testurlop = "get"
     val testapiname = testName + " API Name"
     val actionName = testName + "_action"
-    val swaggerPath = TestUtils.getTestApiGwFilename("testswaggerdoc1")
+    val swaggerPath = TestCLIUtils.getTestApiGwFilename("testswaggerdoc1")
     try {
       var rr = apiCreate(swagger = Some(swaggerPath))
       rr.stdout should include("ok: created API")
@@ -505,7 +505,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
     val newEndpoint = "/newEndpoint"
     try {
       // Create the action for the API.  It must be a "web-action" action.
-      val file = TestUtils.getTestActionFilename(s"echo.js")
+      val file = TestCLIUtils.getTestActionFilename(s"echo.js")
       wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
 
       var rr = apiCreate(
@@ -569,7 +569,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
       println("cli namespace: " + clinamespace)
 
       // Create the action for the API.  It must be a "web-action" action.
-      val file = TestUtils.getTestActionFilename(s"echo.js")
+      val file = TestCLIUtils.getTestActionFilename(s"echo.js")
       wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
 
       var rr = apiCreate(
@@ -599,7 +599,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
     val testurlop = "get"
     val testapiname = testName + " API Name"
     val actionName = testName + "_action"
-    val swaggerPath = TestUtils.getTestApiGwFilename(s"testswaggerdocinvalid")
+    val swaggerPath = TestCLIUtils.getTestApiGwFilename(s"testswaggerdocinvalid")
     try {
       val rr = apiCreate(swagger = Some(swaggerPath), expectedExitCode = ANY_ERROR_EXIT)
       println("api create stdout: " + rr.stdout)
@@ -620,7 +620,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
     val actionName = testName + "_action"
     try {
       // Create the action for the API.  It must be a "web-action" action.
-      val file = TestUtils.getTestActionFilename(s"echo.js")
+      val file = TestCLIUtils.getTestActionFilename(s"echo.js")
       wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
 
       var rr = apiCreate(
@@ -660,7 +660,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
     val actionName = testName + "_action"
     try {
       // Create the action for the API.  It must be a "web-action" action.
-      val file = TestUtils.getTestActionFilename(s"echo.js")
+      val file = TestCLIUtils.getTestActionFilename(s"echo.js")
       wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
 
       var rr = apiCreate(
@@ -699,7 +699,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
     val testurlop = "get"
     val testapiname = testName + " API Name"
     val actionName = "test1a"
-    val swaggerPath = TestUtils.getTestApiGwFilename(s"testswaggerdoc2")
+    val swaggerPath = TestCLIUtils.getTestApiGwFilename(s"testswaggerdoc2")
     try {
       var rr = apiCreate(swagger = Some(swaggerPath))
       println("api create stdout: " + rr.stdout)
@@ -728,7 +728,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
     val actionName = testName + "_action"
     try {
       // Create the action for the API.  It must be a "web-action" action.
-      val file = TestUtils.getTestActionFilename(s"echo.js")
+      val file = TestCLIUtils.getTestActionFilename(s"echo.js")
       wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
 
       var rr = apiCreate(
@@ -800,7 +800,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
     val actionName = testName + "_action"
     try {
       // Create the action for the API.  It must NOT be a "web-action" action for this test
-      val file = TestUtils.getTestActionFilename(s"echo.js")
+      val file = TestCLIUtils.getTestActionFilename(s"echo.js")
       wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT)
 
       val rr = apiCreate(
@@ -828,7 +828,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
     val responseType = "http"
     try {
       // Create the action for the API.  It must be a "web-action" action.
-      val file = TestUtils.getTestActionFilename(s"echo.js")
+      val file = TestCLIUtils.getTestActionFilename(s"echo.js")
       wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
 
       apiCreate(
@@ -868,7 +868,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
     val responseType = "http"
     try {
       // Create the action for the API.  It must be a "web-action" action.
-      val file = TestUtils.getTestActionFilename(s"echo.js")
+      val file = TestCLIUtils.getTestActionFilename(s"echo.js")
       wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
 
       apiCreate(
@@ -898,7 +898,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
     val responseType = "http"
     try {
       // Create the action for the API.  It must be a "web-action" action.
-      val file = TestUtils.getTestActionFilename(s"echo.js")
+      val file = TestCLIUtils.getTestActionFilename(s"echo.js")
       wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
 
       apiCreate(
@@ -926,7 +926,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
     val testurlop = "get"
     val testapiname = testbasepath
     val actionName = "webhttpecho"
-    val swaggerPath = TestUtils.getTestApiGwFilename(s"local.api.yaml")
+    val swaggerPath = TestCLIUtils.getTestApiGwFilename(s"local.api.yaml")
     try {
       var rr = apiCreate(swagger = Some(swaggerPath))
       println("api create stdout: " + rr.stdout)
@@ -945,7 +945,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
   it should "reject creation of an API from invalid YAML formatted API configuration file" in {
     val testName = "CLI_APIGWTEST22"
     val testbasepath = "/" + testName + "_bp"
-    val swaggerPath = TestUtils.getTestApiGwFilename(s"local.api.bad.yaml")
+    val swaggerPath = TestCLIUtils.getTestApiGwFilename(s"local.api.bad.yaml")
     try {
       val rr = apiCreate(swagger = Some(swaggerPath), expectedExitCode = ANY_ERROR_EXIT)
       println("api create stdout: " + rr.stdout)
@@ -969,7 +969,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
     val testbasepath = "/NoActions"
     val testrelpath = "/"
     val testops: Seq[String] = Seq("put", "delete", "get", "head", "options", "patch", "post")
-    val swaggerPath = TestUtils.getTestApiGwFilename(s"endpoints.without.action.swagger.json")
+    val swaggerPath = TestCLIUtils.getTestApiGwFilename(s"endpoints.without.action.swagger.json")
 
     try {
       var rr = apiCreate(swagger = Some(swaggerPath))
@@ -1006,7 +1006,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
 
     try {
       // Create the action for the API.
-      val file = TestUtils.getTestActionFilename(s"echo.js")
+      val file = TestCLIUtils.getTestActionFilename(s"echo.js")
       wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
 
       // Set an invalid auth key
@@ -1028,7 +1028,7 @@ class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach
   it should "list api alphabetically by Base/Rel/Verb" in {
     val baseName = "/BaseTestPathApiList"
     val actionName = "actionName"
-    val file = TestUtils.getTestActionFilename(s"echo-web-http.js")
+    val file = TestCLIUtils.getTestActionFilename(s"echo-web-http.js")
     try {
       // Create Action for apis
       var action =
diff --git a/tests/src/test/scala/whisk/core/cli/test/WskActionSequenceTests.scala b/tests/src/test/scala/whisk/core/cli/test/WskActionSequenceTests.scala
index f48d0ac..012dc01 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskActionSequenceTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskActionSequenceTests.scala
@@ -54,13 +54,13 @@ class WskActionSequenceTests extends TestHelpers with WskTestHelpers {
     }
 
     assetHelper.withCleaner(wsk.action, fullHelloActionName) {
-      val file = Some(TestUtils.getTestActionFilename("hello.js"))
+      val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
       (action, _) =>
         action.create(fullHelloActionName, file)(wp)
     }
 
     assetHelper.withCleaner(wsk.action, fullCatActionName) {
-      val file = Some(TestUtils.getTestActionFilename("cat.js"))
+      val file = Some(TestCLIUtils.getTestActionFilename("cat.js"))
       (action, _) =>
         action.create(fullCatActionName, file)(wp)
     }
diff --git a/tests/src/test/scala/whisk/core/cli/test/WskBasicUsageTests.scala b/tests/src/test/scala/whisk/core/cli/test/WskBasicUsageTests.scala
index 6514963..ba2f865 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskBasicUsageTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskBasicUsageTests.scala
@@ -57,7 +57,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
 
   implicit val wskprops = WskProps()
   val wsk = new Wsk
-  val defaultAction = Some(TestUtils.getTestActionFilename("hello.js"))
+  val defaultAction = Some(TestCLIUtils.getTestActionFilename("hello.js"))
   val usrAgentHeaderRegEx = """\bUser-Agent\b": \[\s+"OpenWhisk\-CLI/1.\d+.*"""
 
   behavior of "Wsk CLI usage"
@@ -150,7 +150,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
   it should "reject action update when specified file is missing" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     // Create dummy action to update
     val name = "updateMissingFile"
-    val file = Some(TestUtils.getTestActionFilename("hello.js"))
+    val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
     assetHelper.withCleaner(wsk.action, name) { (action, name) =>
       action.create(name, file)
     }
@@ -160,7 +160,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
 
   it should "reject action update for sequence with no components" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     val name = "updateMissingComponents"
-    val file = Some(TestUtils.getTestActionFilename("hello.js"))
+    val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
     assetHelper.withCleaner(wsk.action, name) { (action, name) =>
       action.create(name, file)
     }
@@ -170,7 +170,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
   it should "create, and get an action to verify parameter and annotation parsing" in withAssetCleaner(wskprops) {
     (wp, assetHelper) =>
       val name = "actionAnnotations"
-      val file = Some(TestUtils.getTestActionFilename("hello.js"))
+      val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
 
       assetHelper.withCleaner(wsk.action, name) { (action, _) =>
         action.create(name, file, annotations = getValidJSONTestArgInput, parameters = getValidJSONTestArgInput)
@@ -192,8 +192,8 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
   it should "create, and get an action to verify file parameter and annotation parsing" in withAssetCleaner(wskprops) {
     (wp, assetHelper) =>
       val name = "actionAnnotAndParamParsing"
-      val file = Some(TestUtils.getTestActionFilename("hello.js"))
-      val argInput = Some(TestUtils.getTestActionFilename("validInput1.json"))
+      val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
+      val argInput = Some(TestCLIUtils.getTestActionFilename("validInput1.json"))
 
       assetHelper.withCleaner(wsk.action, name) { (action, _) =>
         action.create(name, file, annotationFile = argInput, parameterFile = argInput)
@@ -215,7 +215,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
   it should "create an action with the proper parameter and annotation escapes" in withAssetCleaner(wskprops) {
     (wp, assetHelper) =>
       val name = "actionEscapes"
-      val file = Some(TestUtils.getTestActionFilename("hello.js"))
+      val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
 
       assetHelper.withCleaner(wsk.action, name) { (action, _) =>
         action.create(name, file, parameters = getEscapedJSONTestArgInput, annotations = getEscapedJSONTestArgInput)
@@ -238,7 +238,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
     (wp, assetHelper) =>
       val name = "abort init"
       assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-        action.create(name, Some(TestUtils.getTestActionFilename("initexit.js")))
+        action.create(name, Some(TestCLIUtils.getTestActionFilename("initexit.js")))
       }
 
       withActivation(wsk.activation, wsk.action.invoke(name)) { activation =>
@@ -252,7 +252,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
     (wp, assetHelper) =>
       val name = "hang init"
       assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-        action.create(name, Some(TestUtils.getTestActionFilename("initforever.js")), timeout = Some(3 seconds))
+        action.create(name, Some(TestCLIUtils.getTestActionFilename("initforever.js")), timeout = Some(3 seconds))
       }
 
       withActivation(wsk.activation, wsk.action.invoke(name)) { activation =>
@@ -266,7 +266,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
     (wp, assetHelper) =>
       val name = "abort run"
       assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-        action.create(name, Some(TestUtils.getTestActionFilename("runexit.js")))
+        action.create(name, Some(TestCLIUtils.getTestActionFilename("runexit.js")))
       }
 
       withActivation(wsk.activation, wsk.action.invoke(name)) { activation =>
@@ -308,12 +308,28 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
       N = 5)
   }
 
+  it should "ensure timestamp and stream are stripped from log lines" in withAssetCleaner(wskprops) {
+    val name = "activationLogStripTest"
+    val auth: Seq[String] = Seq("--auth", wskprops.authKey)
+
+    (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, Some(TestCLIUtils.getTestActionFilename("log.js")))
+      }
+
+      withActivation(wsk.activation, wsk.action.invoke(name)) { activation =>
+        val cmd = Seq("activation", "logs", "--strip", activation.activationId)
+        val run = wsk.cli(cmd ++ wskprops.overrides ++ auth, expectedExitCode = SUCCESS_EXIT)
+        run.stdout shouldBe "this is stdout\nthis is stderr\n"
+      }
+  }
+
   it should "ensure keys are not omitted from activation record" in withAssetCleaner(wskprops) {
     val name = "activationRecordTest"
 
     (wp, assetHelper) =>
       assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-        action.create(name, Some(TestUtils.getTestActionFilename("argCheck.js")))
+        action.create(name, Some(TestCLIUtils.getTestActionFilename("argCheck.js")))
       }
 
       val run = wsk.action.invoke(name)
@@ -338,7 +354,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
       assetHelper.withCleaner(wsk.action, name) { (action, _) =>
         action.create(
           name,
-          Some(TestUtils.getTestActionFilename("helloAsync.js")),
+          Some(TestCLIUtils.getTestActionFilename("helloAsync.js")),
           memory = Some(memoryLimit),
           timeout = Some(timeLimit),
           logsize = Some(logLimit))
@@ -353,7 +369,9 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
           "key" -> JsString("limits"),
           "value" -> ActionLimits(TimeLimit(timeLimit), MemoryLimit(memoryLimit), LogLimit(logLimit)).toJson)
 
-        val path = annotations.find { _.fields("key").convertTo[String] == "path" }.get
+        val path = annotations.find {
+          _.fields("key").convertTo[String] == "path"
+        }.get
 
         path.fields("value").convertTo[String] should fullyMatch regex (s""".*/$name""")
         annotations should contain(limitsObj)
@@ -365,7 +383,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
       val rr = assetHelper.withCleaner(wsk.action, "invalid kind", confirmDelete = false) { (action, name) =>
         action.create(
           name,
-          Some(TestUtils.getTestActionFilename("echo.js")),
+          Some(TestCLIUtils.getTestActionFilename("echo.js")),
           kind = Some("foobar"),
           expectedExitCode = BAD_REQUEST)
       }
@@ -375,7 +393,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
   it should "report error when creating an action with zip but without kind" in withAssetCleaner(wskprops) {
     (wp, assetHelper) =>
       val name = "zipWithNoKind"
-      val zippedPythonAction = Some(TestUtils.getTestActionFilename("python.zip"))
+      val zippedPythonAction = Some(TestCLIUtils.getTestActionFilename("python.zip"))
       val createResult = assetHelper.withCleaner(wsk.action, name, confirmDelete = false) { (action, _) =>
         action.create(name, zippedPythonAction, expectedExitCode = ANY_ERROR_EXIT)
       }
@@ -406,69 +424,13 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
           limits.length should be > 0
           limits(0).fields("value") should not be JsNull
         }
-<<<<<<< HEAD
-    }
-
-    it should "reject commands that are executed with a missing or invalid parameter or annotation file" in {
-        val emptyFile = TestCLIUtils.getTestActionFilename("emtpy.js")
-        val missingFile = "notafile"
-        val emptyFileMsg = s"File '$emptyFile' is not a valid file or it does not exist"
-        val missingFileMsg = s"File '$missingFile' is not a valid file or it does not exist"
-        val invalidArgs = Seq(
-            (Seq("action", "create", "actionName", TestCLIUtils.getTestActionFilename("hello.js"), "-P", emptyFile),
-                emptyFileMsg),
-            (Seq("action", "update", "actionName", TestCLIUtils.getTestActionFilename("hello.js"), "-P", emptyFile),
-                emptyFileMsg),
-            (Seq("action", "invoke", "actionName", "-P", emptyFile), emptyFileMsg),
-            (Seq("action", "create", "actionName", "-P", emptyFile), emptyFileMsg),
-            (Seq("action", "update", "actionName", "-P", emptyFile), emptyFileMsg),
-            (Seq("action", "invoke", "actionName", "-P", emptyFile), emptyFileMsg),
-            (Seq("package", "create", "packageName", "-P", emptyFile), emptyFileMsg),
-            (Seq("package", "update", "packageName", "-P", emptyFile), emptyFileMsg),
-            (Seq("package", "bind", "packageName", "boundPackageName", "-P", emptyFile), emptyFileMsg),
-            (Seq("package", "create", "packageName", "-P", emptyFile), emptyFileMsg),
-            (Seq("package", "update", "packageName", "-P", emptyFile), emptyFileMsg),
-            (Seq("package", "bind", "packageName", "boundPackageName", "-P", emptyFile), emptyFileMsg),
-            (Seq("trigger", "create", "triggerName", "-P", emptyFile), emptyFileMsg),
-            (Seq("trigger", "update", "triggerName", "-P", emptyFile), emptyFileMsg),
-            (Seq("trigger", "fire", "triggerName", "-P", emptyFile), emptyFileMsg),
-            (Seq("trigger", "create", "triggerName", "-P", emptyFile), emptyFileMsg),
-            (Seq("trigger", "update", "triggerName", "-P", emptyFile), emptyFileMsg),
-            (Seq("trigger", "fire", "triggerName", "-P", emptyFile), emptyFileMsg),
-            (Seq("action", "create", "actionName", TestCLIUtils.getTestActionFilename("hello.js"), "-A", missingFile),
-                missingFileMsg),
-            (Seq("action", "update", "actionName", TestCLIUtils.getTestActionFilename("hello.js"), "-A", missingFile),
-                missingFileMsg),
-            (Seq("action", "invoke", "actionName", "-A", missingFile), missingFileMsg),
-            (Seq("action", "create", "actionName", "-A", missingFile), missingFileMsg),
-            (Seq("action", "update", "actionName", "-A", missingFile), missingFileMsg),
-            (Seq("action", "invoke", "actionName", "-A", missingFile), missingFileMsg),
-            (Seq("package", "create", "packageName", "-A", missingFile), missingFileMsg),
-            (Seq("package", "update", "packageName", "-A", missingFile), missingFileMsg),
-            (Seq("package", "bind", "packageName", "boundPackageName", "-A", missingFile), missingFileMsg),
-            (Seq("package", "create", "packageName", "-A", missingFile), missingFileMsg),
-            (Seq("package", "update", "packageName", "-A", missingFile), missingFileMsg),
-            (Seq("package", "bind", "packageName", "boundPackageName", "-A", missingFile), missingFileMsg),
-            (Seq("trigger", "create", "triggerName", "-A", missingFile), missingFileMsg),
-            (Seq("trigger", "update", "triggerName", "-A", missingFile), missingFileMsg),
-            (Seq("trigger", "fire", "triggerName", "-A", missingFile), missingFileMsg),
-            (Seq("trigger", "create", "triggerName", "-A", missingFile), missingFileMsg),
-            (Seq("trigger", "update", "triggerName", "-A", missingFile), missingFileMsg),
-            (Seq("trigger", "fire", "triggerName", "-A", missingFile), missingFileMsg))
-
-        invalidArgs foreach {
-            case (cmd, err) =>
-                val stderr = wsk.cli(cmd, expectedExitCode = MISUSE_EXIT).stderr
-                stderr should include(err)
-                stderr should include("Run 'wsk --help' for usage.")
-=======
       }
   }
 
   it should "invoke an action using npm openwhisk" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     val name = "hello npm openwhisk"
     assetHelper.withCleaner(wsk.action, name, confirmDelete = false) { (action, _) =>
-      action.create(name, Some(TestUtils.getTestActionFilename("helloOpenwhiskPackage.js")))
+      action.create(name, Some(TestCLIUtils.getTestActionFilename("helloOpenwhiskPackage.js")))
     }
 
     val run = wsk.action.invoke(name, Map("ignore_certs" -> true.toJson, "name" -> name.toJson))
@@ -485,7 +447,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
     val namespace = wsk.namespace.whois()
     val name = "context"
     assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-      action.create(name, Some(TestUtils.getTestActionFilename("helloContext.js")))
+      action.create(name, Some(TestCLIUtils.getTestActionFilename("helloContext.js")))
     }
 
     val start = Instant.now(Clock.systemUTC()).toEpochMilli
@@ -506,7 +468,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
     (wp, assetHelper) =>
       val name = "invokeResult"
       assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-        action.create(name, Some(TestUtils.getTestActionFilename("echo.js")))
+        action.create(name, Some(TestCLIUtils.getTestActionFilename("echo.js")))
       }
       val args = Map("hello" -> "Robert".toJson)
       val run = wsk.action.invoke(name, args, blocking = true, result = true)
@@ -517,7 +479,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
     (wp, assetHelper) =>
       val name = "deadline"
       assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-        action.create(name, Some(TestUtils.getTestActionFilename("helloDeadline.js")), timeout = Some(3 seconds))
+        action.create(name, Some(TestCLIUtils.getTestActionFilename("helloDeadline.js")), timeout = Some(3 seconds))
       }
 
       val run = wsk.action.invoke(name)
@@ -536,7 +498,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
     (wp, assetHelper) =>
       val name = "timeout"
       assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-        action.create(name, Some(TestUtils.getTestActionFilename("helloDeadline.js")), timeout = Some(3 seconds))
+        action.create(name, Some(TestCLIUtils.getTestActionFilename("helloDeadline.js")), timeout = Some(3 seconds))
       }
 
       val start = Instant.now(Clock.systemUTC()).toEpochMilli
@@ -560,7 +522,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
 
   it should "ensure --web flags set the proper annotations" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     val name = "webaction"
-    val file = Some(TestUtils.getTestActionFilename("echo.js"))
+    val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
 
     assetHelper.withCleaner(wsk.action, name) { (action, _) =>
       action.create(name, file)
@@ -585,7 +547,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
   it should "ensure action update with --web flag only copies existing annotations when new annotations are not provided" in withAssetCleaner(
     wskprops) { (wp, assetHelper) =>
     val name = "webaction"
-    val file = Some(TestUtils.getTestActionFilename("echo.js"))
+    val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
     val createKey = "createKey"
     val createValue = JsString("createValue")
     val updateKey = "updateKey"
@@ -628,7 +590,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
   it should "ensure action update creates an action with --web flag" in withAssetCleaner(wskprops) {
     (wp, assetHelper) =>
       val name = "webaction"
-      val file = Some(TestUtils.getTestActionFilename("echo.js"))
+      val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
 
       assetHelper.withCleaner(wsk.action, name) { (action, _) =>
         action.create(name, file, web = Some("true"), update = true)
@@ -646,7 +608,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
   it should "reject action create and update with invalid web flag input" in withAssetCleaner(wskprops) {
     (wp, assetHelper) =>
       val name = "webaction"
-      val file = Some(TestUtils.getTestActionFilename("echo.js"))
+      val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
       val invalidInput = "bogus"
       val errorMsg =
         s"Invalid argument '$invalidInput' for --web flag. Valid input consist of 'yes', 'true', 'raw', 'false', or 'no'."
@@ -659,7 +621,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
 
   it should "invoke action while not encoding &, <, > characters" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     val name = "nonescape"
-    val file = Some(TestUtils.getTestActionFilename("hello.js"))
+    val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
     val nonescape = "&<>"
     val input = Map("payload" -> nonescape.toJson)
     val output = JsObject("payload" -> JsString(s"hello, $nonescape!"))
@@ -740,7 +702,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
       val params = Seq("-p", "bigValue", "a" * 1000)
 
       assetHelper.withCleaner(wsk.action, name) { (action, _) =>
-        action.create(name, Some(TestUtils.getTestActionFilename("echo.js")))
+        action.create(name, Some(TestCLIUtils.getTestActionFilename("echo.js")))
       }
 
       val truncated = wsk
@@ -851,8 +813,8 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
   it should "create, and get a package to verify file parameter and annotation parsing" in withAssetCleaner(wskprops) {
     (wp, assetHelper) =>
       val name = "packageAnnotAndParamFileParsing"
-      val file = Some(TestUtils.getTestActionFilename("hello.js"))
-      val argInput = Some(TestUtils.getTestActionFilename("validInput1.json"))
+      val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
+      val argInput = Some(TestCLIUtils.getTestActionFilename("validInput1.json"))
 
       assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
         pkg.create(name, annotationFile = argInput, parameterFile = argInput)
@@ -894,7 +856,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
 
   it should "report conformance error accessing action as package" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     val name = "aAsP"
-    val file = Some(TestUtils.getTestActionFilename("hello.js"))
+    val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
     assetHelper.withCleaner(wsk.action, name) { (action, _) =>
       action.create(name, file)
     }
@@ -991,8 +953,8 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
   it should "create, and get a trigger to verify file parameter and annotation parsing" in withAssetCleaner(wskprops) {
     (wp, assetHelper) =>
       val name = "triggerAnnotAndParamFileParsing"
-      val file = Some(TestUtils.getTestActionFilename("hello.js"))
-      val argInput = Some(TestUtils.getTestActionFilename("validInput1.json"))
+      val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
+      val argInput = Some(TestCLIUtils.getTestActionFilename("validInput1.json"))
 
       assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
         trigger.create(name, annotationFile = argInput, parameterFile = argInput)
@@ -1127,7 +1089,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
 
   it should "create, and list an action with a long name" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     val name = "x" * 70
-    val file = Some(TestUtils.getTestActionFilename("hello.js"))
+    val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
     assetHelper.withCleaner(wsk.action, name) { (action, _) =>
       action.create(name, file)
     }
@@ -1200,7 +1162,6 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
         val name = s"${packageName}/${actionName}$i"
         assetHelper.withCleaner(wsk.action, name) { (action, name) =>
           action.create(name, defaultAction)
->>>>>>> c10e681... Apply standard scala formatting. (#2650)
         }
       }
       retry(
@@ -1301,14 +1262,14 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
   it should "reject commands that are executed with invalid JSON for annotations and parameters" in {
     val invalidJSONInputs = getInvalidJSONInput
     val invalidJSONFiles = Seq(
-      TestUtils.getTestActionFilename("malformed.js"),
-      TestUtils.getTestActionFilename("invalidInput1.json"),
-      TestUtils.getTestActionFilename("invalidInput2.json"),
-      TestUtils.getTestActionFilename("invalidInput3.json"),
-      TestUtils.getTestActionFilename("invalidInput4.json"))
+      TestCLIUtils.getTestActionFilename("malformed.js"),
+      TestCLIUtils.getTestActionFilename("invalidInput1.json"),
+      TestCLIUtils.getTestActionFilename("invalidInput2.json"),
+      TestCLIUtils.getTestActionFilename("invalidInput3.json"),
+      TestCLIUtils.getTestActionFilename("invalidInput4.json"))
     val paramCmds = Seq(
-      Seq("action", "create", "actionName", TestUtils.getTestActionFilename("hello.js")),
-      Seq("action", "update", "actionName", TestUtils.getTestActionFilename("hello.js")),
+      Seq("action", "create", "actionName", TestCLIUtils.getTestActionFilename("hello.js")),
+      Seq("action", "update", "actionName", TestCLIUtils.getTestActionFilename("hello.js")),
       Seq("action", "invoke", "actionName"),
       Seq("package", "create", "packageName"),
       Seq("package", "update", "packageName"),
@@ -1317,8 +1278,8 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
       Seq("trigger", "update", "triggerName"),
       Seq("trigger", "fire", "triggerName"))
     val annotCmds = Seq(
-      Seq("action", "create", "actionName", TestUtils.getTestActionFilename("hello.js")),
-      Seq("action", "update", "actionName", TestUtils.getTestActionFilename("hello.js")),
+      Seq("action", "create", "actionName", TestCLIUtils.getTestActionFilename("hello.js")),
+      Seq("action", "update", "actionName", TestCLIUtils.getTestActionFilename("hello.js")),
       Seq("package", "create", "packageName"),
       Seq("package", "update", "packageName"),
       Seq("package", "bind", "packageName", "boundPackageName"),
@@ -1354,16 +1315,16 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
   }
 
   it should "reject commands that are executed with a missing or invalid parameter or annotation file" in {
-    val emptyFile = TestUtils.getTestActionFilename("emtpy.js")
+    val emptyFile = TestCLIUtils.getTestActionFilename("emtpy.js")
     val missingFile = "notafile"
     val emptyFileMsg = s"File '$emptyFile' is not a valid file or it does not exist"
     val missingFileMsg = s"File '$missingFile' is not a valid file or it does not exist"
     val invalidArgs = Seq(
       (
-        Seq("action", "create", "actionName", TestUtils.getTestActionFilename("hello.js"), "-P", emptyFile),
+        Seq("action", "create", "actionName", TestCLIUtils.getTestActionFilename("hello.js"), "-P", emptyFile),
         emptyFileMsg),
       (
-        Seq("action", "update", "actionName", TestUtils.getTestActionFilename("hello.js"), "-P", emptyFile),
+        Seq("action", "update", "actionName", TestCLIUtils.getTestActionFilename("hello.js"), "-P", emptyFile),
         emptyFileMsg),
       (Seq("action", "invoke", "actionName", "-P", emptyFile), emptyFileMsg),
       (Seq("action", "create", "actionName", "-P", emptyFile), emptyFileMsg),
@@ -1382,10 +1343,10 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
       (Seq("trigger", "update", "triggerName", "-P", emptyFile), emptyFileMsg),
       (Seq("trigger", "fire", "triggerName", "-P", emptyFile), emptyFileMsg),
       (
-        Seq("action", "create", "actionName", TestUtils.getTestActionFilename("hello.js"), "-A", missingFile),
+        Seq("action", "create", "actionName", TestCLIUtils.getTestActionFilename("hello.js"), "-A", missingFile),
         missingFileMsg),
       (
-        Seq("action", "update", "actionName", TestUtils.getTestActionFilename("hello.js"), "-A", missingFile),
+        Seq("action", "update", "actionName", TestCLIUtils.getTestActionFilename("hello.js"), "-A", missingFile),
         missingFileMsg),
       (Seq("action", "invoke", "actionName", "-A", missingFile), missingFileMsg),
       (Seq("action", "create", "actionName", "-A", missingFile), missingFileMsg),
@@ -1614,7 +1575,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
 
   it should "create an action with different permutations of limits" in withAssetCleaner(wskprops) {
     (wp, assetHelper) =>
-      val file = Some(TestUtils.getTestActionFilename("hello.js"))
+      val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
 
       def testLimit(timeout: Option[Duration] = None,
                     memory: Option[ByteSize] = None,
diff --git a/tests/src/test/scala/whisk/core/cli/test/WskEntitlementTests.scala b/tests/src/test/scala/whisk/core/cli/test/WskEntitlementTests.scala
index 8140cb4..27310aa 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskEntitlementTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskEntitlementTests.scala
@@ -57,7 +57,7 @@ class WskEntitlementTests extends TestHelpers with WskTestHelpers with BeforeAnd
       val privateAction = "privateAction"
 
       assetHelper.withCleaner(wsk.action, privateAction) { (action, name) =>
-        action.create(name, Some(TestUtils.getTestActionFilename("hello.js")))(wp)
+        action.create(name, Some(TestCLIUtils.getTestActionFilename("hello.js")))(wp)
       }
 
       val fullyQualifiedActionName = s"/$guestNamespace/$privateAction"
@@ -96,7 +96,7 @@ class WskEntitlementTests extends TestHelpers with WskTestHelpers with BeforeAnd
       }
 
       assetHelper.withCleaner(wsk.action, fullSampleActionName) {
-        val file = Some(TestUtils.getTestActionFilename("empty.js"))
+        val file = Some(TestCLIUtils.getTestActionFilename("empty.js"))
         (action, _) =>
           action.create(fullSampleActionName, file)(wp)
       }
@@ -113,7 +113,7 @@ class WskEntitlementTests extends TestHelpers with WskTestHelpers with BeforeAnd
       }
 
       val fullyQualifiedActionName = s"/$guestNamespace/notallowed"
-      val file = Some(TestUtils.getTestActionFilename("empty.js"))
+      val file = Some(TestCLIUtils.getTestActionFilename("empty.js"))
 
       withAssetCleaner(defaultWskProps) { (wp, assetHelper) =>
         assetHelper.withCleaner(wsk.action, fullyQualifiedActionName, confirmDelete = false) { (action, name) =>
@@ -129,7 +129,7 @@ class WskEntitlementTests extends TestHelpers with WskTestHelpers with BeforeAnd
       }
 
       assetHelper.withCleaner(wsk.action, fullSampleActionName) {
-        val file = Some(TestUtils.getTestActionFilename("empty.js"))
+        val file = Some(TestCLIUtils.getTestActionFilename("empty.js"))
         (action, _) =>
           action.create(fullSampleActionName, file)(wp)
       }
@@ -166,7 +166,7 @@ class WskEntitlementTests extends TestHelpers with WskTestHelpers with BeforeAnd
     }
 
     assetHelper.withCleaner(wsk.action, fullSampleActionName) {
-      val file = Some(TestUtils.getTestActionFilename("empty.js"))
+      val file = Some(TestCLIUtils.getTestActionFilename("empty.js"))
       (action, _) =>
         action.create(fullSampleActionName, file, kind = Some("nodejs:default"))(wp)
     }
@@ -224,7 +224,7 @@ class WskEntitlementTests extends TestHelpers with WskTestHelpers with BeforeAnd
     }
 
     assetHelper.withCleaner(wsk.action, fullSampleActionName) {
-      val file = Some(TestUtils.getTestActionFilename("hello.js"))
+      val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
       (action, _) =>
         action.create(fullSampleActionName, file)(wp)
     }
@@ -250,7 +250,7 @@ class WskEntitlementTests extends TestHelpers with WskTestHelpers with BeforeAnd
     }
 
     assetHelper.withCleaner(wsk.action, fullSampleActionName) {
-      val file = Some(TestUtils.getTestActionFilename("hello.js"))
+      val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
       (action, _) =>
         action.create(fullSampleActionName, file)(wp)
     }
@@ -277,7 +277,7 @@ class WskEntitlementTests extends TestHelpers with WskTestHelpers with BeforeAnd
     }
 
     assetHelper.withCleaner(wsk.action, fullSampleActionName) {
-      val file = Some(TestUtils.getTestActionFilename("hello.js"))
+      val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
       (action, _) =>
         action.create(fullSampleActionName, file)(guestwp)
         action.create(s"$privateSamplePackage/$sampleAction", file)(guestwp)
@@ -307,7 +307,7 @@ class WskEntitlementTests extends TestHelpers with WskTestHelpers with BeforeAnd
     }
 
     assetHelper.withCleaner(wsk.action, packagedActionName) {
-      val file = Some(TestUtils.getTestActionFilename("helloContext.js"))
+      val file = Some(TestCLIUtils.getTestActionFilename("helloContext.js"))
       (action, _) =>
         action.create(packagedActionName, file)(guestWskProps)
     }
@@ -332,7 +332,7 @@ class WskEntitlementTests extends TestHelpers with WskTestHelpers with BeforeAnd
 
       val sampleFeed = s"$samplePackage/sampleFeed"
       assetHelper.withCleaner(wsk.action, sampleFeed) {
-        val file = Some(TestUtils.getTestActionFilename("empty.js"))
+        val file = Some(TestCLIUtils.getTestActionFilename("empty.js"))
         (action, _) =>
           action.create(sampleFeed, file, kind = Some("nodejs:default"))(wp)
       }
diff --git a/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala b/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala
index c94c36e..1a8ff04 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala
@@ -45,8 +45,8 @@ import whisk.common.TransactionId
 import whisk.core.entity.Subject
 
 /**
- * Tests web actions.
- */
+  * Tests web actions.
+  */
 @RunWith(classOf[JUnitRunner])
 class WskWebActionsTests extends TestHelpers with WskTestHelpers with RestUtil with BeforeAndAfterAll {
   val MAX_URL_LENGTH = 8192 // 8K matching nginx default
@@ -60,11 +60,11 @@ class WskWebActionsTests extends TestHelpers with WskTestHelpers with RestUtil w
   behavior of "Wsk Web Actions"
 
   /**
-   * Tests web actions, plus max url limit.
-   */
+    * Tests web actions, plus max url limit.
+    */
   it should "create a web action accessible via HTTPS" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     val name = "webaction"
-    val file = Some(TestUtils.getTestActionFilename("echo.js"))
+    val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
     val host = getServiceURL()
     val requestPath = host + s"$testRoutePath/$namespace/default/$name.text/a?a="
     val padAmount = MAX_URL_LENGTH - requestPath.length
@@ -98,12 +98,12 @@ class WskWebActionsTests extends TestHelpers with WskTestHelpers with RestUtil w
   }
 
   /**
-   * Tests web action requiring authentication.
-   */
+    * Tests web action requiring authentication.
+    */
   it should "create a web action requiring authentication accessible via HTTPS" in withAssetCleaner(wskprops) {
     (wp, assetHelper) =>
       val name = "webaction"
-      val file = Some(TestUtils.getTestActionFilename("echo.js"))
+      val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
       val host = getServiceURL()
       val url = s"$host$testRoutePath/$namespace/default/$name.text/__ow_user"
 
@@ -129,7 +129,7 @@ class WskWebActionsTests extends TestHelpers with WskTestHelpers with RestUtil w
   it should "ensure that CORS header is preserved for custom options" in withAssetCleaner(wskprops) {
     (wp, assetHelper) =>
       val name = "webaction"
-      val file = Some(TestUtils.getTestActionFilename("corsHeaderMod.js"))
+      val file = Some(TestCLIUtils.getTestActionFilename("corsHeaderMod.js"))
       val host = getServiceURL()
       val url = host + s"$testRoutePath/$namespace/default/$name.http"
 
@@ -149,7 +149,7 @@ class WskWebActionsTests extends TestHelpers with WskTestHelpers with RestUtil w
 
   it should "ensure that default CORS header is preserved" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     val name = "webaction"
-    val file = Some(TestUtils.getTestActionFilename("corsHeaderMod.js"))
+    val file = Some(TestCLIUtils.getTestActionFilename("corsHeaderMod.js"))
     val host = getServiceURL()
     val url = host + s"$testRoutePath/$namespace/default/$name"
 
@@ -174,7 +174,7 @@ class WskWebActionsTests extends TestHelpers with WskTestHelpers with RestUtil w
   it should "invoke web action to ensure the returned body argument is correct" in withAssetCleaner(wskprops) {
     (wp, assetHelper) =>
       val name = "webaction"
-      val file = Some(TestUtils.getTestActionFilename("echo.js"))
+      val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
       val bodyContent = "This is the body"
       val host = getServiceURL()
       val url = s"$host$testRoutePath/$namespace/default/webaction.text/__ow_body"
@@ -195,7 +195,7 @@ class WskWebActionsTests extends TestHelpers with WskTestHelpers with RestUtil w
   it should "reject invocation of web action with invalid accept header" in withAssetCleaner(wskprops) {
     (wp, assetHelper) =>
       val name = "webaction"
-      val file = Some(TestUtils.getTestActionFilename("textBody.js"))
+      val file = Some(TestCLIUtils.getTestActionFilename("textBody.js"))
       val host = getServiceURL()
       val url = host + s"$testRoutePath/$namespace/default/$name.http"
 
@@ -210,7 +210,7 @@ class WskWebActionsTests extends TestHelpers with WskTestHelpers with RestUtil w
 
   it should "support multiple response header values" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     val name = "webaction"
-    val file = Some(TestUtils.getTestActionFilename("multipleHeaders.js"))
+    val file = Some(TestCLIUtils.getTestActionFilename("multipleHeaders.js"))
     val host = getServiceURL()
     val url = host + s"$testRoutePath/$namespace/default/$name.http"
 
@@ -230,7 +230,7 @@ class WskWebActionsTests extends TestHelpers with WskTestHelpers with RestUtil w
 
   it should "handle http web action with base64 encoded response" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
     val name = "base64Web"
-    val file = Some(TestUtils.getTestActionFilename("base64Web.js"))
+    val file = Some(TestCLIUtils.getTestActionFilename("base64Web.js"))
     val host = getServiceURL
     val url = host + s"$testRoutePath/$namespace/default/$name.http"
 
@@ -248,7 +248,7 @@ class WskWebActionsTests extends TestHelpers with WskTestHelpers with RestUtil w
   it should "handle http web action with base64 encoded binary response" in withAssetCleaner(wskprops) {
     (wp, assetHelper) =>
       val name = "binaryWeb"
-      val file = Some(TestUtils.getTestActionFilename("pngWeb.js"))
+      val file = Some(TestCLIUtils.getTestActionFilename("pngWeb.js"))
       val host = getServiceURL
       val url = host + s"$testRoutePath/$namespace/default/$name.http"
       val png = "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAGCAYAAAD68A/GAAAA/klEQVQYGWNgAAEHBxaG//+ZQMyyn581Pfas+cRQnf1LfF" +
@@ -300,7 +300,7 @@ class WskWebActionsTests extends TestHelpers with WskTestHelpers with RestUtil w
     (wp, assetHelper) =>
       val actionName = "webaction"
 
-      val file = Some(TestUtils.getTestActionFilename("echo.js"))
+      val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
       assetHelper.withCleaner(wsk.action, actionName) { (action, _) =>
         action.create(actionName, file, web = Some(true.toString))(wp)
       }
diff --git a/wski18n/i18n_resources.go b/wski18n/i18n_resources.go
index 000257d..72f9ec4 100644
--- a/wski18n/i18n_resources.go
+++ b/wski18n/i18n_resources.go
@@ -109,7 +109,7 @@ func wski18nResourcesDe_deAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/de_DE.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1505508829, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/de_DE.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1500156058, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -129,7 +129,7 @@ func wski18nResourcesEn_usAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/en_US.all.json", size: 50955, mode: os.FileMode(420), modTime: time.Unix(1505509004, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/en_US.all.json", size: 50955, mode: os.FileMode(420), modTime: time.Unix(1505616931, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -149,7 +149,7 @@ func wski18nResourcesEs_esAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/es_ES.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1505508829, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/es_ES.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1500156058, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -169,7 +169,7 @@ func wski18nResourcesFr_frAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/fr_FR.all.json", size: 101, mode: os.FileMode(420), modTime: time.Unix(1505508829, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/fr_FR.all.json", size: 101, mode: os.FileMode(420), modTime: time.Unix(1500156058, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -189,7 +189,7 @@ func wski18nResourcesIt_itAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/it_IT.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1505508829, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/it_IT.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1500156058, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -209,7 +209,7 @@ func wski18nResourcesJa_jaAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/ja_JA.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1505508829, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/ja_JA.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1500156058, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -229,7 +229,7 @@ func wski18nResourcesKo_krAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/ko_KR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1505508829, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/ko_KR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1500156058, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -249,7 +249,7 @@ func wski18nResourcesPt_brAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/pt_BR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1505508829, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/pt_BR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1500156058, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -269,7 +269,7 @@ func wski18nResourcesZh_hansAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/zh_Hans.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1505508829, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/zh_Hans.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1500156058, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -289,7 +289,7 @@ func wski18nResourcesZh_hantAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/zh_Hant.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1505508829, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/zh_Hant.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1500156058, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 09/16: API gw test cleanup (#2493)

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csantanapr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git

commit 6101281af08d0f3dcbf5a1fad35026b996a94f4a
Author: rodric rabbah <ro...@gmail.com>
AuthorDate: Tue Sep 5 15:05:21 2017 -0400

    API gw test cleanup (#2493)
    
    * Replace unnecessary vars.
    Refactor check throttle.
    
    * Review comments.
---
 .../apigw/healthtests/ApiGwEndToEndTests.scala     |  22 +-
 .../scala/whisk/core/cli/test/ApiGwTests.scala     | 341 ++++++++++-----------
 2 files changed, 173 insertions(+), 190 deletions(-)

diff --git a/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala b/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala
index dd70b6d..332a5ca 100644
--- a/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala
+++ b/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala
@@ -97,11 +97,10 @@ class ApiGwEndToEndTests
                 action = Some(actionName),
                 apiname = Some(testapiname),
                 responsetype = Some("http"),
-                cliCfgFile = Some(cliWskPropsFile.getCanonicalPath())
-            )
+                cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
             rr.stdout should include("ok: created API")
             val apiurl = rr.stdout.split("\n")(1)
-            println(s"apiurl: '${apiurl}'")
+            println(s"apiurl: '$apiurl'")
 
             // Validate the API was successfully created
             // List result will look like:
@@ -112,17 +111,15 @@ class ApiGwEndToEndTests
                 basepathOrApiName = Some(testbasepath),
                 relpath = Some(testrelpath),
                 operation = Some(testurlop),
-                cliCfgFile = Some(cliWskPropsFile.getCanonicalPath())
-            )
+                cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
             rr.stdout should include("ok: APIs")
-            rr.stdout should include regex (s"${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+            rr.stdout should include regex (s"$actionName\\s+$testurlop\\s+$testapiname\\s+")
             rr.stdout should include(testbasepath + testrelpath)
 
             // Recreate the API using a JSON swagger file
             rr = wsk.api.get(
                 basepathOrApiName = Some(testbasepath),
-                cliCfgFile = Some(cliWskPropsFile.getCanonicalPath())
-            )
+                cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
             val swaggerfile = File.createTempFile("api", ".json")
             swaggerfile.deleteOnExit()
             val bw = new BufferedWriter(new FileWriter(swaggerfile))
@@ -133,14 +130,12 @@ class ApiGwEndToEndTests
             val deleteApiResult = wsk.api.delete(
                 basepathOrApiName = testbasepath,
                 expectedExitCode = DONTCARE_EXIT,
-                cliCfgFile = Some(cliWskPropsFile.getCanonicalPath())
-            )
+                cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
 
             // Create the API again, but use the swagger file this time
             rr = wsk.api.create(
                 swagger = Some(swaggerfile.getAbsolutePath()),
-                cliCfgFile = Some(cliWskPropsFile.getCanonicalPath())
-            )
+                cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
             rr.stdout should include("ok: created API")
             val swaggerapiurl = rr.stdout.split("\n")(1)
             println(s"Returned api url: '${swaggerapiurl}'")
@@ -169,8 +164,7 @@ class ApiGwEndToEndTests
             val finallydeleteApiResult = wsk.api.delete(
                 basepathOrApiName = testbasepath,
                 expectedExitCode = DONTCARE_EXIT,
-                cliCfgFile = Some(cliWskPropsFile.getCanonicalPath())
-            )
+                cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
         }
     }
 }
diff --git a/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala b/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
index e99c88f..77943c5 100644
--- a/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
@@ -21,11 +21,16 @@ import java.io.File
 import java.io.BufferedWriter
 import java.io.FileWriter
 import java.time.Instant
+
 import scala.collection.mutable.ArrayBuffer
 import scala.concurrent.duration._
+
 import org.junit.runner.RunWith
+
 import org.scalatest.BeforeAndAfterAll
+import org.scalatest.BeforeAndAfterEach
 import org.scalatest.junit.JUnitRunner
+
 import common.TestHelpers
 import common.TestUtils._
 import common.TestCLIUtils
@@ -41,9 +46,10 @@ import common.WskTestHelpers
 class ApiGwTests
     extends TestHelpers
     with WskTestHelpers
+    with BeforeAndAfterEach
     with BeforeAndAfterAll {
 
-    implicit var wskprops = WskProps()
+    implicit val wskprops = WskProps()
     val wsk = new Wsk
     val clinamespace = wsk.namespace.whois()
 
@@ -58,23 +64,23 @@ class ApiGwTests
     val cliWskPropsFile = File.createTempFile("wskprops", ".tmp")
 
     /**
-      * Expected to be called before or after each CLI invocation
-      * If number of CLI invocations in this suite have reached the throttle limit
-      * then pause the test for enough time so that the throttle restriction is gone
-      */
-    def checkThrottle(maxInvocationsBeforeThrottle: Int = maxActionsPerMin) = {
-        var t = Instant.now
-        var tminus60 = t.minusSeconds(60)
-        var invocationsLast60Seconds = invocationTimes.filter(_.isAfter(tminus60)).sorted
-        var invocationCount = invocationsLast60Seconds.length
+     * Expected to be called before each test.
+     * Assumes that each test will not invoke more than 5 actions and
+     * settle the throttle when there isn't enough capacity to handle the test.
+     */
+    def checkThrottle(maxInvocationsBeforeThrottle: Int = maxActionsPerMin, expectedActivationsPerTest: Int = 5) = {
+        val t = Instant.now
+        val tminus60 = t.minusSeconds(60)
+        val invocationsLast60Seconds = invocationTimes.filter(_.isAfter(tminus60)).sorted
+        val invocationCount = invocationsLast60Seconds.length
         println(s"Action invokes within last minute: ${invocationCount}")
 
-        if (invocationCount >= maxInvocationsBeforeThrottle) {
+        if (invocationCount + expectedActivationsPerTest >= maxInvocationsBeforeThrottle) {
             // Instead of waiting a fixed 60 seconds to settle the throttle,
             // calculate a wait time that will clear out about half of the
             // current invocations (assuming even distribution) from the
             // next 60 second period.
-            var oldestInvocationInLast60Seconds = invocationsLast60Seconds.head
+            val oldestInvocationInLast60Seconds = invocationsLast60Seconds.head
 
             // Take the oldest invocation time in this 60 second period.  To clear
             // this invocation from the next 60 second period, the wait time will be
@@ -82,18 +88,22 @@ class ApiGwTests
             // This will clear all of the invocations from the next period at the
             // expense of potentially waiting uncessarily long. Instead, this calculation
             // halves the delta time as a compromise.
-            var throttleTime =  60.seconds.toMillis - ((t.toEpochMilli - oldestInvocationInLast60Seconds.toEpochMilli) /2)
+            val throttleTime = 60.seconds.toMillis - ((t.toEpochMilli - oldestInvocationInLast60Seconds.toEpochMilli) / 2)
             println(s"Waiting ${throttleTime} milliseconds to settle the throttle")
             Thread.sleep(throttleTime)
         }
+
         invocationTimes += Instant.now
     }
 
+    override def beforeEach() = {
+        checkThrottle()
+    }
+
     /*
      * Create a CLI properties file for use by the tests
      */
     override def beforeAll() = {
-        //cliWskPropsFile = File.createTempFile("wskprops", ".tmp")
         cliWskPropsFile.deleteOnExit()
         val wskprops = WskProps(token = "SOME TOKEN")
         wskprops.writeFile(cliWskPropsFile)
@@ -118,10 +128,8 @@ class ApiGwTests
         swagger: Option[String] = None,
         responsetype: Option[String] = None,
         expectedExitCode: Int = SUCCESS_EXIT,
-        cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath())): RunResult = {
-
-        checkThrottle()
-        wsk.api.create(basepath, relpath, operation, action, apiname, swagger, responsetype, expectedExitCode, cliCfgFile)
+        cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath()))(implicit wskpropsOverride: WskProps): RunResult = {
+        wsk.api.create(basepath, relpath, operation, action, apiname, swagger, responsetype, expectedExitCode, cliCfgFile)(wskpropsOverride)
     }
 
     def apiList(
@@ -134,8 +142,6 @@ class ApiGwTests
         nameSort: Option[Boolean] = None,
         expectedExitCode: Int = SUCCESS_EXIT,
         cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath())): RunResult = {
-
-        checkThrottle()
         wsk.api.list(basepathOrApiName, relpath, operation, limit, since, full, nameSort, expectedExitCode, cliCfgFile)
     }
 
@@ -145,8 +151,6 @@ class ApiGwTests
         expectedExitCode: Int = SUCCESS_EXIT,
         cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath()),
         format: Option[String] = None): RunResult = {
-
-        checkThrottle()
         wsk.api.get(basepathOrApiName, full, expectedExitCode, cliCfgFile, format)
     }
 
@@ -156,8 +160,6 @@ class ApiGwTests
         operation: Option[String] = None,
         expectedExitCode: Int = SUCCESS_EXIT,
         cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath())): RunResult = {
-
-        checkThrottle()
         wsk.api.delete(basepathOrApiName, relpath, operation, expectedExitCode, cliCfgFile)
     }
 
@@ -167,13 +169,13 @@ class ApiGwTests
         val badpath = "badpath"
 
         var rr = apiCreate(basepath = Some("/basepath"), relpath = Some(badpath), operation = Some("GET"), action = Some("action"), expectedExitCode = ANY_ERROR_EXIT)
-        rr.stderr should include (s"'${badpath}' must begin with '/'")
+        rr.stderr should include(s"'${badpath}' must begin with '/'")
 
         rr = apiDelete(basepathOrApiName = "/basepath", relpath = Some(badpath), operation = Some("GET"), expectedExitCode = ANY_ERROR_EXIT)
-        rr.stderr should include (s"'${badpath}' must begin with '/'")
+        rr.stderr should include(s"'${badpath}' must begin with '/'")
 
         rr = apiList(basepathOrApiName = Some("/basepath"), relpath = Some(badpath), operation = Some("GET"), expectedExitCode = ANY_ERROR_EXIT)
-        rr.stderr should include (s"'${badpath}' must begin with '/'")
+        rr.stderr should include(s"'${badpath}' must begin with '/'")
     }
 
     it should "reject an api commands with an invalid verb parameter" in {
@@ -192,7 +194,7 @@ class ApiGwTests
     it should "reject an api create command that specifies a nonexistent configuration file" in {
         val configfile = "/nonexistent/file"
 
-        var rr = apiCreate(swagger = Some(configfile), expectedExitCode = ANY_ERROR_EXIT)
+        val rr = apiCreate(swagger = Some(configfile), expectedExitCode = ANY_ERROR_EXIT)
         rr.stderr should include(s"Error reading swagger file '${configfile}':")
     }
 
@@ -205,7 +207,7 @@ class ApiGwTests
         bw.write("a=A")
         bw.close()
 
-        var rr = apiCreate(swagger = Some(filename), expectedExitCode = ANY_ERROR_EXIT)
+        val rr = apiCreate(swagger = Some(filename), expectedExitCode = ANY_ERROR_EXIT)
         rr.stderr should include(s"Error parsing swagger file '${filename}':")
     }
 
@@ -230,7 +232,7 @@ class ApiGwTests
                     |}""".stripMargin)
         bw.close()
 
-        var rr = apiCreate(swagger = Some(filename), expectedExitCode = ANY_ERROR_EXIT)
+        val rr = apiCreate(swagger = Some(filename), expectedExitCode = ANY_ERROR_EXIT)
         rr.stderr should include(s"Swagger file is invalid (missing basePath, info, paths, or swagger fields")
     }
 
@@ -261,23 +263,22 @@ class ApiGwTests
             rr.stdout should include regex (s"API Name:\\s+${testapiname}\n")
             rr.stdout should include regex (s"URL:\\s+")
             rr.stdout should include(testbasepath + testrelpath)
-        }
-        finally {
-            val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            val deleteresult = apiDelete(basepathOrApiName = testbasepath)
+        } finally {
+            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath)
         }
     }
 
     it should "verify successful creation and deletion of a new API" in {
         val testName = "CLI_APIGWTEST1"
-        val testbasepath = "/"+testName+"_bp"
+        val testbasepath = "/" + testName + "_bp"
         val testrelpath = "/path/with/sub_paths/in/it"
         val testnewrelpath = "/path_new"
         val testurlop = "get"
-        val testapiname = testName+" API Name"
-        val actionName = testName+"_action"
+        val testapiname = testName + " API Name"
+        val actionName = testName + "_action"
         try {
-            println("cli namespace: "+clinamespace)
+            println("cli namespace: " + clinamespace)
 
             // Create the action for the API.  It must be a "web-action" action.
             val file = TestCLIUtils.getTestActionFilename(s"echo.js")
@@ -293,21 +294,20 @@ class ApiGwTests
             rr.stdout should include regex (s""""operationId":\\s+"getPathWithSub_pathsInIt"""")
             val deleteresult = apiDelete(basepathOrApiName = testbasepath)
             deleteresult.stdout should include("ok: deleted API")
-        }
-        finally {
-            val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+        } finally {
+            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
     it should "verify get API name " in {
         val testName = "CLI_APIGWTEST3"
-        val testbasepath = "/"+testName+"_bp"
+        val testbasepath = "/" + testName + "_bp"
         val testrelpath = "/path"
         val testnewrelpath = "/path_new"
         val testurlop = "get"
-        val testapiname = testName+" API Name"
-        val actionName = testName+"_action"
+        val testapiname = testName + " API Name"
+        val actionName = testName + "_action"
         try {
             // Create the action for the API.  It must be a "web-action" action.
             val file = TestCLIUtils.getTestActionFilename(s"echo.js")
@@ -320,21 +320,20 @@ class ApiGwTests
             rr.stdout should include(s"${actionName}")
             rr.stdout should include regex (""""cors":\s*\{\s*\n\s*"enabled":\s*true""")
             rr.stdout should include regex (s""""target-url":\\s+.*${actionName}.json""")
-        }
-        finally {
-            val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+        } finally {
+            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
     it should "verify delete API name " in {
         val testName = "CLI_APIGWTEST4"
-        val testbasepath = "/"+testName+"_bp"
+        val testbasepath = "/" + testName + "_bp"
         val testrelpath = "/path"
         val testnewrelpath = "/path_new"
         val testurlop = "get"
-        val testapiname = testName+" API Name"
-        val actionName = testName+"_action"
+        val testapiname = testName + " API Name"
+        val actionName = testName + "_action"
         try {
             // Create the action for the API.  It must be a "web-action" action.
             val file = TestCLIUtils.getTestActionFilename(s"echo.js")
@@ -344,21 +343,20 @@ class ApiGwTests
             rr.stdout should include("ok: created API")
             rr = apiDelete(basepathOrApiName = testapiname)
             rr.stdout should include("ok: deleted API")
-        }
-        finally {
-            val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+        } finally {
+            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
     it should "verify delete API basepath " in {
         val testName = "CLI_APIGWTEST5"
-        val testbasepath = "/"+testName+"_bp"
+        val testbasepath = "/" + testName + "_bp"
         val testrelpath = "/path"
         val testnewrelpath = "/path_new"
         val testurlop = "get"
-        val testapiname = testName+" API Name"
-        val actionName = testName+"_action"
+        val testapiname = testName + " API Name"
+        val actionName = testName + "_action"
         try {
             // Create the action for the API.  It must be a "web-action" action.
             val file = TestCLIUtils.getTestActionFilename(s"echo.js")
@@ -368,21 +366,20 @@ class ApiGwTests
             rr.stdout should include("ok: created API")
             rr = apiDelete(basepathOrApiName = testbasepath)
             rr.stdout should include("ok: deleted API")
-        }
-        finally {
-            val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+        } finally {
+            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
     it should "verify adding endpoints to existing api" in {
         val testName = "CLI_APIGWTEST6"
-        val testbasepath = "/"+testName+"_bp"
+        val testbasepath = "/" + testName + "_bp"
         val testrelpath = "/path2"
         val testnewrelpath = "/path_new"
         val testurlop = "get"
-        val testapiname = testName+" API Name"
-        val actionName = testName+"_action"
+        val testapiname = testName + " API Name"
+        val actionName = testName + "_action"
         val newEndpoint = "/newEndpoint"
         try {
             // Create the action for the API.  It must be a "web-action" action.
@@ -398,48 +395,46 @@ class ApiGwTests
             rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
             rr.stdout should include(testbasepath + testrelpath)
             rr.stdout should include(testbasepath + newEndpoint)
-        }
-        finally {
-            val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+        } finally {
+            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
     it should "verify successful creation with swagger doc as input" in {
         // NOTE: These values must match the swagger file contents
         val testName = "CLI_APIGWTEST7"
-        val testbasepath = "/"+testName+"_bp"
+        val testbasepath = "/" + testName + "_bp"
         val testrelpath = "/path"
         val testurlop = "get"
-        val testapiname = testName+" API Name"
-        val actionName = testName+"_action"
+        val testapiname = testName + " API Name"
+        val actionName = testName + "_action"
         val swaggerPath = TestCLIUtils.getTestApiGwFilename("testswaggerdoc1")
         try {
             var rr = apiCreate(swagger = Some(swaggerPath))
             rr.stdout should include("ok: created API")
             rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
-            println("list stdout: "+rr.stdout)
-            println("list stderr: "+rr.stderr)
+            println("list stdout: " + rr.stdout)
+            println("list stderr: " + rr.stderr)
             rr.stdout should include("ok: APIs")
             // Actual CLI namespace will vary from local dev to automated test environments, so don't check
             rr.stdout should include regex (s"/[@\\w._\\-]+/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
             rr.stdout should include(testbasepath + testrelpath)
-        }
-        finally {
-            val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+        } finally {
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
     it should "verify adding endpoints to two existing apis" in {
         val testName = "CLI_APIGWTEST8"
-        val testbasepath = "/"+testName+"_bp"
-        val testbasepath2 = "/"+testName+"_bp2"
+        val testbasepath = "/" + testName + "_bp"
+        val testbasepath2 = "/" + testName + "_bp2"
         val testrelpath = "/path2"
         val testnewrelpath = "/path_new"
         val testurlop = "get"
-        val testapiname = testName+" API Name"
-        val testapiname2 = testName+" API Name 2"
-        val actionName = testName+"_action"
+        val testapiname = testName + " API Name"
+        val testapiname2 = testName + " API Name 2"
+        val actionName = testName + "_action"
         val newEndpoint = "/newEndpoint"
         try {
             // Create the action for the API.  It must be a "web-action" action.
@@ -468,11 +463,10 @@ class ApiGwTests
             rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
             rr.stdout should include(testbasepath2 + testrelpath)
             rr.stdout should include(testbasepath2 + newEndpoint)
-        }
-        finally {
-            val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            var deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-            deleteresult = apiDelete(basepathOrApiName = testbasepath2, expectedExitCode = DONTCARE_EXIT)
+        } finally {
+            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath2, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
@@ -484,10 +478,11 @@ class ApiGwTests
         val testrelpath = "/path"
         val testnewrelpath = "/path_new"
         val testurlop = "get"
-        val testapiname = testName+" API Name"
-        val actionName = testName+"a-c@t ion"
+        val testapiname = testName + " API Name"
+        val actionName = testName + "a-c@t ion"
         try {
-            println("cli namespace: "+clinamespace)
+            println("cli namespace: " + clinamespace)
+
             // Create the action for the API.  It must be a "web-action" action.
             val file = TestCLIUtils.getTestActionFilename(s"echo.js")
             wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
@@ -500,10 +495,9 @@ class ApiGwTests
             rr.stdout should include(testbasepath + testrelpath)
             val deleteresult = apiDelete(basepathOrApiName = testbasepath)
             deleteresult.stdout should include("ok: deleted API")
-        }
-        finally {
-            val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+        } finally {
+            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
@@ -517,12 +511,12 @@ class ApiGwTests
         val actionName = testName + "_action"
         val swaggerPath = TestCLIUtils.getTestApiGwFilename(s"testswaggerdocinvalid")
         try {
-            var rr = apiCreate(swagger = Some(swaggerPath), expectedExitCode = ANY_ERROR_EXIT)
+            val rr = apiCreate(swagger = Some(swaggerPath), expectedExitCode = ANY_ERROR_EXIT)
             println("api create stdout: " + rr.stdout)
             println("api create stderr: " + rr.stderr)
             rr.stderr should include(s"Swagger file is invalid")
         } finally {
-            val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
@@ -544,14 +538,14 @@ class ApiGwTests
             var rr2 = apiCreate(basepath = Some(testbasepath), relpath = Some(testnewrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
             rr2.stdout should include("ok: created API")
             rr = apiDelete(basepathOrApiName = testbasepath, relpath = Some(testrelpath))
-            rr.stdout should include("ok: deleted " + testrelpath +" from "+ testbasepath)
+            rr.stdout should include("ok: deleted " + testrelpath + " from " + testbasepath)
             rr2 = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testnewrelpath))
             rr2.stdout should include("ok: APIs")
             rr2.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
             rr2.stdout should include(testbasepath + testnewrelpath)
         } finally {
-            val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
@@ -577,13 +571,13 @@ class ApiGwTests
             rr.stdout should include("ok: APIs")
             rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
             rr.stdout should include(testbasepath + testrelpath)
-            rr = apiDelete(basepathOrApiName = testbasepath,relpath = Some(testrelpath), operation = Some(testurlop2))
-            rr.stdout should include("ok: deleted " + testrelpath + " " + "POST" +" from "+ testbasepath)
+            rr = apiDelete(basepathOrApiName = testbasepath, relpath = Some(testrelpath), operation = Some(testurlop2))
+            rr.stdout should include("ok: deleted " + testrelpath + " " + "POST" + " from " + testbasepath)
             rr = apiList(basepathOrApiName = Some(testbasepath))
             rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
         } finally {
-            val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
@@ -608,7 +602,7 @@ class ApiGwTests
             rr.stdout should include(testbasepath + testrelpath)
             rr.stdout should include(testbasepath + testrelpath2)
         } finally {
-            val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
@@ -648,26 +642,25 @@ class ApiGwTests
             rr = apiDelete(basepathOrApiName = testbasepath)
             rr.stdout should include("ok: deleted API")
         } finally {
-            val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            var deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-            deleteresult = apiDelete(basepathOrApiName = testbasepath2, expectedExitCode = DONTCARE_EXIT)
+            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath2, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
     it should "reject an API created with a non-existent action" in {
         val testName = "CLI_APIGWTEST15"
-        val testbasepath = "/"+testName+"_bp"
+        val testbasepath = "/" + testName + "_bp"
         val testrelpath = "/path"
         val testnewrelpath = "/path_new"
         val testurlop = "get"
-        val testapiname = testName+" API Name"
-        val actionName = testName+"_action"
+        val testapiname = testName + " API Name"
+        val actionName = testName + "_action"
         try {
-            var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname), expectedExitCode = ANY_ERROR_EXIT)
+            val rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname), expectedExitCode = ANY_ERROR_EXIT)
             rr.stderr should include("does not exist")
-        }
-        finally {
-            val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+        } finally {
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
@@ -684,119 +677,116 @@ class ApiGwTests
             val file = TestCLIUtils.getTestActionFilename(s"echo.js")
             wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT)
 
-            var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname), expectedExitCode = ANY_ERROR_EXIT)
+            val rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname), expectedExitCode = ANY_ERROR_EXIT)
             rr.stderr should include("is not a web action")
         } finally {
-            val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            var deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
     it should "verify API with http response type " in {
         val testName = "CLI_APIGWTEST17"
-        val testbasepath = "/"+testName+"_bp"
+        val testbasepath = "/" + testName + "_bp"
         val testrelpath = "/path"
         val testnewrelpath = "/path_new"
         val testurlop = "get"
-        val testapiname = testName+" API Name"
-        val actionName = testName+"_action"
+        val testapiname = testName + " API Name"
+        val actionName = testName + "_action"
         val responseType = "http"
         try {
             // Create the action for the API.  It must be a "web-action" action.
             val file = TestCLIUtils.getTestActionFilename(s"echo.js")
             wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
 
-            var rr = apiCreate(
+            apiCreate(
                 basepath = Some(testbasepath),
                 relpath = Some(testrelpath),
                 operation = Some(testurlop),
                 action = Some(actionName),
                 apiname = Some(testapiname),
-                responsetype = Some(responseType)
-            )
-            rr.stdout should include("ok: created API")
-            rr = apiGet(basepathOrApiName = Some(testapiname))
+                responsetype = Some(responseType))
+                .stdout should include("ok: created API")
+
+            val rr = apiGet(basepathOrApiName = Some(testapiname))
             rr.stdout should include(testbasepath)
             rr.stdout should include(s"${actionName}")
             rr.stdout should include regex (s""""target-url":\\s+.*${actionName}.${responseType}""")
-        }
-        finally {
-            val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+        } finally {
+            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
     it should "reject API export when export type is invalid" in {
         val testName = "CLI_APIGWTEST18"
-        val testbasepath = "/"+testName+"_bp"
+        val testbasepath = "/" + testName + "_bp"
 
-        var rr = apiGet(basepathOrApiName = Some(testbasepath), format = Some("BadType"), expectedExitCode = ANY_ERROR_EXIT)
+        val rr = apiGet(basepathOrApiName = Some(testbasepath), format = Some("BadType"), expectedExitCode = ANY_ERROR_EXIT)
         rr.stderr should include("Invalid format type")
     }
 
     it should "successfully export an API in YAML format" in {
         val testName = "CLI_APIGWTEST19"
-        val testbasepath = "/"+testName+"_bp"
+        val testbasepath = "/" + testName + "_bp"
         val testrelpath = "/path"
         val testnewrelpath = "/path_new"
         val testurlop = "get"
-        val testapiname = testName+" API Name"
-        val actionName = testName+"_action"
+        val testapiname = testName + " API Name"
+        val actionName = testName + "_action"
         val responseType = "http"
         try {
             // Create the action for the API.  It must be a "web-action" action.
             val file = TestCLIUtils.getTestActionFilename(s"echo.js")
             wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
 
-            var rr = apiCreate(
+            apiCreate(
                 basepath = Some(testbasepath),
                 relpath = Some(testrelpath),
                 operation = Some(testurlop),
                 action = Some(actionName),
                 apiname = Some(testapiname),
-                responsetype = Some(responseType)
-            )
-            rr.stdout should include("ok: created API")
-            rr = apiGet(basepathOrApiName = Some(testapiname), format = Some("yaml"))
-            rr.stdout should include (s"basePath: ${testbasepath}")
-        }
-        finally {
-            val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+                responsetype = Some(responseType))
+                .stdout should include("ok: created API")
+
+            val rr = apiGet(basepathOrApiName = Some(testapiname), format = Some("yaml"))
+            rr.stdout should include(s"basePath: ${testbasepath}")
+        } finally {
+            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
     it should "successfully export an API when JSON format is explcitly specified" in {
         val testName = "CLI_APIGWTEST20"
-        val testbasepath = "/"+testName+"_bp"
+        val testbasepath = "/" + testName + "_bp"
         val testrelpath = "/path"
         val testnewrelpath = "/path_new"
         val testurlop = "get"
-        val testapiname = testName+" API Name"
-        val actionName = testName+"_action"
+        val testapiname = testName + " API Name"
+        val actionName = testName + "_action"
         val responseType = "http"
         try {
             // Create the action for the API.  It must be a "web-action" action.
             val file = TestCLIUtils.getTestActionFilename(s"echo.js")
             wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
 
-            var rr = apiCreate(
+            apiCreate(
                 basepath = Some(testbasepath),
                 relpath = Some(testrelpath),
                 operation = Some(testurlop),
                 action = Some(actionName),
                 apiname = Some(testapiname),
-                responsetype = Some(responseType)
-            )
-            rr.stdout should include("ok: created API")
-            rr = apiGet(basepathOrApiName = Some(testapiname), format = Some("json"))
+                responsetype = Some(responseType))
+                .stdout should include("ok: created API")
+
+            val rr = apiGet(basepathOrApiName = Some(testapiname), format = Some("json"))
             rr.stdout should include(testbasepath)
             rr.stdout should include(s"${actionName}")
             rr.stdout should include regex (s""""target-url":\\s+.*${actionName}.${responseType}""")
-        }
-        finally {
-            val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+        } finally {
+            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
@@ -819,34 +809,34 @@ class ApiGwTests
             rr.stdout should include regex (s"/[@\\w._\\-]+/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
             rr.stdout should include(testbasepath + testrelpath)
         } finally {
-            val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
     it should "reject creation of an API from invalid YAML formatted API configuration file" in {
         val testName = "CLI_APIGWTEST22"
-        val testbasepath = "/"+testName+"_bp"
+        val testbasepath = "/" + testName + "_bp"
         val swaggerPath = TestCLIUtils.getTestApiGwFilename(s"local.api.bad.yaml")
         try {
-            var rr = apiCreate(swagger = Some(swaggerPath), expectedExitCode = ANY_ERROR_EXIT)
+            val rr = apiCreate(swagger = Some(swaggerPath), expectedExitCode = ANY_ERROR_EXIT)
             println("api create stdout: " + rr.stdout)
             println("api create stderror: " + rr.stderr)
             rr.stderr should include("Unable to parse YAML configuration file")
         } finally {
-            val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
     it should "reject deletion of a non-existent api" in {
         val nonexistentApi = "/not-there"
 
-        var rr = apiDelete(basepathOrApiName = nonexistentApi, expectedExitCode = ANY_ERROR_EXIT)
-        rr.stderr should include (s"API '${nonexistentApi}' does not exist")
+        val rr = apiDelete(basepathOrApiName = nonexistentApi, expectedExitCode = ANY_ERROR_EXIT)
+        rr.stderr should include(s"API '${nonexistentApi}' does not exist")
     }
 
     it should "successfully list an API whose endpoints are not mapped to actions" in {
         val testName = "CLI_APIGWTEST23"
-        var testapiname = "A descriptive name"
+        val testapiname = "A descriptive name"
         val testbasepath = "/NoActions"
         val testrelpath = "/"
         val testops: Seq[String] = Seq("put", "delete", "get", "head", "options", "patch", "post")
@@ -873,7 +863,7 @@ class ApiGwTests
             rr.stdout should include(testbasepath + testrelpath)
 
         } finally {
-            val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
@@ -884,27 +874,26 @@ class ApiGwTests
         val testurlop = "get"
         val testapiname = testName + " API Name"
         val actionName = testName + "_action"
-        val wskpropsBackup = wskprops
+
         try {
             // Create the action for the API.
             val file = TestCLIUtils.getTestActionFilename(s"echo.js")
             wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
 
             // Set an invalid auth key
-            wskprops = WskProps(authKey = "bad-auth-key")
+            val badWskProps = WskProps(authKey = "bad-auth-key")
 
-            var rr = apiCreate(
+            apiCreate(
                 basepath = Some(testbasepath),
                 relpath = Some(testrelpath),
                 operation = Some(testurlop),
                 action = Some(actionName),
                 apiname = Some(testapiname),
-                expectedExitCode = ANY_ERROR_EXIT)
-            rr.stderr should include("The supplied authentication is invalid")
+                expectedExitCode = ANY_ERROR_EXIT)(badWskProps)
+                .stderr should include("The supplied authentication is invalid")
         } finally {
-            wskprops = wskpropsBackup
-            val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            var deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
@@ -930,7 +919,7 @@ class ApiGwTests
             val originalFull = apiList(full = Some(true), nameSort = Some(true)).stdout
             val scalaSorted = List(s"${baseName}1" + "/", s"${baseName}2" + "/", s"${baseName}3" + "/")
             val regex = s"${baseName}[1-3]/".r
-            val list  = (regex.findAllMatchIn(original)).toList
+            val list = (regex.findAllMatchIn(original)).toList
             val listFull = (regex.findAllMatchIn(originalFull)).toList
 
             scalaSorted.toString shouldEqual list.toString
@@ -938,9 +927,9 @@ class ApiGwTests
         } finally {
             // Clean up Apis
             for (i <- 1 to 3) {
-                val deleteApis = apiDelete(basepathOrApiName = s"${baseName}$i", expectedExitCode = DONTCARE_EXIT)
+                apiDelete(basepathOrApiName = s"${baseName}$i", expectedExitCode = DONTCARE_EXIT)
             }
-            val deleteAction = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
         }
     }
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 12/16: Remove redundant test suite. Also remove some spurious log messages. (#2693)

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csantanapr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git

commit 04908d5a2d24e30aede4394b71a41de3c5bc9ecf
Author: rodric rabbah <ro...@gmail.com>
AuthorDate: Thu Sep 7 11:10:28 2017 -0400

    Remove redundant test suite. Also remove some spurious log messages. (#2693)
---
 tests/src/test/scala/system/basic/WskConsoleTests.scala  |  1 -
 tests/src/test/scala/system/basic/WskSequenceTests.scala | 14 ++++++--------
 2 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/tests/src/test/scala/system/basic/WskConsoleTests.scala b/tests/src/test/scala/system/basic/WskConsoleTests.scala
index c2191fa..7abbeeb 100644
--- a/tests/src/test/scala/system/basic/WskConsoleTests.scala
+++ b/tests/src/test/scala/system/basic/WskConsoleTests.scala
@@ -66,7 +66,6 @@ class WskConsoleTests extends TestHelpers with WskTestHelpers {
     val run = wsk.action.invoke(fullActionName, Map("payload" -> payload.toJson))
     withActivation(wsk.activation, run, totalWait = duration.get) { activation =>
       val console = wsk.activation.console(10 seconds, since = duration)
-      println(console.stdout)
       console.stdout should include(payload)
     }
   }
diff --git a/tests/src/test/scala/system/basic/WskSequenceTests.scala b/tests/src/test/scala/system/basic/WskSequenceTests.scala
index bd5cdc0..1b90b6d 100644
--- a/tests/src/test/scala/system/basic/WskSequenceTests.scala
+++ b/tests/src/test/scala/system/basic/WskSequenceTests.scala
@@ -72,7 +72,6 @@ class WskSequenceTests extends TestHelpers with ScalatestRouteTest with WskTestH
         }
       }
 
-      println(s"Sequence $actions")
       assetHelper.withCleaner(wsk.action, name) {
         val sequence = actions.mkString(",")
         (action, _) =>
@@ -93,7 +92,6 @@ class WskSequenceTests extends TestHelpers with ScalatestRouteTest with WskTestH
 
       // update action sequence and run it with normal payload
       val newSequence = Seq("split", "sort").mkString(",")
-      println(s"Update sequence to $newSequence")
       wsk.action.create(
         name,
         Some(newSequence),
@@ -108,7 +106,6 @@ class WskSequenceTests extends TestHelpers with ScalatestRouteTest with WskTestH
         result.fields.get("lines") shouldBe Some(args.sortWith(_.compareTo(_) < 0).toArray.toJson)
       }
 
-      println("Run sequence with error in payload")
       // run sequence with error in the payload
       // sequence should run with no problems, error should be ignored in this test case
       // result of sequence should be identical to previous invocation above
@@ -197,7 +194,7 @@ class WskSequenceTests extends TestHelpers with ScalatestRouteTest with WskTestH
     val args = Array("what time is it?", now)
     val argsJson = args.mkString("\n").toJson
     val run = wsk.action.invoke(sName, Map("payload" -> argsJson))
-    println(s"RUN: ${run.stdout}")
+
     withActivation(wsk.activation, run, totalWait = 2 * allowedActionDuration) { activation =>
       checkSequenceLogsAndAnnotations(activation, 3) // 3 activations in this sequence
       val result = activation.response.result.get
@@ -530,10 +527,11 @@ class WskSequenceTests extends TestHelpers with ScalatestRouteTest with WskTestH
       val componentId = activation.logs.get(atomicActionIdx)
       val getComponentActivation = wsk.activation.get(Some(componentId))
       withActivation(wsk.activation, getComponentActivation, totalWait = allowedActionDuration) { componentActivation =>
-        println(componentActivation)
-        componentActivation.logs shouldBe defined
-        val logs = componentActivation.logs.get.mkString(" ")
-        regex.findFirstIn(logs) shouldBe defined
+        withClue(componentActivation) {
+          componentActivation.logs shouldBe defined
+          val logs = componentActivation.logs.get.mkString(" ")
+          regex.findFirstIn(logs) shouldBe defined
+        }
       }
     }
   }

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 15/16: Clarify WSK_CONFIG_FILE empty string behavior (#2357)

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csantanapr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git

commit 30ba302116a3ca5d53d0762557d12c4a41c11b0b
Author: Mark Deuser <md...@us.ibm.com>
AuthorDate: Thu Sep 14 12:37:21 2017 -0400

    Clarify WSK_CONFIG_FILE empty string behavior (#2357)
    
    - add test and add comments.
---
 tests/src/test/scala/whisk/core/cli/test/WskConfigTests.scala | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/tests/src/test/scala/whisk/core/cli/test/WskConfigTests.scala b/tests/src/test/scala/whisk/core/cli/test/WskConfigTests.scala
index 8e34aea..795a26a 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskConfigTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskConfigTests.scala
@@ -53,6 +53,12 @@ class WskConfigTests extends TestHelpers with WskTestHelpers {
     }
   }
 
+  it should "use default cli configuration when an empty string WSK_CONFIG_FILE is supplied" in {
+    val env = Map("WSK_CONFIG_FILE" -> "")
+    val stderr = wsk.cli(Seq("property", "get", "-i"), env = env, expectedExitCode = ERROR_EXIT).stderr
+    stderr should include("The API host is not valid: An API host must be provided.")
+  }
+
   it should "validate default property values" in {
     val tmpwskprops = File.createTempFile("wskprops", ".tmp")
     val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 03/16: Clarify WSK_CONFIG_FILE empty string behavior (#2357)

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csantanapr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git

commit 326ffdbcceafd685067e2b1613237349c644d6ef
Author: Mark Deuser <md...@us.ibm.com>
AuthorDate: Thu Sep 14 12:37:21 2017 -0400

    Clarify WSK_CONFIG_FILE empty string behavior (#2357)
    
    - add test and add comments.
---
 commands/property.go | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/commands/property.go b/commands/property.go
index d3476fd..d51fdeb 100644
--- a/commands/property.go
+++ b/commands/property.go
@@ -402,8 +402,11 @@ func SetDefaultProperties() {
 func GetPropertiesFilePath() (propsFilePath string, werr error) {
     var envExists bool
 
-    // Environment variable overrides the default properties file path
-    if propsFilePath, envExists = os.LookupEnv("WSK_CONFIG_FILE"); envExists == true || propsFilePath != "" {
+    // WSK_CONFIG_FILE environment variable overrides the default properties file path
+    // NOTE: If this variable is set to an empty string or non-existent/unreadable file
+    // - any existing $HOME/.wskprops is ignored
+    // - a default configuration is used
+    if propsFilePath, envExists = os.LookupEnv("WSK_CONFIG_FILE"); envExists {
         whisk.Debug(whisk.DbgInfo, "Using properties file '%s' from WSK_CONFIG_FILE environment variable\n", propsFilePath)
         return propsFilePath, nil
     } else {

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 02/16: Correct unable to set apihost issue.

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csantanapr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git

commit 8556b55e00de14a516a27ac5e8b6a60f4bd3e130
Author: David Liu <da...@cn.ibm.com>
AuthorDate: Mon Jul 10 14:57:43 2017 +0800

    Correct unable to set apihost issue.
---
 commands/util.go | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/commands/util.go b/commands/util.go
index de0b1f7..e7ba176 100644
--- a/commands/util.go
+++ b/commands/util.go
@@ -819,6 +819,10 @@ func GetURLBase(host string, path string) (*url.URL, error)  {
         return nil, whiskErr
     }
 
+    if !strings.HasPrefix(host, "http") {
+        host = "https://" + host
+    }
+
     urlBase := fmt.Sprintf("%s%s", host, path)
     url, err := url.Parse(urlBase)
 

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 11/16: Apply standard scala formatting. (#2650)

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csantanapr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git

commit 5e39d4bbaba4be93b027afc2d145395dd05257cf
Author: Markus Thömmes <ma...@me.com>
AuthorDate: Wed Sep 6 20:53:48 2017 +0200

    Apply standard scala formatting. (#2650)
    
    Formats all .scala files according to `scalafmt`'s (opinionated) style.
    Adds Travis checks for correctly formatted code.
---
 .../apigw/healthtests/ApiGwEndToEndTests.scala     |  227 +-
 .../test/scala/system/basic/WskActionTests.scala   |  539 ++--
 .../test/scala/system/basic/WskBasicTests.scala    | 1628 +++++-----
 .../test/scala/system/basic/WskConsoleTests.scala  |   84 +-
 .../test/scala/system/basic/WskPackageTests.scala  |  169 +-
 .../src/test/scala/system/basic/WskRuleTests.scala |  706 ++---
 .../src/test/scala/system/basic/WskSdkTests.scala  |  152 +-
 .../test/scala/system/basic/WskSequenceTests.scala |  933 +++---
 .../scala/whisk/core/admin/WskAdminTests.scala     |  275 +-
 .../actions/test/ApiGwRoutemgmtActionTests.scala   |  781 +++--
 .../scala/whisk/core/cli/test/ApiGwTests.scala     | 1839 ++++++------
 .../core/cli/test/WskActionSequenceTests.scala     |   81 +-
 .../whisk/core/cli/test/WskBasicUsageTests.scala   | 3140 ++++++++++----------
 .../scala/whisk/core/cli/test/WskConfigTests.scala |  448 +--
 .../whisk/core/cli/test/WskEntitlementTests.scala  |  557 ++--
 .../whisk/core/cli/test/WskWebActionsTests.scala   |  530 ++--
 16 files changed, 6217 insertions(+), 5872 deletions(-)

diff --git a/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala b/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala
index 332a5ca..4c95bf5 100644
--- a/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala
+++ b/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala
@@ -53,118 +53,119 @@ class ApiGwEndToEndTests
     with WskTestHelpers
     with BeforeAndAfterAll {
 
-    implicit val wskprops = WskProps()
-    val wsk = new Wsk
-    val clinamespace = wsk.namespace.whois()
-
-    // Custom CLI properties file
-    val cliWskPropsFile = File.createTempFile("wskprops", ".tmp")
-
-    /*
-     * Create a CLI properties file for use by the tests
-     */
-    override def beforeAll() = {
-        cliWskPropsFile.deleteOnExit()
-        val wskprops = WskProps(token = "SOME TOKEN")
-        wskprops.writeFile(cliWskPropsFile)
-        println(s"wsk temporary props file created here: ${cliWskPropsFile.getCanonicalPath()}")
-    }
-
-    behavior of "Wsk api"
-
-    it should s"create an API and successfully invoke that API" in {
-        val testName = "APIGW_HEALTHTEST1"
-        val testbasepath = "/" + testName + "_bp"
-        val testrelpath = "/path"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val actionName = testName + "_echo"
-        val urlqueryparam = "name"
-        val urlqueryvalue = testName
-
-        try {
-            println("cli namespace: " + clinamespace)
-
-            // Create the action for the API.  It must be a "web-action" action.
-            val file = TestCLIUtils.getTestActionFilename(s"echo-web-http.js")
-            wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, annotations = Map("web-export" -> true.toJson))
-
-            // Create the API
-            var rr = wsk.api.create(
-                basepath = Some(testbasepath),
-                relpath = Some(testrelpath),
-                operation = Some(testurlop),
-                action = Some(actionName),
-                apiname = Some(testapiname),
-                responsetype = Some("http"),
-                cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
-            rr.stdout should include("ok: created API")
-            val apiurl = rr.stdout.split("\n")(1)
-            println(s"apiurl: '$apiurl'")
-
-            // Validate the API was successfully created
-            // List result will look like:
-            // ok: APIs
-            // Action                            Verb             API Name  URL
-            // /_//whisk.system/utils/echo          get  APIGW_HEALTHTEST1 API Name  http://172.17.0.1:9001/api/ab9082cd-ea8e-465a-8a65-b491725cc4ef/APIGW_HEALTHTEST1_bp/path
-            rr = wsk.api.list(
-                basepathOrApiName = Some(testbasepath),
-                relpath = Some(testrelpath),
-                operation = Some(testurlop),
-                cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
-            rr.stdout should include("ok: APIs")
-            rr.stdout should include regex (s"$actionName\\s+$testurlop\\s+$testapiname\\s+")
-            rr.stdout should include(testbasepath + testrelpath)
-
-            // Recreate the API using a JSON swagger file
-            rr = wsk.api.get(
-                basepathOrApiName = Some(testbasepath),
-                cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
-            val swaggerfile = File.createTempFile("api", ".json")
-            swaggerfile.deleteOnExit()
-            val bw = new BufferedWriter(new FileWriter(swaggerfile))
-            bw.write(rr.stdout)
-            bw.close()
-
-            // Delete API to that it can be recreated again using the generated swagger file
-            val deleteApiResult = wsk.api.delete(
-                basepathOrApiName = testbasepath,
-                expectedExitCode = DONTCARE_EXIT,
-                cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
-
-            // Create the API again, but use the swagger file this time
-            rr = wsk.api.create(
-                swagger = Some(swaggerfile.getAbsolutePath()),
-                cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
-            rr.stdout should include("ok: created API")
-            val swaggerapiurl = rr.stdout.split("\n")(1)
-            println(s"Returned api url: '${swaggerapiurl}'")
-
-            // Call the API URL and validate the results
-            val start = java.lang.System.currentTimeMillis
-            val apiToInvoke = s"$swaggerapiurl?$urlqueryparam=$urlqueryvalue&guid=$start"
-            println(s"Invoking: '${apiToInvoke}'")
-            val response = whisk.utils.retry({
-                val response = RestAssured.given().config(sslconfig).get(s"$apiToInvoke")
-                println("URL invocation response status: " + response.statusCode)
-                response.statusCode should be(200)
-                response
-            }, 6, Some(2.second))
-            val end = java.lang.System.currentTimeMillis
-            val elapsed = end - start
-            println("Elapsed time (milliseconds) for a successful response: " + elapsed)
-            val responseString = response.body.asString
-            println("URL invocation response: " + responseString)
-            responseString.parseJson.asJsObject.fields(urlqueryparam).convertTo[String] should be(urlqueryvalue)
-
-        } finally {
-            println("Deleting action: " + actionName)
-            val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            println("Deleting API: " + testbasepath)
-            val finallydeleteApiResult = wsk.api.delete(
-                basepathOrApiName = testbasepath,
-                expectedExitCode = DONTCARE_EXIT,
-                cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
-        }
+  implicit val wskprops = WskProps()
+  val wsk = new Wsk
+  val clinamespace = wsk.namespace.whois()
+
+  // Custom CLI properties file
+  val cliWskPropsFile = File.createTempFile("wskprops", ".tmp")
+
+  /*
+   * Create a CLI properties file for use by the tests
+   */
+  override def beforeAll() = {
+    cliWskPropsFile.deleteOnExit()
+    val wskprops = WskProps(token = "SOME TOKEN")
+    wskprops.writeFile(cliWskPropsFile)
+    println(s"wsk temporary props file created here: ${cliWskPropsFile.getCanonicalPath()}")
+  }
+
+  behavior of "Wsk api"
+
+  it should s"create an API and successfully invoke that API" in {
+    val testName = "APIGW_HEALTHTEST1"
+    val testbasepath = "/" + testName + "_bp"
+    val testrelpath = "/path"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val actionName = testName + "_echo"
+    val urlqueryparam = "name"
+    val urlqueryvalue = testName
+
+    try {
+      println("cli namespace: " + clinamespace)
+
+      // Create the action for the API.  It must be a "web-action" action.
+      val file = TestUtils.getTestActionFilename(s"echo-web-http.js")
+      wsk.action.create(
+        name = actionName,
+        artifact = Some(file),
+        expectedExitCode = SUCCESS_EXIT,
+        annotations = Map("web-export" -> true.toJson))
+
+      // Create the API
+      var rr = wsk.api.create(
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname),
+        responsetype = Some("http"),
+        cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
+      rr.stdout should include("ok: created API")
+      val apiurl = rr.stdout.split("\n")(1)
+      println(s"apiurl: '$apiurl'")
+
+      // Validate the API was successfully created
+      // List result will look like:
+      // ok: APIs
+      // Action                            Verb             API Name  URL
+      // /_//whisk.system/utils/echo          get  APIGW_HEALTHTEST1 API Name  http://172.17.0.1:9001/api/ab9082cd-ea8e-465a-8a65-b491725cc4ef/APIGW_HEALTHTEST1_bp/path
+      rr = wsk.api.list(
+        basepathOrApiName = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
+      rr.stdout should include("ok: APIs")
+      rr.stdout should include regex (s"$actionName\\s+$testurlop\\s+$testapiname\\s+")
+      rr.stdout should include(testbasepath + testrelpath)
+
+      // Recreate the API using a JSON swagger file
+      rr = wsk.api.get(basepathOrApiName = Some(testbasepath), cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
+      val swaggerfile = File.createTempFile("api", ".json")
+      swaggerfile.deleteOnExit()
+      val bw = new BufferedWriter(new FileWriter(swaggerfile))
+      bw.write(rr.stdout)
+      bw.close()
+
+      // Delete API to that it can be recreated again using the generated swagger file
+      val deleteApiResult = wsk.api.delete(
+        basepathOrApiName = testbasepath,
+        expectedExitCode = DONTCARE_EXIT,
+        cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
+
+      // Create the API again, but use the swagger file this time
+      rr = wsk.api
+        .create(swagger = Some(swaggerfile.getAbsolutePath()), cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
+      rr.stdout should include("ok: created API")
+      val swaggerapiurl = rr.stdout.split("\n")(1)
+      println(s"Returned api url: '${swaggerapiurl}'")
+
+      // Call the API URL and validate the results
+      val start = java.lang.System.currentTimeMillis
+      val apiToInvoke = s"$swaggerapiurl?$urlqueryparam=$urlqueryvalue&guid=$start"
+      println(s"Invoking: '${apiToInvoke}'")
+      val response = whisk.utils.retry({
+        val response = RestAssured.given().config(sslconfig).get(s"$apiToInvoke")
+        println("URL invocation response status: " + response.statusCode)
+        response.statusCode should be(200)
+        response
+      }, 6, Some(2.second))
+      val end = java.lang.System.currentTimeMillis
+      val elapsed = end - start
+      println("Elapsed time (milliseconds) for a successful response: " + elapsed)
+      val responseString = response.body.asString
+      println("URL invocation response: " + responseString)
+      responseString.parseJson.asJsObject.fields(urlqueryparam).convertTo[String] should be(urlqueryvalue)
+
+    } finally {
+      println("Deleting action: " + actionName)
+      val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+      println("Deleting API: " + testbasepath)
+      val finallydeleteApiResult = wsk.api.delete(
+        basepathOrApiName = testbasepath,
+        expectedExitCode = DONTCARE_EXIT,
+        cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()))
     }
+  }
 }
diff --git a/tests/src/test/scala/system/basic/WskActionTests.scala b/tests/src/test/scala/system/basic/WskActionTests.scala
index 06778a3..fb65f2c 100644
--- a/tests/src/test/scala/system/basic/WskActionTests.scala
+++ b/tests/src/test/scala/system/basic/WskActionTests.scala
@@ -34,327 +34,274 @@ import spray.json.JsObject
 import spray.json.pimpAny
 
 @RunWith(classOf[JUnitRunner])
-class WskActionTests
-    extends TestHelpers
-    with WskTestHelpers
-    with JsHelpers {
-
-    implicit val wskprops = WskProps()
-    val wsk = new Wsk
-
-    val testString = "this is a test"
-    val testResult = JsObject("count" -> testString.split(" ").length.toJson)
-    val guestNamespace = wskprops.namespace
-
-    behavior of "Whisk actions"
-
-    it should "invoke an action returning a promise" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "hello promise"
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("helloPromise.js")))
-            }
-
-            val run = wsk.action.invoke(name)
-            withActivation(wsk.activation, run) {
-                activation =>
-                    activation.response.status shouldBe "success"
-                    activation.response.result shouldBe Some(JsObject("done" -> true.toJson))
-                    activation.logs.get.mkString(" ") shouldBe empty
-            }
+class WskActionTests extends TestHelpers with WskTestHelpers with JsHelpers {
+
+  implicit val wskprops = WskProps()
+  val wsk = new Wsk
+
+  val testString = "this is a test"
+  val testResult = JsObject("count" -> testString.split(" ").length.toJson)
+  val guestNamespace = wskprops.namespace
+
+  behavior of "Whisk actions"
+
+  it should "invoke an action returning a promise" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "hello promise"
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, Some(TestUtils.getTestActionFilename("helloPromise.js")))
+    }
+
+    val run = wsk.action.invoke(name)
+    withActivation(wsk.activation, run) { activation =>
+      activation.response.status shouldBe "success"
+      activation.response.result shouldBe Some(JsObject("done" -> true.toJson))
+      activation.logs.get.mkString(" ") shouldBe empty
+    }
+  }
+
+  it should "invoke an action with a space in the name" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "hello Async"
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, Some(TestUtils.getTestActionFilename("helloAsync.js")))
+    }
+
+    val run = wsk.action.invoke(name, Map("payload" -> testString.toJson))
+    withActivation(wsk.activation, run) { activation =>
+      activation.response.status shouldBe "success"
+      activation.response.result shouldBe Some(testResult)
+      activation.logs.get.mkString(" ") should include(testString)
+    }
+  }
+
+  it should "pass parameters bound on creation-time to the action" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "printParams"
+    val params = Map("param1" -> "test1", "param2" -> "test2")
+
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(
+        name,
+        Some(TestUtils.getTestActionFilename("printParams.js")),
+        parameters = params.mapValues(_.toJson))
+    }
+
+    val invokeParams = Map("payload" -> testString)
+    val run = wsk.action.invoke(name, invokeParams.mapValues(_.toJson))
+    withActivation(wsk.activation, run) { activation =>
+      val logs = activation.logs.get.mkString(" ")
+
+      (params ++ invokeParams).foreach {
+        case (key, value) =>
+          logs should include(s"params.$key: $value")
+      }
+    }
+  }
+
+  it should "copy an action and invoke it successfully" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "copied"
+    val packageName = "samples"
+    val actionName = "wordcount"
+    val fullQualifiedName = s"/$guestNamespace/$packageName/$actionName"
+
+    assetHelper.withCleaner(wsk.pkg, packageName) { (pkg, _) =>
+      pkg.create(packageName, shared = Some(true))
     }
 
-    it should "invoke an action with a space in the name" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "hello Async"
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("helloAsync.js")))
-            }
-
-            val run = wsk.action.invoke(name, Map("payload" -> testString.toJson))
-            withActivation(wsk.activation, run) {
-                activation =>
-                    activation.response.status shouldBe "success"
-                    activation.response.result shouldBe Some(testResult)
-                    activation.logs.get.mkString(" ") should include(testString)
-            }
+    assetHelper.withCleaner(wsk.action, fullQualifiedName) {
+      val file = Some(TestUtils.getTestActionFilename("wc.js"))
+      (action, _) =>
+        action.create(fullQualifiedName, file)
     }
 
-    it should "pass parameters bound on creation-time to the action" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "printParams"
-            val params = Map(
-                "param1" -> "test1",
-                "param2" -> "test2")
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) =>
-                    action.create(
-                        name,
-                        Some(TestCLIUtils.getTestActionFilename("printParams.js")),
-                        parameters = params.mapValues(_.toJson))
-            }
-
-            val invokeParams = Map("payload" -> testString)
-            val run = wsk.action.invoke(name, invokeParams.mapValues(_.toJson))
-            withActivation(wsk.activation, run) {
-                activation =>
-                    val logs = activation.logs.get.mkString(" ")
-
-                    (params ++ invokeParams).foreach {
-                        case (key, value) =>
-                            logs should include(s"params.$key: $value")
-                    }
-            }
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, Some(fullQualifiedName), Some("copy"))
     }
 
-    it should "copy an action and invoke it successfully" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "copied"
-            val packageName = "samples"
-            val actionName = "wordcount"
-            val fullQualifiedName = s"/$guestNamespace/$packageName/$actionName"
-
-            assetHelper.withCleaner(wsk.pkg, packageName) {
-                (pkg, _) => pkg.create(packageName, shared = Some(true))
-            }
-
-            assetHelper.withCleaner(wsk.action, fullQualifiedName) {
-                val file = Some(TestCLIUtils.getTestActionFilename("wc.js"))
-                (action, _) => action.create(fullQualifiedName, file)
-            }
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(fullQualifiedName), Some("copy"))
-            }
-
-            val run = wsk.action.invoke(name, Map("payload" -> testString.toJson))
-            withActivation(wsk.activation, run) {
-                activation =>
-                    activation.response.status shouldBe "success"
-                    activation.response.result shouldBe Some(testResult)
-                    activation.logs.get.mkString(" ") should include(testString)
-            }
+    val run = wsk.action.invoke(name, Map("payload" -> testString.toJson))
+    withActivation(wsk.activation, run) { activation =>
+      activation.response.status shouldBe "success"
+      activation.response.result shouldBe Some(testResult)
+      activation.logs.get.mkString(" ") should include(testString)
+    }
+  }
+
+  it should "copy an action and ensure exec, parameters, and annotations copied" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val origActionName = "origAction"
+      val copiedActionName = "copiedAction"
+      val params = Map("a" -> "A".toJson)
+      val annots = Map("b" -> "B".toJson)
+
+      assetHelper.withCleaner(wsk.action, origActionName) {
+        val file = Some(TestUtils.getTestActionFilename("wc.js"))
+        (action, _) =>
+          action.create(origActionName, file, parameters = params, annotations = annots)
+      }
+
+      assetHelper.withCleaner(wsk.action, copiedActionName) { (action, _) =>
+        action.create(copiedActionName, Some(origActionName), Some("copy"))
+      }
+
+      val copiedAction = getJSONFromCLIResponse(wsk.action.get(copiedActionName).stdout)
+      val origAction = getJSONFromCLIResponse(wsk.action.get(copiedActionName).stdout)
+
+      copiedAction.fields("annotations") shouldBe origAction.fields("annotations")
+      copiedAction.fields("parameters") shouldBe origAction.fields("parameters")
+      copiedAction.fields("exec") shouldBe origAction.fields("exec")
+      copiedAction.fields("version") shouldBe JsString("0.0.1")
+  }
+
+  it should "add new parameters and annotations while copying an action" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val origName = "origAction"
+      val copiedName = "copiedAction"
+      val origParams = Map("origParam1" -> "origParamValue1".toJson, "origParam2" -> 999.toJson)
+      val copiedParams = Map("copiedParam1" -> "copiedParamValue1".toJson, "copiedParam2" -> 123.toJson)
+      val origAnnots = Map("origAnnot1" -> "origAnnotValue1".toJson, "origAnnot2" -> true.toJson)
+      val copiedAnnots = Map("copiedAnnot1" -> "copiedAnnotValue1".toJson, "copiedAnnot2" -> false.toJson)
+      val resParams = Seq(
+        JsObject("key" -> JsString("copiedParam1"), "value" -> JsString("copiedParamValue1")),
+        JsObject("key" -> JsString("copiedParam2"), "value" -> JsNumber(123)),
+        JsObject("key" -> JsString("origParam1"), "value" -> JsString("origParamValue1")),
+        JsObject("key" -> JsString("origParam2"), "value" -> JsNumber(999)))
+      val resAnnots = Seq(
+        JsObject("key" -> JsString("origAnnot1"), "value" -> JsString("origAnnotValue1")),
+        JsObject("key" -> JsString("copiedAnnot2"), "value" -> JsBoolean(false)),
+        JsObject("key" -> JsString("copiedAnnot1"), "value" -> JsString("copiedAnnotValue1")),
+        JsObject("key" -> JsString("origAnnot2"), "value" -> JsBoolean(true)),
+        JsObject("key" -> JsString("exec"), "value" -> JsString("nodejs:6")))
+
+      assetHelper.withCleaner(wsk.action, origName) {
+        val file = Some(TestUtils.getTestActionFilename("echo.js"))
+        (action, _) =>
+          action.create(origName, file, parameters = origParams, annotations = origAnnots)
+      }
+
+      assetHelper.withCleaner(wsk.action, copiedName) { (action, _) =>
+        action.create(copiedName, Some(origName), Some("copy"), parameters = copiedParams, annotations = copiedAnnots)
+      }
+
+      val copiedAction = getJSONFromCLIResponse(wsk.action.get(copiedName).stdout)
+
+      // CLI does not guarantee order of annotations and parameters so do a diff to compare the values
+      copiedAction.fields("parameters").convertTo[Seq[JsObject]] diff resParams shouldBe List()
+      copiedAction.fields("annotations").convertTo[Seq[JsObject]] diff resAnnots shouldBe List()
+  }
+
+  it should "recreate and invoke a new action with different code" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "recreatedAction"
+    assetHelper.withCleaner(wsk.action, name, false) { (action, _) =>
+      action.create(name, Some(TestUtils.getTestActionFilename("wc.js")))
     }
 
-    it should "copy an action and ensure exec, parameters, and annotations copied" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val origActionName = "origAction"
-            val copiedActionName = "copiedAction"
-            val params = Map("a" -> "A".toJson)
-            val annots = Map("b" -> "B".toJson)
-
-            assetHelper.withCleaner(wsk.action, origActionName) {
-                val file = Some(TestCLIUtils.getTestActionFilename("wc.js"))
-                (action, _) => action.create(origActionName, file, parameters = params, annotations = annots)
-            }
-
-            assetHelper.withCleaner(wsk.action, copiedActionName) {
-                (action, _) => action.create(copiedActionName, Some(origActionName), Some("copy"))
-            }
-
-            val copiedAction = getJSONFromCLIResponse(wsk.action.get(copiedActionName).stdout)
-            val origAction = getJSONFromCLIResponse(wsk.action.get(copiedActionName).stdout)
-
-            copiedAction.fields("annotations") shouldBe origAction.fields("annotations")
-            copiedAction.fields("parameters") shouldBe origAction.fields("parameters")
-            copiedAction.fields("exec") shouldBe origAction.fields("exec")
-            copiedAction.fields("version") shouldBe JsString("0.0.1")
+    val run1 = wsk.action.invoke(name, Map("payload" -> testString.toJson))
+    withActivation(wsk.activation, run1) { activation =>
+      activation.response.status shouldBe "success"
+      activation.logs.get.mkString(" ") should include(s"The message '$testString' has")
     }
 
-    it should "add new parameters and annotations while copying an action" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val origName = "origAction"
-            val copiedName = "copiedAction"
-            val origParams = Map("origParam1" -> "origParamValue1".toJson, "origParam2" -> 999.toJson)
-            val copiedParams = Map("copiedParam1" -> "copiedParamValue1".toJson, "copiedParam2" -> 123.toJson)
-            val origAnnots = Map("origAnnot1" -> "origAnnotValue1".toJson, "origAnnot2" -> true.toJson)
-            val copiedAnnots = Map("copiedAnnot1" -> "copiedAnnotValue1".toJson, "copiedAnnot2" -> false.toJson)
-            val resParams = Seq(
-                JsObject(
-                    "key" -> JsString("copiedParam1"),
-                    "value" -> JsString("copiedParamValue1")
-                ),
-                JsObject(
-                    "key" -> JsString("copiedParam2"),
-                    "value" -> JsNumber(123)
-                ),
-                JsObject(
-                    "key" -> JsString("origParam1"),
-                    "value" -> JsString("origParamValue1")
-                ),
-                JsObject(
-                    "key" -> JsString("origParam2"),
-                    "value" -> JsNumber(999)
-                )
-            )
-            val resAnnots = Seq(
-                JsObject(
-                    "key" -> JsString("origAnnot1"),
-                    "value" -> JsString("origAnnotValue1")
-                ),
-                JsObject(
-                    "key" -> JsString("copiedAnnot2"),
-                    "value" -> JsBoolean(false)
-                ),
-                JsObject(
-                    "key" -> JsString("copiedAnnot1"),
-                    "value" -> JsString("copiedAnnotValue1")
-                ),
-                JsObject(
-                    "key" -> JsString("origAnnot2"),
-                    "value" -> JsBoolean(true)
-                ),
-                JsObject(
-                    "key" -> JsString("exec"),
-                    "value" -> JsString("nodejs:6")
-                )
-            )
-
-            assetHelper.withCleaner(wsk.action, origName) {
-                val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
-                (action, _) => action.create(origName, file, parameters = origParams, annotations = origAnnots)
-            }
-
-            assetHelper.withCleaner(wsk.action, copiedName) {
-                (action, _) => action.create(copiedName, Some(origName), Some("copy"), parameters = copiedParams, annotations = copiedAnnots)
-            }
-
-            val copiedAction = getJSONFromCLIResponse(wsk.action.get(copiedName).stdout)
-
-            // CLI does not guarantee order of annotations and parameters so do a diff to compare the values
-            copiedAction.fields("parameters").convertTo[Seq[JsObject]] diff resParams shouldBe List()
-            copiedAction.fields("annotations").convertTo[Seq[JsObject]] diff resAnnots shouldBe List()
+    wsk.action.delete(name)
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, Some(TestUtils.getTestActionFilename("hello.js")))
     }
 
-    it should "recreate and invoke a new action with different code" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "recreatedAction"
-            assetHelper.withCleaner(wsk.action, name, false) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("wc.js")))
-            }
-
-            val run1 = wsk.action.invoke(name, Map("payload" -> testString.toJson))
-            withActivation(wsk.activation, run1) {
-                activation =>
-                    activation.response.status shouldBe "success"
-                    activation.logs.get.mkString(" ") should include(s"The message '$testString' has")
-            }
-
-            wsk.action.delete(name)
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("hello.js")))
-            }
-
-            val run2 = wsk.action.invoke(name, Map("payload" -> testString.toJson))
-            withActivation(wsk.activation, run2) {
-                activation =>
-                    activation.response.status shouldBe "success"
-                    activation.logs.get.mkString(" ") should include(s"hello, $testString")
-            }
+    val run2 = wsk.action.invoke(name, Map("payload" -> testString.toJson))
+    withActivation(wsk.activation, run2) { activation =>
+      activation.response.status shouldBe "success"
+      activation.logs.get.mkString(" ") should include(s"hello, $testString")
     }
+  }
 
-    it should "fail to invoke an action with an empty file" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "empty"
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("empty.js")))
-            }
-            val run = wsk.action.invoke(name)
-            withActivation(wsk.activation, run) {
-                activation =>
-                    activation.response.status shouldBe "action developer error"
-                    activation.response.result shouldBe Some(JsObject("error" -> "Missing main/no code to execute.".toJson))
-            }
+  it should "fail to invoke an action with an empty file" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "empty"
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, Some(TestUtils.getTestActionFilename("empty.js")))
+    }
+    val run = wsk.action.invoke(name)
+    withActivation(wsk.activation, run) { activation =>
+      activation.response.status shouldBe "action developer error"
+      activation.response.result shouldBe Some(JsObject("error" -> "Missing main/no code to execute.".toJson))
     }
+  }
 
-    it should "create an action with an empty file" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "empty"
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("empty.js")))
-            }
-            val rr = wsk.action.get(name)
-            wsk.parseJsonString(rr.stdout).getFieldPath("exec", "code") shouldBe Some(JsString(""))
+  it should "create an action with an empty file" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "empty"
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, Some(TestUtils.getTestActionFilename("empty.js")))
     }
+    val rr = wsk.action.get(name)
+    wsk.parseJsonString(rr.stdout).getFieldPath("exec", "code") shouldBe Some(JsString(""))
+  }
 
-    it should "blocking invoke of nested blocking actions" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "nestedBlockingAction"
-            val child = "wc"
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("wcbin.js")))
-            }
-            assetHelper.withCleaner(wsk.action, child) {
-                (action, _) => action.create(child, Some(TestCLIUtils.getTestActionFilename("wc.js")))
-            }
-
-            val run = wsk.action.invoke(name, Map("payload" -> testString.toJson), blocking = true)
-            val activation = wsk.parseJsonString(run.stdout).convertTo[ActivationResult]
-
-            withClue(s"check failed for activation: $activation") {
-                val wordCount = testString.split(" ").length
-                activation.response.result.get shouldBe JsObject("binaryCount" -> s"${wordCount.toBinaryString} (base 2)".toJson)
-            }
+  it should "blocking invoke of nested blocking actions" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "nestedBlockingAction"
+    val child = "wc"
+
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, Some(TestUtils.getTestActionFilename("wcbin.js")))
+    }
+    assetHelper.withCleaner(wsk.action, child) { (action, _) =>
+      action.create(child, Some(TestUtils.getTestActionFilename("wc.js")))
     }
 
-    it should "blocking invoke an asynchronous action" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "helloAsync"
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("helloAsync.js")))
-            }
-
-            val run = wsk.action.invoke(name, Map("payload" -> testString.toJson), blocking = true)
-            val activation = wsk.parseJsonString(run.stdout).convertTo[ActivationResult]
-
-            withClue(s"check failed for activation: $activation") {
-                activation.response.status shouldBe "success"
-                activation.response.result shouldBe Some(testResult)
-                activation.logs shouldBe Some(List())
-            }
+    val run = wsk.action.invoke(name, Map("payload" -> testString.toJson), blocking = true)
+    val activation = wsk.parseJsonString(run.stdout).convertTo[ActivationResult]
+
+    withClue(s"check failed for activation: $activation") {
+      val wordCount = testString.split(" ").length
+      activation.response.result.get shouldBe JsObject("binaryCount" -> s"${wordCount.toBinaryString} (base 2)".toJson)
+    }
+  }
+
+  it should "blocking invoke an asynchronous action" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "helloAsync"
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, Some(TestUtils.getTestActionFilename("helloAsync.js")))
+    }
+
+    val run = wsk.action.invoke(name, Map("payload" -> testString.toJson), blocking = true)
+    val activation = wsk.parseJsonString(run.stdout).convertTo[ActivationResult]
+
+    withClue(s"check failed for activation: $activation") {
+      activation.response.status shouldBe "success"
+      activation.response.result shouldBe Some(testResult)
+      activation.logs shouldBe Some(List())
+    }
+  }
+
+  it should "reject an invoke with the wrong parameters set" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val fullQualifiedName = s"/$guestNamespace/samples/helloWorld"
+    val payload = "bob"
+    val rr = wsk.cli(
+      Seq("action", "invoke", fullQualifiedName, payload) ++ wskprops.overrides,
+      expectedExitCode = TestUtils.ERROR_EXIT)
+    rr.stderr should include("Run 'wsk --help' for usage.")
+    rr.stderr should include(s"error: Invalid argument(s): $payload")
+  }
+
+  it should "not be able to use 'ping' in an action" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "ping"
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, Some(TestUtils.getTestActionFilename("ping.js")))
     }
 
-    it should "reject an invoke with the wrong parameters set" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val fullQualifiedName = s"/$guestNamespace/samples/helloWorld"
-            val payload = "bob"
-            val rr = wsk.cli(Seq("action", "invoke", fullQualifiedName, payload) ++ wskprops.overrides,
-                expectedExitCode = TestUtils.ERROR_EXIT)
-            rr.stderr should include("Run 'wsk --help' for usage.")
-            rr.stderr should include(s"error: Invalid argument(s): $payload")
+    val run = wsk.action.invoke(name, Map("payload" -> "google.com".toJson))
+    withActivation(wsk.activation, run) { activation =>
+      activation.response.result shouldBe Some(
+        JsObject("stderr" -> "ping: icmp open socket: Operation not permitted\n".toJson, "stdout" -> "".toJson))
     }
+  }
 
-    it should "not be able to use 'ping' in an action" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "ping"
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("ping.js")))
-            }
-
-            val run = wsk.action.invoke(name, Map("payload" -> "google.com".toJson))
-            withActivation(wsk.activation, run) {
-                activation =>
-                    activation.response.result shouldBe Some(JsObject(
-                        "stderr" -> "ping: icmp open socket: Operation not permitted\n".toJson,
-                        "stdout" -> "".toJson))
-            }
+  ignore should "support UTF-8 as input and output format" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "utf8Test"
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, Some(TestUtils.getTestActionFilename("hello.js")))
     }
 
-    ignore should "support UTF-8 as input and output format" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "utf8Test"
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("hello.js")))
-            }
-
-            val utf8 = "«ταБЬℓσö»: 1<2 & 4+1>³, now 20%€§$ off!"
-            val run = wsk.action.invoke(name, Map("payload" -> utf8.toJson))
-            withActivation(wsk.activation, run) {
-                activation =>
-                    activation.response.status shouldBe "success"
-                    activation.logs.get.mkString(" ") should include(s"hello $utf8")
-            }
+    val utf8 = "«ταБЬℓσö»: 1<2 & 4+1>³, now 20%€§$ off!"
+    val run = wsk.action.invoke(name, Map("payload" -> utf8.toJson))
+    withActivation(wsk.activation, run) { activation =>
+      activation.response.status shouldBe "success"
+      activation.logs.get.mkString(" ") should include(s"hello $utf8")
     }
+  }
 }
diff --git a/tests/src/test/scala/system/basic/WskBasicTests.scala b/tests/src/test/scala/system/basic/WskBasicTests.scala
index d83cf6f..4ee00cb 100644
--- a/tests/src/test/scala/system/basic/WskBasicTests.scala
+++ b/tests/src/test/scala/system/basic/WskBasicTests.scala
@@ -37,823 +37,831 @@ import spray.json.DefaultJsonProtocol._
 import spray.json.pimpAny
 
 @RunWith(classOf[JUnitRunner])
-class WskBasicTests
-    extends TestHelpers
-    with WskTestHelpers {
-
-    implicit val wskprops = WskProps()
-    val wsk = new Wsk
-    val defaultAction = Some(TestCLIUtils.getTestActionFilename("hello.js"))
-
-    behavior of "Wsk CLI"
-
-    it should "reject creating duplicate entity" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "testDuplicateCreate"
-            assetHelper.withCleaner(wsk.trigger, name) {
-                (trigger, _) => trigger.create(name)
-            }
-            assetHelper.withCleaner(wsk.action, name, confirmDelete = false) {
-                (action, _) => action.create(name, defaultAction, expectedExitCode = CONFLICT)
-            }
+class WskBasicTests extends TestHelpers with WskTestHelpers {
+
+  implicit val wskprops = WskProps()
+  val wsk = new Wsk
+  val defaultAction = Some(TestUtils.getTestActionFilename("hello.js"))
+
+  behavior of "Wsk CLI"
+
+  it should "reject creating duplicate entity" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "testDuplicateCreate"
+    assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
+      trigger.create(name)
+    }
+    assetHelper.withCleaner(wsk.action, name, confirmDelete = false) { (action, _) =>
+      action.create(name, defaultAction, expectedExitCode = CONFLICT)
+    }
+  }
+
+  it should "reject deleting entity in wrong collection" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "testCrossDelete"
+    assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
+      trigger.create(name)
+    }
+    wsk.action.delete(name, expectedExitCode = CONFLICT)
+  }
+
+  it should "reject unauthenticated access" in {
+    implicit val wskprops = WskProps("xxx") // shadow properties
+    val errormsg = "The supplied authentication is invalid"
+    wsk.namespace.list(expectedExitCode = UNAUTHORIZED).stderr should include(errormsg)
+    wsk.namespace.get(expectedExitCode = UNAUTHORIZED).stderr should include(errormsg)
+  }
+
+  behavior of "Wsk Package CLI"
+
+  it should "create, update, get and list a package" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "testPackage"
+    val params = Map("a" -> "A".toJson)
+    assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
+      pkg.create(name, parameters = params, shared = Some(true))
+      pkg.create(name, update = true)
+    }
+    val stdout = wsk.pkg.get(name).stdout
+    stdout should include regex (""""key": "a"""")
+    stdout should include regex (""""value": "A"""")
+    stdout should include regex (""""publish": true""")
+    stdout should include regex (""""version": "0.0.2"""")
+    wsk.pkg.list().stdout should include(name)
+  }
+
+  it should "create, and get a package summary" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val packageName = "packageName"
+    val actionName = "actionName"
+    val packageAnnots = Map(
+      "description" -> JsString("Package description"),
+      "parameters" -> JsArray(
+        JsObject("name" -> JsString("paramName1"), "description" -> JsString("Parameter description 1")),
+        JsObject("name" -> JsString("paramName2"), "description" -> JsString("Parameter description 2"))))
+    val actionAnnots = Map(
+      "description" -> JsString("Action description"),
+      "parameters" -> JsArray(
+        JsObject("name" -> JsString("paramName1"), "description" -> JsString("Parameter description 1")),
+        JsObject("name" -> JsString("paramName2"), "description" -> JsString("Parameter description 2"))))
+
+    assetHelper.withCleaner(wsk.pkg, packageName) { (pkg, _) =>
+      pkg.create(packageName, annotations = packageAnnots)
+    }
+
+    wsk.action.create(packageName + "/" + actionName, defaultAction, annotations = actionAnnots)
+    val stdout = wsk.pkg.get(packageName, summary = true).stdout
+    val ns = wsk.namespace.whois()
+    wsk.action.delete(packageName + "/" + actionName)
+
+    stdout should include regex (s"(?i)package /$ns/$packageName: Package description\\s*\\(parameters: paramName1, paramName2\\)")
+    stdout should include regex (s"(?i)action /$ns/$packageName/$actionName: Action description\\s*\\(parameters: paramName1, paramName2\\)")
+  }
+
+  it should "create a package with a name that contains spaces" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "package with spaces"
+
+    val res = assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
+      pkg.create(name)
+    }
+
+    res.stdout should include(s"ok: created package $name")
+  }
+
+  it should "create a package, and get its individual fields" in withAssetCleaner(wskprops) {
+    val name = "packageFields"
+    val paramInput = Map("payload" -> "test".toJson)
+    val successMsg = s"ok: got package $name, displaying field"
+
+    (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
+        pkg.create(name, parameters = paramInput)
+      }
+
+      val expectedParam = JsObject("payload" -> JsString("test"))
+      val ns = wsk.namespace.whois()
+
+      wsk.pkg
+        .get(name, fieldFilter = Some("namespace"))
+        .stdout should include regex (s"""(?i)$successMsg namespace\n"$ns"""")
+      wsk.pkg.get(name, fieldFilter = Some("name")).stdout should include(s"""$successMsg name\n"$name"""")
+      wsk.pkg.get(name, fieldFilter = Some("version")).stdout should include(s"""$successMsg version\n"0.0.1"""")
+      wsk.pkg.get(name, fieldFilter = Some("publish")).stdout should include(s"""$successMsg publish\nfalse""")
+      wsk.pkg.get(name, fieldFilter = Some("binding")).stdout should include regex (s"""\\{\\}""")
+      wsk.pkg.get(name, fieldFilter = Some("invalid"), expectedExitCode = ERROR_EXIT).stderr should include(
+        "error: Invalid field filter 'invalid'.")
+  }
+
+  it should "reject creation of duplication packages" in withAssetCleaner(wskprops) {
+    val name = "dupePackage"
+
+    (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
+        pkg.create(name)
+      }
+
+      val stderr = wsk.pkg.create(name, expectedExitCode = CONFLICT).stderr
+      stderr should include regex (s"""Unable to create package '$name': resource already exists \\(code \\d+\\)""")
+  }
+
+  it should "reject delete of package that does not exist" in {
+    val name = "nonexistentPackage"
+    val stderr = wsk.pkg.delete(name, expectedExitCode = NOT_FOUND).stderr
+    stderr should include regex (s"""Unable to delete package '$name'. The requested resource does not exist. \\(code \\d+\\)""")
+  }
+
+  it should "reject get of package that does not exist" in {
+    val name = "nonexistentPackage"
+    val stderr = wsk.pkg.get(name, expectedExitCode = NOT_FOUND).stderr
+    stderr should include regex (s"""Unable to get package '$name': The requested resource does not exist. \\(code \\d+\\)""")
+  }
+
+  behavior of "Wsk Action CLI"
+
+  it should "create the same action twice with different cases" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    assetHelper.withCleaner(wsk.action, "TWICE") { (action, name) =>
+      action.create(name, defaultAction)
+    }
+    assetHelper.withCleaner(wsk.action, "twice") { (action, name) =>
+      action.create(name, defaultAction)
+    }
+  }
+
+  it should "create, update, get and list an action" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "createAndUpdate"
+    val file = Some(TestUtils.getTestActionFilename("hello.js"))
+    val params = Map("a" -> "A".toJson)
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, file, parameters = params)
+      action.create(name, None, parameters = Map("b" -> "B".toJson), update = true)
+    }
+
+    val stdout = wsk.action.get(name).stdout
+    stdout should not include regex(""""key": "a"""")
+    stdout should not include regex(""""value": "A"""")
+    stdout should include regex (""""key": "b""")
+    stdout should include regex (""""value": "B"""")
+    stdout should include regex (""""publish": false""")
+    stdout should include regex (""""version": "0.0.2"""")
+    wsk.action.list().stdout should include(name)
+  }
+
+  it should "reject create of an action that already exists" in withAssetCleaner(wskprops) {
+    val name = "dupeAction"
+    val file = Some(TestUtils.getTestActionFilename("echo.js"))
+
+    (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, file)
+      }
+
+      val stderr = wsk.action.create(name, file, expectedExitCode = CONFLICT).stderr
+      stderr should include regex (s"""Unable to create action '$name': resource already exists \\(code \\d+\\)""")
+  }
+
+  it should "reject delete of action that does not exist" in {
+    val name = "nonexistentAction"
+    val stderr = wsk.action.delete(name, expectedExitCode = NOT_FOUND).stderr
+    stderr should include regex (s"""Unable to delete action '$name'. The requested resource does not exist. \\(code \\d+\\)""")
+  }
+
+  it should "reject invocation of action that does not exist" in {
+    val name = "nonexistentAction"
+    val stderr = wsk.action.invoke(name, expectedExitCode = NOT_FOUND).stderr
+    stderr should include regex (s"""Unable to invoke action '$name': The requested resource does not exist. \\(code \\d+\\)""")
+  }
+
+  it should "reject get of an action that does not exist" in {
+    val name = "nonexistentAction"
+    val stderr = wsk.action.get(name, expectedExitCode = NOT_FOUND).stderr
+    stderr should include regex (s"""Unable to get action '$name': The requested resource does not exist. \\(code \\d+\\)""")
+  }
+
+  it should "create, and invoke an action that utilizes a docker container" in withAssetCleaner(wskprops) {
+    val name = "dockerContainer"
+    (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.action, name) {
+        // this docker image will be need to be pulled from dockerhub and hence has to be published there first
+        (action, _) =>
+          action.create(name, None, docker = Some("openwhisk/example"))
+      }
+
+      val args = Map("payload" -> "test".toJson)
+      val run = wsk.action.invoke(name, args)
+      withActivation(wsk.activation, run) { activation =>
+        activation.response.result shouldBe Some(
+          JsObject("args" -> args.toJson, "msg" -> "Hello from arbitrary C program!".toJson))
+      }
+  }
+
+  it should "create, and invoke an action that utilizes dockerskeleton with native zip" in withAssetCleaner(wskprops) {
+    val name = "dockerContainerWithZip"
+    (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.action, name) {
+        // this docker image will be need to be pulled from dockerhub and hence has to be published there first
+        (action, _) =>
+          action.create(name, Some(TestUtils.getTestActionFilename("blackbox.zip")), kind = Some("native"))
+      }
+
+      val run = wsk.action.invoke(name, Map())
+      withActivation(wsk.activation, run) { activation =>
+        activation.response.result shouldBe Some(JsObject("msg" -> "hello zip".toJson))
+        activation.logs shouldBe defined
+        val logs = activation.logs.get.toString
+        logs should include("This is an example zip used with the docker skeleton action.")
+        logs should not include ("XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX")
+      }
+  }
+
+  it should "create, and invoke an action using a parameter file" in withAssetCleaner(wskprops) {
+    val name = "paramFileAction"
+    val file = Some(TestUtils.getTestActionFilename("argCheck.js"))
+    val argInput = Some(TestUtils.getTestActionFilename("validInput2.json"))
+
+    (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, file)
+      }
+
+      val expectedOutput = JsObject("payload" -> JsString("test"))
+      val run = wsk.action.invoke(name, parameterFile = argInput)
+      withActivation(wsk.activation, run) { activation =>
+        activation.response.result shouldBe Some(expectedOutput)
+      }
+  }
+
+  it should "create an action, and get its individual fields" in withAssetCleaner(wskprops) {
+    val name = "actionFields"
+    val paramInput = Map("payload" -> "test".toJson)
+    val successMsg = s"ok: got action $name, displaying field"
+
+    (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, defaultAction, parameters = paramInput)
+      }
+
+      val expectedParam = JsObject("payload" -> JsString("test"))
+      val ns = wsk.namespace.whois()
+
+      wsk.action.get(name, fieldFilter = Some("name")).stdout should include(s"""$successMsg name\n"$name"""")
+      wsk.action.get(name, fieldFilter = Some("version")).stdout should include(s"""$successMsg version\n"0.0.1"""")
+      wsk.action.get(name, fieldFilter = Some("exec")).stdout should include(s"""$successMsg""")
+      wsk.action
+        .get(name, fieldFilter = Some("exec"))
+        .stdout should include regex (s"""$successMsg exec\n\\{\\s+"kind":\\s+"nodejs:6",\\s+"code":\\s+"\\/\\*\\*[\\\\r]*\\\\n \\* Hello, world.[\\\\r]*\\\\n \\*\\/[\\\\r]*\\\\nfunction main\\(params\\) \\{[\\\\r]*\\\\n    greeting \\= 'hello, ' \\+ params.payload \\+ '!'[\\\\r]*\\\\n    console.log\\(greeting\\);[\\\\r]*\\\\n    return \\{payload: greeting\\}[\\\\r]*\\\\n\\}""")
+      wsk.action
+        .get(name, fieldFilter = Some("parameters"))
+        .stdout should include regex (s"""$successMsg parameters\n\\[\\s+\\{\\s+"key":\\s+"payload",\\s+"value":\\s+"test"\\s+\\}\\s+\\]""")
+      wsk.action
+        .get(name, fieldFilter = Some("annotations"))
+        .stdout should include regex (s"""$successMsg annotations\n\\[\\s+\\{\\s+"key":\\s+"exec",\\s+"value":\\s+"nodejs:6"\\s+\\}\\s+\\]""")
+      wsk.action
+        .get(name, fieldFilter = Some("limits"))
+        .stdout should include regex (s"""$successMsg limits\n\\{\\s+"timeout":\\s+60000,\\s+"memory":\\s+256,\\s+"logs":\\s+10\\s+\\}""")
+      wsk.action
+        .get(name, fieldFilter = Some("namespace"))
+        .stdout should include regex (s"""(?i)$successMsg namespace\n"$ns"""")
+      wsk.action.get(name, fieldFilter = Some("invalid"), expectedExitCode = MISUSE_EXIT).stderr should include(
+        "error: Invalid field filter 'invalid'.")
+      wsk.action.get(name, fieldFilter = Some("publish")).stdout should include(s"""$successMsg publish\nfalse""")
+  }
+
+  /**
+   * Tests creating an action from a malformed js file. This should fail in
+   * some way - preferably when trying to create the action. If not, then
+   * surely when it runs there should be some indication in the logs. Don't
+   * think this is true currently.
+   */
+  it should "create and invoke action with malformed js resulting in activation error" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "MALFORMED"
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, Some(TestUtils.getTestActionFilename("malformed.js")))
+      }
+
+      val run = wsk.action.invoke(name, Map("payload" -> "whatever".toJson))
+      withActivation(wsk.activation, run) { activation =>
+        activation.response.status shouldBe "action developer error"
+        // representing nodejs giving an error when given malformed.js
+        activation.response.result.get.toString should include("ReferenceError")
+      }
+  }
+
+  it should "create and invoke a blocking action resulting in an application error response" in withAssetCleaner(
+    wskprops) { (wp, assetHelper) =>
+    val name = "applicationError"
+    val strErrInput = Map("error" -> "Error message".toJson)
+    val numErrInput = Map("error" -> 502.toJson)
+    val boolErrInput = Map("error" -> true.toJson)
+
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, Some(TestUtils.getTestActionFilename("echo.js")))
+    }
+
+    Seq(strErrInput, numErrInput, boolErrInput) foreach { input =>
+      getJSONFromCLIResponse(
+        wsk.action.invoke(name, parameters = input, blocking = true, expectedExitCode = 246).stderr)
+        .fields("response")
+        .asJsObject
+        .fields("result")
+        .asJsObject shouldBe input.toJson.asJsObject
+
+      wsk.action
+        .invoke(name, parameters = input, blocking = true, result = true, expectedExitCode = 246)
+        .stderr
+        .parseJson
+        .asJsObject shouldBe input.toJson.asJsObject
+    }
+  }
+
+  it should "create and invoke a blocking action resulting in an failed promise" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "errorResponseObject"
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, Some(TestUtils.getTestActionFilename("asyncError.js")))
+      }
+
+      val stderr = wsk.action.invoke(name, blocking = true, expectedExitCode = 246).stderr
+      ActivationResult.serdes.read(removeCLIHeader(stderr).parseJson).response.result shouldBe Some {
+        JsObject("error" -> JsObject("msg" -> "failed activation on purpose".toJson))
+      }
+  }
+
+  it should "invoke a blocking action and get only the result" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "basicInvoke"
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, Some(TestUtils.getTestActionFilename("wc.js")))
+    }
+
+    wsk.action
+      .invoke(name, Map("payload" -> "one two three".toJson), result = true)
+      .stdout should include regex (""""count": 3""")
+  }
+
+  it should "create, and get an action summary" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "actionName"
+    val annots = Map(
+      "description" -> JsString("Action description"),
+      "parameters" -> JsArray(
+        JsObject("name" -> JsString("paramName1"), "description" -> JsString("Parameter description 1")),
+        JsObject("name" -> JsString("paramName2"), "description" -> JsString("Parameter description 2"))))
+
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, defaultAction, annotations = annots)
+    }
+
+    val stdout = wsk.action.get(name, summary = true).stdout
+    val ns = wsk.namespace.whois()
+
+    stdout should include regex (s"(?i)action /$ns/$name: Action description\\s*\\(parameters: paramName1, paramName2\\)")
+  }
+
+  it should "create an action with a name that contains spaces" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "action with spaces"
+
+    val res = assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, defaultAction)
+    }
+
+    res.stdout should include(s"ok: created action $name")
+  }
+
+  it should "create an action, and invoke an action that returns an empty JSON object" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "emptyJSONAction"
+
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, Some(TestUtils.getTestActionFilename("emptyJSONResult.js")))
+      }
+
+      val stdout = wsk.action.invoke(name, result = true).stdout
+      stdout.parseJson.asJsObject shouldBe JsObject()
+  }
+
+  it should "create, and invoke an action that times out to ensure the proper response is received" in withAssetCleaner(
+    wskprops) { (wp, assetHelper) =>
+    val name = "sleepAction"
+    val params = Map("payload" -> "100000".toJson)
+    val allowedActionDuration = 120 seconds
+    val res = assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, Some(TestUtils.getTestActionFilename("timeout.js")), timeout = Some(allowedActionDuration))
+      action.invoke(name, parameters = params, result = true, expectedExitCode = ACCEPTED)
     }
 
-    it should "reject deleting entity in wrong collection" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "testCrossDelete"
-            assetHelper.withCleaner(wsk.trigger, name) {
-                (trigger, _) => trigger.create(name)
-            }
-            wsk.action.delete(name, expectedExitCode = CONFLICT)
+    res.stderr should include("""but the request has not yet finished""")
+  }
+
+  it should "create, and get docker action get ensure exec code is omitted" in withAssetCleaner(wskprops) {
+    val name = "dockerContainer"
+    (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, None, docker = Some("fake-container"))
+      }
+
+      wsk.action.get(name).stdout should not include (""""code"""")
+  }
+
+  behavior of "Wsk Trigger CLI"
+
+  it should "create, update, get, fire and list trigger" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "listTriggers"
+    val params = Map("a" -> "A".toJson)
+    assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
+      trigger.create(name, parameters = params)
+      trigger.create(name, update = true)
+    }
+    val stdout = wsk.trigger.get(name).stdout
+    stdout should include regex (""""key": "a"""")
+    stdout should include regex (""""value": "A"""")
+    stdout should include regex (""""publish": false""")
+    stdout should include regex (""""version": "0.0.2"""")
+
+    val dynamicParams = Map("t" -> "T".toJson)
+    val run = wsk.trigger.fire(name, dynamicParams)
+    withActivation(wsk.activation, run) { activation =>
+      activation.response.result shouldBe Some(dynamicParams.toJson)
+      activation.duration shouldBe 0L // shouldn't exist but CLI generates it
+      activation.end shouldBe Instant.EPOCH // shouldn't exist but CLI generates it
     }
 
-    it should "reject unauthenticated access" in {
-        implicit val wskprops = WskProps("xxx") // shadow properties
-        val errormsg = "The supplied authentication is invalid"
-        wsk.namespace.list(expectedExitCode = UNAUTHORIZED).
-            stderr should include(errormsg)
-        wsk.namespace.get(expectedExitCode = UNAUTHORIZED).
-            stderr should include(errormsg)
+    val runWithNoParams = wsk.trigger.fire(name, Map())
+    withActivation(wsk.activation, runWithNoParams) { activation =>
+      activation.response.result shouldBe Some(JsObject())
+      activation.duration shouldBe 0L // shouldn't exist but CLI generates it
+      activation.end shouldBe Instant.EPOCH // shouldn't exist but CLI generates it
     }
 
-    behavior of "Wsk Package CLI"
-
-    it should "create, update, get and list a package" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "testPackage"
-            val params = Map("a" -> "A".toJson)
-            assetHelper.withCleaner(wsk.pkg, name) {
-                (pkg, _) =>
-                    pkg.create(name, parameters = params, shared = Some(true))
-                    pkg.create(name, update = true)
-            }
-            val stdout = wsk.pkg.get(name).stdout
-            stdout should include regex (""""key": "a"""")
-            stdout should include regex (""""value": "A"""")
-            stdout should include regex (""""publish": true""")
-            stdout should include regex (""""version": "0.0.2"""")
-            wsk.pkg.list().stdout should include(name)
+    wsk.trigger.list().stdout should include(name)
+  }
+
+  it should "create, and get a trigger summary" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "triggerName"
+    val annots = Map(
+      "description" -> JsString("Trigger description"),
+      "parameters" -> JsArray(
+        JsObject("name" -> JsString("paramName1"), "description" -> JsString("Parameter description 1")),
+        JsObject("name" -> JsString("paramName2"), "description" -> JsString("Parameter description 2"))))
+
+    assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
+      trigger.create(name, annotations = annots)
     }
 
-    it should "create, and get a package summary" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val packageName = "packageName"
-            val actionName = "actionName"
-            val packageAnnots = Map(
-                "description" -> JsString("Package description"),
-                "parameters" -> JsArray(
-                    JsObject(
-                        "name" -> JsString("paramName1"),
-                        "description" -> JsString("Parameter description 1")),
-                    JsObject(
-                        "name" -> JsString("paramName2"),
-                        "description" -> JsString("Parameter description 2"))))
-            val actionAnnots = Map(
-                "description" -> JsString("Action description"),
-                "parameters" -> JsArray(
-                    JsObject(
-                        "name" -> JsString("paramName1"),
-                        "description" -> JsString("Parameter description 1")),
-                    JsObject(
-                        "name" -> JsString("paramName2"),
-                        "description" -> JsString("Parameter description 2"))))
-
-            assetHelper.withCleaner(wsk.pkg, packageName) {
-                (pkg, _) => pkg.create(packageName, annotations = packageAnnots)
-            }
-
-            wsk.action.create(packageName + "/" + actionName, defaultAction, annotations = actionAnnots)
-            val stdout = wsk.pkg.get(packageName, summary = true).stdout
-            val ns = wsk.namespace.whois()
-            wsk.action.delete(packageName + "/" + actionName)
-
-            stdout should include regex (s"(?i)package /$ns/$packageName: Package description\\s*\\(parameters: paramName1, paramName2\\)")
-            stdout should include regex (s"(?i)action /$ns/$packageName/$actionName: Action description\\s*\\(parameters: paramName1, paramName2\\)")
-    }
-
-    it should "create a package with a name that contains spaces" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "package with spaces"
-
-            val res = assetHelper.withCleaner(wsk.pkg, name) {
-                (pkg, _) => pkg.create(name)
-            }
-
-            res.stdout should include(s"ok: created package $name")
-    }
-
-    it should "create a package, and get its individual fields" in withAssetCleaner(wskprops) {
-        val name = "packageFields"
-        val paramInput = Map("payload" -> "test".toJson)
-        val successMsg = s"ok: got package $name, displaying field"
-
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.pkg, name) {
-                (pkg, _) => pkg.create(name, parameters = paramInput)
-            }
-
-            val expectedParam = JsObject("payload" -> JsString("test"))
-            val ns = wsk.namespace.whois()
-
-            wsk.pkg.get(name, fieldFilter = Some("namespace")).stdout should include regex (s"""(?i)$successMsg namespace\n"$ns"""")
-            wsk.pkg.get(name, fieldFilter = Some("name")).stdout should include(s"""$successMsg name\n"$name"""")
-            wsk.pkg.get(name, fieldFilter = Some("version")).stdout should include(s"""$successMsg version\n"0.0.1"""")
-            wsk.pkg.get(name, fieldFilter = Some("publish")).stdout should include(s"""$successMsg publish\nfalse""")
-            wsk.pkg.get(name, fieldFilter = Some("binding")).stdout should include regex (s"""\\{\\}""")
-            wsk.pkg.get(name, fieldFilter = Some("invalid"), expectedExitCode = ERROR_EXIT).stderr should include("error: Invalid field filter 'invalid'.")
-    }
-
-    it should "reject creation of duplication packages" in withAssetCleaner(wskprops) {
-        val name = "dupePackage"
-
-        (wp, assetHelper) => assetHelper.withCleaner(wsk.pkg, name) {
-            (pkg, _) => pkg.create(name)
-        }
-
-        val stderr = wsk.pkg.create(name, expectedExitCode = CONFLICT).stderr
-        stderr should include regex (s"""Unable to create package '$name': resource already exists \\(code \\d+\\)""")
-    }
-
-    it should "reject delete of package that does not exist" in {
-        val name = "nonexistentPackage"
-        val stderr = wsk.pkg.delete(name, expectedExitCode = NOT_FOUND).stderr
-        stderr should include regex (s"""Unable to delete package '$name'. The requested resource does not exist. \\(code \\d+\\)""")
-    }
-
-    it should "reject get of package that does not exist" in {
-        val name = "nonexistentPackage"
-        val stderr = wsk.pkg.get(name, expectedExitCode = NOT_FOUND).stderr
-        stderr should include regex (s"""Unable to get package '$name': The requested resource does not exist. \\(code \\d+\\)""")
-    }
-
-    behavior of "Wsk Action CLI"
-
-    it should "create the same action twice with different cases" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.action, "TWICE") { (action, name) => action.create(name, defaultAction) }
-            assetHelper.withCleaner(wsk.action, "twice") { (action, name) => action.create(name, defaultAction) }
-    }
-
-    it should "create, update, get and list an action" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "createAndUpdate"
-            val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
-            val params = Map("a" -> "A".toJson)
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) =>
-                    action.create(name, file, parameters = params)
-                    action.create(name, None, parameters = Map("b" -> "B".toJson), update = true)
-            }
-
-            val stdout = wsk.action.get(name).stdout
-            stdout should not include regex(""""key": "a"""")
-            stdout should not include regex(""""value": "A"""")
-            stdout should include regex (""""key": "b""")
-            stdout should include regex (""""value": "B"""")
-            stdout should include regex (""""publish": false""")
-            stdout should include regex (""""version": "0.0.2"""")
-            wsk.action.list().stdout should include(name)
-    }
-
-    it should "reject create of an action that already exists" in withAssetCleaner(wskprops) {
-        val name = "dupeAction"
-        val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
-
-        (wp, assetHelper) => assetHelper.withCleaner(wsk.action, name) {
-            (action, _) => action.create(name, file)
-        }
-
-        val stderr = wsk.action.create(name, file, expectedExitCode = CONFLICT).stderr
-        stderr should include regex (s"""Unable to create action '$name': resource already exists \\(code \\d+\\)""")
-    }
-
-    it should "reject delete of action that does not exist" in {
-        val name = "nonexistentAction"
-        val stderr = wsk.action.delete(name, expectedExitCode = NOT_FOUND).stderr
-        stderr should include regex (s"""Unable to delete action '$name'. The requested resource does not exist. \\(code \\d+\\)""")
-    }
-
-    it should "reject invocation of action that does not exist" in {
-        val name = "nonexistentAction"
-        val stderr = wsk.action.invoke(name, expectedExitCode = NOT_FOUND).stderr
-        stderr should include regex (s"""Unable to invoke action '$name': The requested resource does not exist. \\(code \\d+\\)""")
-    }
-
-    it should "reject get of an action that does not exist" in {
-        val name = "nonexistentAction"
-        val stderr = wsk.action.get(name, expectedExitCode = NOT_FOUND).stderr
-        stderr should include regex (s"""Unable to get action '$name': The requested resource does not exist. \\(code \\d+\\)""")
-    }
-
-    it should "create, and invoke an action that utilizes a docker container" in withAssetCleaner(wskprops) {
-        val name = "dockerContainer"
-        (wp, assetHelper) => assetHelper.withCleaner(wsk.action, name) {
-            // this docker image will be need to be pulled from dockerhub and hence has to be published there first
-            (action, _) => action.create(name, None, docker = Some("openwhisk/example"))
-        }
-
-        val args = Map("payload" -> "test".toJson)
-        val run = wsk.action.invoke(name, args)
-        withActivation(wsk.activation, run) {
-            activation =>
-                activation.response.result shouldBe Some(JsObject(
-                    "args" -> args.toJson,
-                    "msg" -> "Hello from arbitrary C program!".toJson))
-        }
-    }
-
-    it should "create, and invoke an action that utilizes dockerskeleton with native zip" in withAssetCleaner(wskprops) {
-        val name = "dockerContainerWithZip"
-        (wp, assetHelper) => assetHelper.withCleaner(wsk.action, name) {
-            // this docker image will be need to be pulled from dockerhub and hence has to be published there first
-            (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("blackbox.zip")), kind = Some("native"))
-        }
-
-        val run = wsk.action.invoke(name, Map())
-        withActivation(wsk.activation, run) {
-            activation =>
-                activation.response.result shouldBe Some(JsObject(
-                    "msg" -> "hello zip".toJson))
-                activation.logs shouldBe defined
-                val logs = activation.logs.get.toString
-                logs should include("This is an example zip used with the docker skeleton action.")
-                logs should not include ("XXX_THE_END_OF_A_WHISK_ACTIVATION_XXX")
-        }
-    }
-
-    it should "create, and invoke an action using a parameter file" in withAssetCleaner(wskprops) {
-        val name = "paramFileAction"
-        val file = Some(TestCLIUtils.getTestActionFilename("argCheck.js"))
-        val argInput = Some(TestCLIUtils.getTestActionFilename("validInput2.json"))
-
-        (wp, assetHelper) => assetHelper.withCleaner(wsk.action, name) {
-            (action, _) => action.create(name, file)
-        }
-
-        val expectedOutput = JsObject("payload" -> JsString("test"))
-        val run = wsk.action.invoke(name, parameterFile = argInput)
-        withActivation(wsk.activation, run) {
-            activation => activation.response.result shouldBe Some(expectedOutput)
-        }
-    }
-
-    it should "create an action, and get its individual fields" in withAssetCleaner(wskprops) {
-        val name = "actionFields"
-        val paramInput = Map("payload" -> "test".toJson)
-        val successMsg = s"ok: got action $name, displaying field"
-
-        (wp, assetHelper) => assetHelper.withCleaner(wsk.action, name) {
-            (action, _) => action.create(name, defaultAction, parameters = paramInput)
-        }
-
-        val expectedParam = JsObject("payload" -> JsString("test"))
-        val ns = wsk.namespace.whois()
-
-        wsk.action.get(name, fieldFilter = Some("name")).stdout should include(s"""$successMsg name\n"$name"""")
-        wsk.action.get(name, fieldFilter = Some("version")).stdout should include(s"""$successMsg version\n"0.0.1"""")
-        wsk.action.get(name, fieldFilter = Some("exec")).stdout should include(s"""$successMsg""")
-        wsk.action.get(name, fieldFilter = Some("exec")).stdout should include regex (s"""$successMsg exec\n\\{\\s+"kind":\\s+"nodejs:6",\\s+"code":\\s+"\\/\\*\\*[\\\\r]*\\\\n \\* Hello, world.[\\\\r]*\\\\n \\*\\/[\\\\r]*\\\\nfunction main\\(params\\) \\{[\\\\r]*\\\\n    greeting \\= 'hello, ' \\+ params.payload \\+ '!'[\\\\r]*\\\\n    console.log\\(greeting\\);[\\\\r]*\\\\n    return \\{payload: greeting\\}[\\\\r]*\\\\n\\}""")
-        wsk.action.get(name, fieldFilter = Some("parameters")).stdout should include regex (s"""$successMsg parameters\n\\[\\s+\\{\\s+"key":\\s+"payload",\\s+"value":\\s+"test"\\s+\\}\\s+\\]""")
-        wsk.action.get(name, fieldFilter = Some("annotations")).stdout should include regex (s"""$successMsg annotations\n\\[\\s+\\{\\s+"key":\\s+"exec",\\s+"value":\\s+"nodejs:6"\\s+\\}\\s+\\]""")
-        wsk.action.get(name, fieldFilter = Some("limits")).stdout should include regex (s"""$successMsg limits\n\\{\\s+"timeout":\\s+60000,\\s+"memory":\\s+256,\\s+"logs":\\s+10\\s+\\}""")
-        wsk.action.get(name, fieldFilter = Some("namespace")).stdout should include regex (s"""(?i)$successMsg namespace\n"$ns"""")
-        wsk.action.get(name, fieldFilter = Some("invalid"), expectedExitCode = MISUSE_EXIT).stderr should include("error: Invalid field filter 'invalid'.")
-        wsk.action.get(name, fieldFilter = Some("publish")).stdout should include(s"""$successMsg publish\nfalse""")
-    }
-
-    /**
-     * Tests creating an action from a malformed js file. This should fail in
-     * some way - preferably when trying to create the action. If not, then
-     * surely when it runs there should be some indication in the logs. Don't
-     * think this is true currently.
-     */
-    it should "create and invoke action with malformed js resulting in activation error" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "MALFORMED"
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("malformed.js")))
-            }
-
-            val run = wsk.action.invoke(name, Map("payload" -> "whatever".toJson))
-            withActivation(wsk.activation, run) {
-                activation =>
-                    activation.response.status shouldBe "action developer error"
-                    // representing nodejs giving an error when given malformed.js
-                    activation.response.result.get.toString should include("ReferenceError")
-            }
-    }
-
-    it should "create and invoke a blocking action resulting in an application error response" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "applicationError"
-            val strErrInput = Map("error" -> "Error message".toJson)
-            val numErrInput = Map("error" -> 502.toJson)
-            val boolErrInput = Map("error" -> true.toJson)
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("echo.js")))
-            }
-
-            Seq(strErrInput, numErrInput, boolErrInput) foreach { input =>
-                getJSONFromCLIResponse(wsk.action.invoke(name, parameters = input, blocking = true, expectedExitCode = 246).stderr).
-                    fields("response").asJsObject.fields("result").asJsObject shouldBe input.toJson.asJsObject
-
-                wsk.action.invoke(name, parameters = input, blocking = true, result = true, expectedExitCode = 246).
-                    stderr.parseJson.asJsObject shouldBe input.toJson.asJsObject
-            }
-    }
-
-    it should "create and invoke a blocking action resulting in an failed promise" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "errorResponseObject"
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("asyncError.js")))
-            }
-
-            val stderr = wsk.action.invoke(name, blocking = true, expectedExitCode = 246).stderr
-            ActivationResult.serdes.read(removeCLIHeader(stderr).parseJson).response.result shouldBe Some {
-                JsObject("error" -> JsObject("msg" -> "failed activation on purpose".toJson))
-            }
-    }
-
-    it should "invoke a blocking action and get only the result" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "basicInvoke"
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("wc.js")))
-            }
-
-            wsk.action.invoke(name, Map("payload" -> "one two three".toJson), result = true)
-                .stdout should include regex (""""count": 3""")
-    }
-
-    it should "create, and get an action summary" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "actionName"
-            val annots = Map(
-                "description" -> JsString("Action description"),
-                "parameters" -> JsArray(
-                    JsObject(
-                        "name" -> JsString("paramName1"),
-                        "description" -> JsString("Parameter description 1")),
-                    JsObject(
-                        "name" -> JsString("paramName2"),
-                        "description" -> JsString("Parameter description 2"))))
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) =>
-                    action.create(name, defaultAction, annotations = annots)
-            }
-
-            val stdout = wsk.action.get(name, summary = true).stdout
-            val ns = wsk.namespace.whois()
-
-            stdout should include regex (s"(?i)action /$ns/$name: Action description\\s*\\(parameters: paramName1, paramName2\\)")
-    }
-
-    it should "create an action with a name that contains spaces" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "action with spaces"
-
-            val res = assetHelper.withCleaner(wsk.action, name) {
-                (action, _) =>
-                    action.create(name, defaultAction)
-            }
-
-            res.stdout should include(s"ok: created action $name")
-    }
-
-    it should "create an action, and invoke an action that returns an empty JSON object" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "emptyJSONAction"
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) =>
-                    action.create(name, Some(TestCLIUtils.getTestActionFilename("emptyJSONResult.js")))
-            }
-
-            val stdout = wsk.action.invoke(name, result = true).stdout
-            stdout.parseJson.asJsObject shouldBe JsObject()
-    }
-
-    it should "create, and invoke an action that times out to ensure the proper response is received" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "sleepAction"
-            val params = Map("payload" -> "100000".toJson)
-            val allowedActionDuration = 120 seconds
-            val res = assetHelper.withCleaner(wsk.action, name) {
-                (action, _) =>
-                    action.create(name, Some(TestCLIUtils.getTestActionFilename("timeout.js")),
-                        timeout = Some(allowedActionDuration))
-                    action.invoke(name, parameters = params, result = true, expectedExitCode = ACCEPTED)
-            }
-
-            res.stderr should include("""but the request has not yet finished""")
-    }
-
-    it should "create, and get docker action get ensure exec code is omitted" in withAssetCleaner(wskprops) {
-        val name = "dockerContainer"
-        (wp, assetHelper) => assetHelper.withCleaner(wsk.action, name) {
-            (action, _) => action.create(name, None, docker = Some("fake-container"))
-        }
+    val stdout = wsk.trigger.get(name, summary = true).stdout
+    val ns = wsk.namespace.whois()
 
-        wsk.action.get(name).stdout should not include (""""code"""")
-    }
-
-    behavior of "Wsk Trigger CLI"
-
-    it should "create, update, get, fire and list trigger" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "listTriggers"
-            val params = Map("a" -> "A".toJson)
-            assetHelper.withCleaner(wsk.trigger, name) {
-                (trigger, _) =>
-                    trigger.create(name, parameters = params)
-                    trigger.create(name, update = true)
-            }
-            val stdout = wsk.trigger.get(name).stdout
-            stdout should include regex (""""key": "a"""")
-            stdout should include regex (""""value": "A"""")
-            stdout should include regex (""""publish": false""")
-            stdout should include regex (""""version": "0.0.2"""")
-
-            val dynamicParams = Map("t" -> "T".toJson)
-            val run = wsk.trigger.fire(name, dynamicParams)
-            withActivation(wsk.activation, run) {
-                activation =>
-                    activation.response.result shouldBe Some(dynamicParams.toJson)
-                    activation.duration shouldBe 0L // shouldn't exist but CLI generates it
-                    activation.end shouldBe Instant.EPOCH // shouldn't exist but CLI generates it
-            }
-
-            val runWithNoParams = wsk.trigger.fire(name, Map())
-            withActivation(wsk.activation, runWithNoParams) {
-                activation =>
-                    activation.response.result shouldBe Some(JsObject())
-                    activation.duration shouldBe 0L // shouldn't exist but CLI generates it
-                    activation.end shouldBe Instant.EPOCH // shouldn't exist but CLI generates it
-            }
-
-            wsk.trigger.list().stdout should include(name)
-    }
-
-    it should "create, and get a trigger summary" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "triggerName"
-            val annots = Map(
-                "description" -> JsString("Trigger description"),
-                "parameters" -> JsArray(
-                    JsObject(
-                        "name" -> JsString("paramName1"),
-                        "description" -> JsString("Parameter description 1")),
-                    JsObject(
-                        "name" -> JsString("paramName2"),
-                        "description" -> JsString("Parameter description 2"))))
-
-            assetHelper.withCleaner(wsk.trigger, name) {
-                (trigger, _) =>
-                    trigger.create(name, annotations = annots)
-            }
-
-            val stdout = wsk.trigger.get(name, summary = true).stdout
-            val ns = wsk.namespace.whois()
-
-            stdout should include regex (s"trigger /$ns/$name: Trigger description\\s*\\(parameters: paramName1, paramName2\\)")
-    }
-
-    it should "create a trigger with a name that contains spaces" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "trigger with spaces"
-
-            val res = assetHelper.withCleaner(wsk.trigger, name) {
-                (trigger, _) => trigger.create(name)
-            }
-
-            res.stdout should include regex (s"ok: created trigger $name")
-    }
-
-    it should "create, and fire a trigger using a parameter file" in withAssetCleaner(wskprops) {
-        val name = "paramFileTrigger"
-        val file = Some(TestCLIUtils.getTestActionFilename("argCheck.js"))
-        val argInput = Some(TestCLIUtils.getTestActionFilename("validInput2.json"))
-
-        (wp, assetHelper) => assetHelper.withCleaner(wsk.trigger, name) {
-            (trigger, _) => trigger.create(name)
-        }
-
-        val expectedOutput = JsObject("payload" -> JsString("test"))
-        val run = wsk.trigger.fire(name, parameterFile = argInput)
-        withActivation(wsk.activation, run) {
-            activation => activation.response.result shouldBe Some(expectedOutput)
-        }
-    }
-
-    it should "create a trigger, and get its individual fields" in withAssetCleaner(wskprops) {
-        val name = "triggerFields"
-        val paramInput = Map("payload" -> "test".toJson)
-        val successMsg = s"ok: got trigger $name, displaying field"
-
-        (wp, assetHelper) => assetHelper.withCleaner(wsk.trigger, name) {
-            (trigger, _) => trigger.create(name, parameters = paramInput)
-        }
-
-        val expectedParam = JsObject("payload" -> JsString("test"))
-        val ns = wsk.namespace.whois()
-
-        wsk.trigger.get(name, fieldFilter = Some("namespace")).stdout should include regex (s"""(?i)$successMsg namespace\n"$ns"""")
-        wsk.trigger.get(name, fieldFilter = Some("name")).stdout should include(s"""$successMsg name\n"$name"""")
-        wsk.trigger.get(name, fieldFilter = Some("version")).stdout should include(s"""$successMsg version\n"0.0.1"""")
-        wsk.trigger.get(name, fieldFilter = Some("publish")).stdout should include(s"""$successMsg publish\nfalse""")
-        wsk.trigger.get(name, fieldFilter = Some("annotations")).stdout should include(s"""$successMsg annotations\n[]""")
-        wsk.trigger.get(name, fieldFilter = Some("parameters")).stdout should include regex (s"""$successMsg parameters\n\\[\\s+\\{\\s+"key":\\s+"payload",\\s+"value":\\s+"test"\\s+\\}\\s+\\]""")
-        wsk.trigger.get(name, fieldFilter = Some("limits")).stdout should include(s"""$successMsg limits\n{}""")
-        wsk.trigger.get(name, fieldFilter = Some("invalid"), expectedExitCode = ERROR_EXIT).stderr should include("error: Invalid field filter 'invalid'.")
-    }
-
-    it should "create, and fire a trigger to ensure result is empty" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "emptyResultTrigger"
-            assetHelper.withCleaner(wsk.trigger, name) {
-                (trigger, _) => trigger.create(name)
-            }
-
-            val run = wsk.trigger.fire(name)
-            withActivation(wsk.activation, run) {
-                activation => activation.response.result shouldBe Some(JsObject())
-            }
-    }
-
-    it should "reject creation of duplicate triggers" in withAssetCleaner(wskprops) {
-        val name = "dupeTrigger"
-
-        (wp, assetHelper) => assetHelper.withCleaner(wsk.trigger, name) {
-            (trigger, _) => trigger.create(name)
-        }
-
-        val stderr = wsk.trigger.create(name, expectedExitCode = CONFLICT).stderr
-        stderr should include regex (s"""Unable to create trigger '$name': resource already exists \\(code \\d+\\)""")
-    }
-
-    it should "reject delete of trigger that does not exist" in {
-        val name = "nonexistentTrigger"
-        val stderr = wsk.trigger.delete(name, expectedExitCode = NOT_FOUND).stderr
-        stderr should include regex (s"""Unable to get trigger '$name'. The requested resource does not exist. \\(code \\d+\\)""")
-    }
-
-    it should "reject get of trigger that does not exist" in {
-        val name = "nonexistentTrigger"
-        val stderr = wsk.trigger.get(name, expectedExitCode = NOT_FOUND).stderr
-        stderr should include regex (s"""Unable to get trigger '$name': The requested resource does not exist. \\(code \\d+\\)""")
-    }
-
-    it should "reject firing of a trigger that does not exist" in {
-        val name = "nonexistentTrigger"
-        val stderr = wsk.trigger.fire(name, expectedExitCode = NOT_FOUND).stderr
-        stderr should include regex (s"""Unable to fire trigger '$name': The requested resource does not exist. \\(code \\d+\\)""")
-    }
-
-    behavior of "Wsk Rule CLI"
-
-    it should "create rule, get rule, update rule and list rule" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val ruleName = "listRules"
-            val triggerName = "listRulesTrigger"
-            val actionName = "listRulesAction"
-
-            assetHelper.withCleaner(wsk.trigger, triggerName) {
-                (trigger, name) => trigger.create(name)
-            }
-            assetHelper.withCleaner(wsk.action, actionName) {
-                (action, name) => action.create(name, defaultAction)
-            }
-            assetHelper.withCleaner(wsk.rule, ruleName) {
-                (rule, name) =>
-                    rule.create(name, trigger = triggerName, action = actionName)
-            }
-
-            // finally, we perform the update, and expect success this time
-            wsk.rule.create(ruleName, trigger = triggerName, action = actionName, update = true)
-
-            val stdout = wsk.rule.get(ruleName).stdout
-            stdout should include(ruleName)
-            stdout should include(triggerName)
-            stdout should include(actionName)
-            stdout should include regex (""""version": "0.0.2"""")
-            wsk.rule.list().stdout should include(ruleName)
-    }
-
-    it should "create rule, get rule, ensure rule is enabled by default" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val ruleName = "enabledRule"
-            val triggerName = "enabledRuleTrigger"
-            val actionName = "enabledRuleAction"
-
-            assetHelper.withCleaner(wsk.trigger, triggerName) {
-                (trigger, name) => trigger.create(name)
-            }
-            assetHelper.withCleaner(wsk.action, actionName) {
-                (action, name) => action.create(name, defaultAction)
-            }
-            assetHelper.withCleaner(wsk.rule, ruleName) {
-                (rule, name) => rule.create(name, trigger = triggerName, action = actionName)
-            }
-
-            val stdout = wsk.rule.get(ruleName).stdout
-            stdout should include regex (""""status":\s*"active"""")
-    }
-
-    it should "display a rule summary when --summary flag is used with 'wsk rule get'" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val ruleName = "mySummaryRule"
-            val triggerName = "summaryRuleTrigger"
-            val actionName = "summaryRuleAction"
-
-            assetHelper.withCleaner(wsk.trigger, triggerName) {
-                (trigger, name) => trigger.create(name)
-            }
-            assetHelper.withCleaner(wsk.action, actionName) {
-                (action, name) => action.create(name, defaultAction)
-            }
-            assetHelper.withCleaner(wsk.rule, ruleName, confirmDelete = false) {
-                (rule, name) => rule.create(name, trigger = triggerName, action = actionName)
-            }
-
-            // Summary namespace should match one of the allowable namespaces (typically 'guest')
-            val ns = wsk.namespace.whois()
-            val stdout = wsk.rule.get(ruleName, summary = true).stdout
-
-            stdout should include regex (s"(?i)rule /$ns/$ruleName\\s*\\(status: active\\)")
-    }
-
-    it should "create a rule, and get its individual fields" in withAssetCleaner(wskprops) {
-        val ruleName = "ruleFields"
-        val triggerName = "ruleTriggerFields"
-        val actionName = "ruleActionFields"
-        val paramInput = Map("payload" -> "test".toJson)
-        val successMsg = s"ok: got rule $ruleName, displaying field"
-
-        (wp, assetHelper) => assetHelper.withCleaner(wsk.trigger, triggerName) {
-            (trigger, name) => trigger.create(name)
-        }
-        assetHelper.withCleaner(wsk.action, actionName) {
-            (action, name) => action.create(name, defaultAction)
-        }
-        assetHelper.withCleaner(wsk.rule, ruleName) {
-            (rule, name) => rule.create(name, trigger = triggerName, action = actionName)
-        }
-
-        val ns = wsk.namespace.whois()
-        wsk.rule.get(ruleName, fieldFilter = Some("namespace")).stdout should include regex (s"""(?i)$successMsg namespace\n"$ns"""")
-        wsk.rule.get(ruleName, fieldFilter = Some("name")).stdout should include(s"""$successMsg name\n"$ruleName"""")
-        wsk.rule.get(ruleName, fieldFilter = Some("version")).stdout should include(s"""$successMsg version\n"0.0.1"\n""")
-        wsk.rule.get(ruleName, fieldFilter = Some("status")).stdout should include(s"""$successMsg status\n"active"""")
-        val trigger = wsk.rule.get(ruleName, fieldFilter = Some("trigger")).stdout
-        trigger should include regex (s"""$successMsg trigger\n""")
-        trigger should include(triggerName)
-        trigger should not include (actionName)
-        val action = wsk.rule.get(ruleName, fieldFilter = Some("action")).stdout
-        action should include regex (s"""$successMsg action\n""")
-        action should include(actionName)
-        action should not include (triggerName)
-    }
-
-    it should "reject creation of duplicate rules" in withAssetCleaner(wskprops) {
-        val ruleName = "dupeRule"
-        val triggerName = "triggerName"
-        val actionName = "actionName"
-
-        (wp, assetHelper) => assetHelper.withCleaner(wsk.trigger, triggerName) {
-            (trigger, name) => trigger.create(name)
-        }
-        assetHelper.withCleaner(wsk.action, actionName) {
-            (action, name) => action.create(name, defaultAction)
-        }
-        assetHelper.withCleaner(wsk.rule, ruleName) {
-            (rule, name) => rule.create(name, trigger = triggerName, action = actionName)
-        }
-
-        val stderr = wsk.rule.create(ruleName, trigger = triggerName, action = actionName, expectedExitCode = CONFLICT).stderr
-        stderr should include regex (s"""Unable to create rule '$ruleName': resource already exists \\(code \\d+\\)""")
-    }
-
-    it should "reject delete of rule that does not exist" in {
-        val name = "nonexistentRule"
-        val stderr = wsk.rule.delete(name, expectedExitCode = NOT_FOUND).stderr
-        stderr should include regex (s"""Unable to delete rule '$name'. The requested resource does not exist. \\(code \\d+\\)""")
-    }
-
-    it should "reject enable of rule that does not exist" in {
-        val name = "nonexistentRule"
-        val stderr = wsk.rule.enable(name, expectedExitCode = NOT_FOUND).stderr
-        stderr should include regex (s"""Unable to enable rule '$name': The requested resource does not exist. \\(code \\d+\\)""")
-    }
-
-    it should "reject disable of rule that does not exist" in {
-        val name = "nonexistentRule"
-        val stderr = wsk.rule.disable(name, expectedExitCode = NOT_FOUND).stderr
-        stderr should include regex (s"""Unable to disable rule '$name': The requested resource does not exist. \\(code \\d+\\)""")
-    }
-
-    it should "reject status of rule that does not exist" in {
-        val name = "nonexistentRule"
-        val stderr = wsk.rule.state(name, expectedExitCode = NOT_FOUND).stderr
-        stderr should include regex (s"""Unable to get status of rule '$name': The requested resource does not exist. \\(code \\d+\\)""")
-    }
-
-    it should "reject get of rule that does not exist" in {
-        val name = "nonexistentRule"
-        val stderr = wsk.rule.get(name, expectedExitCode = NOT_FOUND).stderr
-        stderr should include regex (s"""Unable to get rule '$name': The requested resource does not exist. \\(code \\d+\\)""")
-    }
-
-    behavior of "Wsk Namespace CLI"
-
-    it should "return a list of exactly one namespace" in {
-        val lines = wsk.namespace.list().stdout.lines.toSeq
-        lines should have size 2
-        lines.head shouldBe "namespaces"
-        lines(1).trim should not be empty
-    }
-
-    it should "list entities in default namespace" in {
-        // use a fresh wsk props instance that is guaranteed to use
-        // the default namespace
-        wsk.namespace.get(expectedExitCode = SUCCESS_EXIT)(WskProps()).
-            stdout should include("default")
-    }
-
-    it should "not list entities with an invalid namespace" in {
-        val namespace = "fakeNamespace"
-        val stderr = wsk.namespace.get(Some(s"/${namespace}"), expectedExitCode = FORBIDDEN).stderr
-
-        stderr should include(s"Unable to obtain the list of entities for namespace '${namespace}'")
-    }
-
-    behavior of "Wsk Activation CLI"
-
-    it should "create a trigger, and fire a trigger to get its individual fields from an activation" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "activationFields"
-
-            assetHelper.withCleaner(wsk.trigger, name) {
-                (trigger, _) =>
-                    trigger.create(name)
-            }
-
-            val ns = s""""${wsk.namespace.whois()}""""
-            val run = wsk.trigger.fire(name)
-            withActivation(wsk.activation, run) {
-                activation =>
-                    val successMsg = s"ok: got activation ${activation.activationId}, displaying field"
-                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("namespace")).stdout should include regex (s"""(?i)$successMsg namespace\n$ns""")
-                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("name")).stdout should include(s"""$successMsg name\n"$name"""")
-                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("version")).stdout should include(s"""$successMsg version\n"0.0.1"""")
-                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("publish")).stdout should include(s"""$successMsg publish\nfalse""")
-                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("subject")).stdout should include regex (s"""(?i)$successMsg subject\n""")
-                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("activationid")).stdout should include(s"""$successMsg activationid\n"${activation.activationId}""")
-                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("start")).stdout should include regex (s"""$successMsg start\n\\d""")
-                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("end")).stdout should include regex (s"""$successMsg end\n\\d""")
-                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("duration")).stdout should include regex (s"""$successMsg duration\n\\d""")
-                    wsk.activation.get(Some(activation.activationId), fieldFilter = Some("annotations")).stdout should include(s"""$successMsg annotations\n[]""")
-            }
-    }
-
-    it should "reject get of activation that does not exist" in {
-        val name = "0" * 32
-        val stderr = wsk.activation.get(Some(name), expectedExitCode = NOT_FOUND).stderr
-        stderr should include regex (s"""Unable to get activation '$name': The requested resource does not exist. \\(code \\d+\\)""")
-    }
-
-    it should "reject logs of activation that does not exist" in {
-        val name = "0" * 32
-        val stderr = wsk.activation.logs(Some(name), expectedExitCode = NOT_FOUND).stderr
-        stderr should include regex (s"""Unable to get logs for activation '$name': The requested resource does not exist. \\(code \\d+\\)""")
-    }
-
-    it should "reject result of activation that does not exist" in {
-        val name = "0" * 32
-        val stderr = wsk.activation.result(Some(name), expectedExitCode = NOT_FOUND).stderr
-        stderr should include regex (s"""Unable to get result for activation '$name': The requested resource does not exist. \\(code \\d+\\)""")
-    }
-
-    it should "reject activation request when using activation ID with --last Flag" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val auth: Seq[String] = Seq("--auth", wskprops.authKey)
-
-            val lastId = "dummyActivationId"
-            val tooManyArgsMsg = s"${lastId}. An activation ID is required."
-            val invalidField = s"Invalid field filter '${lastId}'."
-
-            val invalidCmd = Seq(
-                (Seq("activation", "get", s"$lastId", "publish", "--last"), tooManyArgsMsg),
-                (Seq("activation", "get", s"$lastId", "--last"), invalidField),
-                (Seq("activation", "logs", s"$lastId", "--last"), tooManyArgsMsg),
-                (Seq("activation", "result", s"$lastId", "--last"), tooManyArgsMsg))
-
-            invalidCmd foreach {
-                case (cmd, err) =>
-                    val stderr = wsk.cli(cmd ++ wskprops.overrides ++ auth, expectedExitCode = ERROR_EXIT).stderr
-                    stderr should include(err)
-            }
-    }
+    stdout should include regex (s"trigger /$ns/$name: Trigger description\\s*\\(parameters: paramName1, paramName2\\)")
+  }
+
+  it should "create a trigger with a name that contains spaces" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "trigger with spaces"
+
+    val res = assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
+      trigger.create(name)
+    }
+
+    res.stdout should include regex (s"ok: created trigger $name")
+  }
+
+  it should "create, and fire a trigger using a parameter file" in withAssetCleaner(wskprops) {
+    val name = "paramFileTrigger"
+    val file = Some(TestUtils.getTestActionFilename("argCheck.js"))
+    val argInput = Some(TestUtils.getTestActionFilename("validInput2.json"))
+
+    (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
+        trigger.create(name)
+      }
+
+      val expectedOutput = JsObject("payload" -> JsString("test"))
+      val run = wsk.trigger.fire(name, parameterFile = argInput)
+      withActivation(wsk.activation, run) { activation =>
+        activation.response.result shouldBe Some(expectedOutput)
+      }
+  }
+
+  it should "create a trigger, and get its individual fields" in withAssetCleaner(wskprops) {
+    val name = "triggerFields"
+    val paramInput = Map("payload" -> "test".toJson)
+    val successMsg = s"ok: got trigger $name, displaying field"
+
+    (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
+        trigger.create(name, parameters = paramInput)
+      }
+
+      val expectedParam = JsObject("payload" -> JsString("test"))
+      val ns = wsk.namespace.whois()
+
+      wsk.trigger
+        .get(name, fieldFilter = Some("namespace"))
+        .stdout should include regex (s"""(?i)$successMsg namespace\n"$ns"""")
+      wsk.trigger.get(name, fieldFilter = Some("name")).stdout should include(s"""$successMsg name\n"$name"""")
+      wsk.trigger.get(name, fieldFilter = Some("version")).stdout should include(s"""$successMsg version\n"0.0.1"""")
+      wsk.trigger.get(name, fieldFilter = Some("publish")).stdout should include(s"""$successMsg publish\nfalse""")
+      wsk.trigger.get(name, fieldFilter = Some("annotations")).stdout should include(s"""$successMsg annotations\n[]""")
+      wsk.trigger
+        .get(name, fieldFilter = Some("parameters"))
+        .stdout should include regex (s"""$successMsg parameters\n\\[\\s+\\{\\s+"key":\\s+"payload",\\s+"value":\\s+"test"\\s+\\}\\s+\\]""")
+      wsk.trigger.get(name, fieldFilter = Some("limits")).stdout should include(s"""$successMsg limits\n{}""")
+      wsk.trigger.get(name, fieldFilter = Some("invalid"), expectedExitCode = ERROR_EXIT).stderr should include(
+        "error: Invalid field filter 'invalid'.")
+  }
+
+  it should "create, and fire a trigger to ensure result is empty" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "emptyResultTrigger"
+    assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
+      trigger.create(name)
+    }
+
+    val run = wsk.trigger.fire(name)
+    withActivation(wsk.activation, run) { activation =>
+      activation.response.result shouldBe Some(JsObject())
+    }
+  }
+
+  it should "reject creation of duplicate triggers" in withAssetCleaner(wskprops) {
+    val name = "dupeTrigger"
+
+    (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
+        trigger.create(name)
+      }
+
+      val stderr = wsk.trigger.create(name, expectedExitCode = CONFLICT).stderr
+      stderr should include regex (s"""Unable to create trigger '$name': resource already exists \\(code \\d+\\)""")
+  }
+
+  it should "reject delete of trigger that does not exist" in {
+    val name = "nonexistentTrigger"
+    val stderr = wsk.trigger.delete(name, expectedExitCode = NOT_FOUND).stderr
+    stderr should include regex (s"""Unable to get trigger '$name'. The requested resource does not exist. \\(code \\d+\\)""")
+  }
+
+  it should "reject get of trigger that does not exist" in {
+    val name = "nonexistentTrigger"
+    val stderr = wsk.trigger.get(name, expectedExitCode = NOT_FOUND).stderr
+    stderr should include regex (s"""Unable to get trigger '$name': The requested resource does not exist. \\(code \\d+\\)""")
+  }
+
+  it should "reject firing of a trigger that does not exist" in {
+    val name = "nonexistentTrigger"
+    val stderr = wsk.trigger.fire(name, expectedExitCode = NOT_FOUND).stderr
+    stderr should include regex (s"""Unable to fire trigger '$name': The requested resource does not exist. \\(code \\d+\\)""")
+  }
+
+  behavior of "Wsk Rule CLI"
+
+  it should "create rule, get rule, update rule and list rule" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val ruleName = "listRules"
+    val triggerName = "listRulesTrigger"
+    val actionName = "listRulesAction"
+
+    assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, name) =>
+      trigger.create(name)
+    }
+    assetHelper.withCleaner(wsk.action, actionName) { (action, name) =>
+      action.create(name, defaultAction)
+    }
+    assetHelper.withCleaner(wsk.rule, ruleName) { (rule, name) =>
+      rule.create(name, trigger = triggerName, action = actionName)
+    }
+
+    // finally, we perform the update, and expect success this time
+    wsk.rule.create(ruleName, trigger = triggerName, action = actionName, update = true)
+
+    val stdout = wsk.rule.get(ruleName).stdout
+    stdout should include(ruleName)
+    stdout should include(triggerName)
+    stdout should include(actionName)
+    stdout should include regex (""""version": "0.0.2"""")
+    wsk.rule.list().stdout should include(ruleName)
+  }
+
+  it should "create rule, get rule, ensure rule is enabled by default" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val ruleName = "enabledRule"
+      val triggerName = "enabledRuleTrigger"
+      val actionName = "enabledRuleAction"
+
+      assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, name) =>
+        trigger.create(name)
+      }
+      assetHelper.withCleaner(wsk.action, actionName) { (action, name) =>
+        action.create(name, defaultAction)
+      }
+      assetHelper.withCleaner(wsk.rule, ruleName) { (rule, name) =>
+        rule.create(name, trigger = triggerName, action = actionName)
+      }
+
+      val stdout = wsk.rule.get(ruleName).stdout
+      stdout should include regex (""""status":\s*"active"""")
+  }
+
+  it should "display a rule summary when --summary flag is used with 'wsk rule get'" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val ruleName = "mySummaryRule"
+      val triggerName = "summaryRuleTrigger"
+      val actionName = "summaryRuleAction"
+
+      assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, name) =>
+        trigger.create(name)
+      }
+      assetHelper.withCleaner(wsk.action, actionName) { (action, name) =>
+        action.create(name, defaultAction)
+      }
+      assetHelper.withCleaner(wsk.rule, ruleName, confirmDelete = false) { (rule, name) =>
+        rule.create(name, trigger = triggerName, action = actionName)
+      }
+
+      // Summary namespace should match one of the allowable namespaces (typically 'guest')
+      val ns = wsk.namespace.whois()
+      val stdout = wsk.rule.get(ruleName, summary = true).stdout
+
+      stdout should include regex (s"(?i)rule /$ns/$ruleName\\s*\\(status: active\\)")
+  }
+
+  it should "create a rule, and get its individual fields" in withAssetCleaner(wskprops) {
+    val ruleName = "ruleFields"
+    val triggerName = "ruleTriggerFields"
+    val actionName = "ruleActionFields"
+    val paramInput = Map("payload" -> "test".toJson)
+    val successMsg = s"ok: got rule $ruleName, displaying field"
+
+    (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, name) =>
+        trigger.create(name)
+      }
+      assetHelper.withCleaner(wsk.action, actionName) { (action, name) =>
+        action.create(name, defaultAction)
+      }
+      assetHelper.withCleaner(wsk.rule, ruleName) { (rule, name) =>
+        rule.create(name, trigger = triggerName, action = actionName)
+      }
+
+      val ns = wsk.namespace.whois()
+      wsk.rule
+        .get(ruleName, fieldFilter = Some("namespace"))
+        .stdout should include regex (s"""(?i)$successMsg namespace\n"$ns"""")
+      wsk.rule.get(ruleName, fieldFilter = Some("name")).stdout should include(s"""$successMsg name\n"$ruleName"""")
+      wsk.rule.get(ruleName, fieldFilter = Some("version")).stdout should include(s"""$successMsg version\n"0.0.1"\n""")
+      wsk.rule.get(ruleName, fieldFilter = Some("status")).stdout should include(s"""$successMsg status\n"active"""")
+      val trigger = wsk.rule.get(ruleName, fieldFilter = Some("trigger")).stdout
+      trigger should include regex (s"""$successMsg trigger\n""")
+      trigger should include(triggerName)
+      trigger should not include (actionName)
+      val action = wsk.rule.get(ruleName, fieldFilter = Some("action")).stdout
+      action should include regex (s"""$successMsg action\n""")
+      action should include(actionName)
+      action should not include (triggerName)
+  }
+
+  it should "reject creation of duplicate rules" in withAssetCleaner(wskprops) {
+    val ruleName = "dupeRule"
+    val triggerName = "triggerName"
+    val actionName = "actionName"
+
+    (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, name) =>
+        trigger.create(name)
+      }
+      assetHelper.withCleaner(wsk.action, actionName) { (action, name) =>
+        action.create(name, defaultAction)
+      }
+      assetHelper.withCleaner(wsk.rule, ruleName) { (rule, name) =>
+        rule.create(name, trigger = triggerName, action = actionName)
+      }
+
+      val stderr =
+        wsk.rule.create(ruleName, trigger = triggerName, action = actionName, expectedExitCode = CONFLICT).stderr
+      stderr should include regex (s"""Unable to create rule '$ruleName': resource already exists \\(code \\d+\\)""")
+  }
+
+  it should "reject delete of rule that does not exist" in {
+    val name = "nonexistentRule"
+    val stderr = wsk.rule.delete(name, expectedExitCode = NOT_FOUND).stderr
+    stderr should include regex (s"""Unable to delete rule '$name'. The requested resource does not exist. \\(code \\d+\\)""")
+  }
+
+  it should "reject enable of rule that does not exist" in {
+    val name = "nonexistentRule"
+    val stderr = wsk.rule.enable(name, expectedExitCode = NOT_FOUND).stderr
+    stderr should include regex (s"""Unable to enable rule '$name': The requested resource does not exist. \\(code \\d+\\)""")
+  }
+
+  it should "reject disable of rule that does not exist" in {
+    val name = "nonexistentRule"
+    val stderr = wsk.rule.disable(name, expectedExitCode = NOT_FOUND).stderr
+    stderr should include regex (s"""Unable to disable rule '$name': The requested resource does not exist. \\(code \\d+\\)""")
+  }
+
+  it should "reject status of rule that does not exist" in {
+    val name = "nonexistentRule"
+    val stderr = wsk.rule.state(name, expectedExitCode = NOT_FOUND).stderr
+    stderr should include regex (s"""Unable to get status of rule '$name': The requested resource does not exist. \\(code \\d+\\)""")
+  }
+
+  it should "reject get of rule that does not exist" in {
+    val name = "nonexistentRule"
+    val stderr = wsk.rule.get(name, expectedExitCode = NOT_FOUND).stderr
+    stderr should include regex (s"""Unable to get rule '$name': The requested resource does not exist. \\(code \\d+\\)""")
+  }
+
+  behavior of "Wsk Namespace CLI"
+
+  it should "return a list of exactly one namespace" in {
+    val lines = wsk.namespace.list().stdout.lines.toSeq
+    lines should have size 2
+    lines.head shouldBe "namespaces"
+    lines(1).trim should not be empty
+  }
+
+  it should "list entities in default namespace" in {
+    // use a fresh wsk props instance that is guaranteed to use
+    // the default namespace
+    wsk.namespace.get(expectedExitCode = SUCCESS_EXIT)(WskProps()).stdout should include("default")
+  }
+
+  it should "not list entities with an invalid namespace" in {
+    val namespace = "fakeNamespace"
+    val stderr = wsk.namespace.get(Some(s"/${namespace}"), expectedExitCode = FORBIDDEN).stderr
+
+    stderr should include(s"Unable to obtain the list of entities for namespace '${namespace}'")
+  }
+
+  behavior of "Wsk Activation CLI"
+
+  it should "create a trigger, and fire a trigger to get its individual fields from an activation" in withAssetCleaner(
+    wskprops) { (wp, assetHelper) =>
+    val name = "activationFields"
+
+    assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
+      trigger.create(name)
+    }
+
+    val ns = s""""${wsk.namespace.whois()}""""
+    val run = wsk.trigger.fire(name)
+    withActivation(wsk.activation, run) { activation =>
+      val successMsg = s"ok: got activation ${activation.activationId}, displaying field"
+      wsk.activation
+        .get(Some(activation.activationId), fieldFilter = Some("namespace"))
+        .stdout should include regex (s"""(?i)$successMsg namespace\n$ns""")
+      wsk.activation.get(Some(activation.activationId), fieldFilter = Some("name")).stdout should include(
+        s"""$successMsg name\n"$name"""")
+      wsk.activation.get(Some(activation.activationId), fieldFilter = Some("version")).stdout should include(
+        s"""$successMsg version\n"0.0.1"""")
+      wsk.activation.get(Some(activation.activationId), fieldFilter = Some("publish")).stdout should include(
+        s"""$successMsg publish\nfalse""")
+      wsk.activation
+        .get(Some(activation.activationId), fieldFilter = Some("subject"))
+        .stdout should include regex (s"""(?i)$successMsg subject\n""")
+      wsk.activation.get(Some(activation.activationId), fieldFilter = Some("activationid")).stdout should include(
+        s"""$successMsg activationid\n"${activation.activationId}""")
+      wsk.activation
+        .get(Some(activation.activationId), fieldFilter = Some("start"))
+        .stdout should include regex (s"""$successMsg start\n\\d""")
+      wsk.activation
+        .get(Some(activation.activationId), fieldFilter = Some("end"))
+        .stdout should include regex (s"""$successMsg end\n\\d""")
+      wsk.activation
+        .get(Some(activation.activationId), fieldFilter = Some("duration"))
+        .stdout should include regex (s"""$successMsg duration\n\\d""")
+      wsk.activation.get(Some(activation.activationId), fieldFilter = Some("annotations")).stdout should include(
+        s"""$successMsg annotations\n[]""")
+    }
+  }
+
+  it should "reject get of activation that does not exist" in {
+    val name = "0" * 32
+    val stderr = wsk.activation.get(Some(name), expectedExitCode = NOT_FOUND).stderr
+    stderr should include regex (s"""Unable to get activation '$name': The requested resource does not exist. \\(code \\d+\\)""")
+  }
+
+  it should "reject logs of activation that does not exist" in {
+    val name = "0" * 32
+    val stderr = wsk.activation.logs(Some(name), expectedExitCode = NOT_FOUND).stderr
+    stderr should include regex (s"""Unable to get logs for activation '$name': The requested resource does not exist. \\(code \\d+\\)""")
+  }
+
+  it should "reject result of activation that does not exist" in {
+    val name = "0" * 32
+    val stderr = wsk.activation.result(Some(name), expectedExitCode = NOT_FOUND).stderr
+    stderr should include regex (s"""Unable to get result for activation '$name': The requested resource does not exist. \\(code \\d+\\)""")
+  }
+
+  it should "reject activation request when using activation ID with --last Flag" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val auth: Seq[String] = Seq("--auth", wskprops.authKey)
+
+      val lastId = "dummyActivationId"
+      val tooManyArgsMsg = s"${lastId}. An activation ID is required."
+      val invalidField = s"Invalid field filter '${lastId}'."
+
+      val invalidCmd = Seq(
+        (Seq("activation", "get", s"$lastId", "publish", "--last"), tooManyArgsMsg),
+        (Seq("activation", "get", s"$lastId", "--last"), invalidField),
+        (Seq("activation", "logs", s"$lastId", "--last"), tooManyArgsMsg),
+        (Seq("activation", "result", s"$lastId", "--last"), tooManyArgsMsg))
+
+      invalidCmd foreach {
+        case (cmd, err) =>
+          val stderr = wsk.cli(cmd ++ wskprops.overrides ++ auth, expectedExitCode = ERROR_EXIT).stderr
+          stderr should include(err)
+      }
+  }
 }
diff --git a/tests/src/test/scala/system/basic/WskConsoleTests.scala b/tests/src/test/scala/system/basic/WskConsoleTests.scala
index 1848733..c2191fa 100644
--- a/tests/src/test/scala/system/basic/WskConsoleTests.scala
+++ b/tests/src/test/scala/system/basic/WskConsoleTests.scala
@@ -41,59 +41,53 @@ import spray.json.pimpAny
  * Tests of the text console
  */
 @RunWith(classOf[JUnitRunner])
-class WskConsoleTests
-    extends TestHelpers
-    with WskTestHelpers {
+class WskConsoleTests extends TestHelpers with WskTestHelpers {
 
-    implicit val wskprops = WskProps()
-    val wsk = new Wsk
-    val guestNamespace = wskprops.namespace
+  implicit val wskprops = WskProps()
+  val wsk = new Wsk
+  val guestNamespace = wskprops.namespace
 
-    behavior of "Wsk Activation Console"
+  behavior of "Wsk Activation Console"
 
-    it should "show an activation log message for hello world" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val packageName = "samples"
-            val actionName = "helloWorld"
-            val fullActionName = s"/$guestNamespace/$packageName/$actionName"
-            assetHelper.withCleaner(wsk.pkg, packageName) {
-                (pkg, _) => pkg.create(packageName, shared = Some(true))
-            }
+  it should "show an activation log message for hello world" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val packageName = "samples"
+    val actionName = "helloWorld"
+    val fullActionName = s"/$guestNamespace/$packageName/$actionName"
+    assetHelper.withCleaner(wsk.pkg, packageName) { (pkg, _) =>
+      pkg.create(packageName, shared = Some(true))
+    }
 
-            assetHelper.withCleaner(wsk.action, fullActionName) {
-                (action, _) => action.create(fullActionName, Some(TestCLIUtils.getTestActionFilename("hello.js")))
-            }
+    assetHelper.withCleaner(wsk.action, fullActionName) { (action, _) =>
+      action.create(fullActionName, Some(TestUtils.getTestActionFilename("hello.js")))
+    }
 
-            val duration = Some(30 seconds)
-            val payload = new String("from the console!".getBytes, "UTF-8")
-            val run = wsk.action.invoke(fullActionName, Map("payload" -> payload.toJson))
-            withActivation(wsk.activation, run, totalWait = duration.get) {
-                activation =>
-                    val console = wsk.activation.console(10 seconds, since = duration)
-                    println(console.stdout)
-                    console.stdout should include(payload)
-            }
+    val duration = Some(30 seconds)
+    val payload = new String("from the console!".getBytes, "UTF-8")
+    val run = wsk.action.invoke(fullActionName, Map("payload" -> payload.toJson))
+    withActivation(wsk.activation, run, totalWait = duration.get) { activation =>
+      val console = wsk.activation.console(10 seconds, since = duration)
+      println(console.stdout)
+      console.stdout should include(payload)
     }
+  }
 
-    it should "show repeated activations" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "countdown"
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("countdown.js")))
-            }
+  it should "show repeated activations" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "countdown"
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, Some(TestUtils.getTestActionFilename("countdown.js")))
+    }
 
-            val start = Instant.now(Clock.systemUTC())
-            val run = wsk.action.invoke(name, Map("n" -> 3.toJson))
-            withActivation(wsk.activation, run) {
-                activation =>
-                    val activations = wsk.activation.pollFor(N = 4, Some(name), since = Some(start), retries = 80).length
-                    withClue(s"expected activations:") {
-                        activations should be(4)
-                    }
-                    val duration = Duration(Instant.now(Clock.systemUTC()).toEpochMilli - start.toEpochMilli, MILLISECONDS)
-                    val console = wsk.activation.console(10 seconds, since = Some(duration))
-                    console.stdout should include("Happy New Year")
-            }
+    val start = Instant.now(Clock.systemUTC())
+    val run = wsk.action.invoke(name, Map("n" -> 3.toJson))
+    withActivation(wsk.activation, run) { activation =>
+      val activations = wsk.activation.pollFor(N = 4, Some(name), since = Some(start), retries = 80).length
+      withClue(s"expected activations:") {
+        activations should be(4)
+      }
+      val duration = Duration(Instant.now(Clock.systemUTC()).toEpochMilli - start.toEpochMilli, MILLISECONDS)
+      val console = wsk.activation.console(10 seconds, since = Some(duration))
+      console.stdout should include("Happy New Year")
     }
+  }
 
 }
diff --git a/tests/src/test/scala/system/basic/WskPackageTests.scala b/tests/src/test/scala/system/basic/WskPackageTests.scala
index 88618f0..1fae059 100644
--- a/tests/src/test/scala/system/basic/WskPackageTests.scala
+++ b/tests/src/test/scala/system/basic/WskPackageTests.scala
@@ -34,110 +34,103 @@ import common.TestHelpers
 import common.WskProps
 
 @RunWith(classOf[JUnitRunner])
-class WskPackageTests
-    extends TestHelpers
-    with WskTestHelpers {
+class WskPackageTests extends TestHelpers with WskTestHelpers {
 
-    implicit val wskprops = WskProps()
-    val wsk = new Wsk
-    val LOG_DELAY = 80 seconds
+  implicit val wskprops = WskProps()
+  val wsk = new Wsk
+  val LOG_DELAY = 80 seconds
 
-    behavior of "Wsk Package"
+  behavior of "Wsk Package"
 
-    it should "allow creation and deletion of a package" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "simplepackage"
-            assetHelper.withCleaner(wsk.pkg, name) {
-                (pkg, _) => pkg.create(name, Map())
-            }
+  it should "allow creation and deletion of a package" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "simplepackage"
+    assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
+      pkg.create(name, Map())
     }
+  }
 
-    val params1 = Map("p1" -> "v1".toJson, "p2" -> "".toJson)
-    val params2 = Map("p1" -> "v1".toJson, "p2" -> "v2".toJson, "p3" -> "v3".toJson)
+  val params1 = Map("p1" -> "v1".toJson, "p2" -> "".toJson)
+  val params2 = Map("p1" -> "v1".toJson, "p2" -> "v2".toJson, "p3" -> "v3".toJson)
 
-    it should "allow creation of a package with parameters" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "simplepackagewithparams"
-            assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
-                pkg.create(name, params1)
-            }
+  it should "allow creation of a package with parameters" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "simplepackagewithparams"
+    assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
+      pkg.create(name, params1)
     }
+  }
 
-    it should "allow updating a package" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "simplepackagetoupdate"
-            assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
-                pkg.create(name, params1)
-                pkg.create(name, params2, update = true)
-            }
+  it should "allow updating a package" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "simplepackagetoupdate"
+    assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
+      pkg.create(name, params1)
+      pkg.create(name, params2, update = true)
     }
+  }
 
-    it should "allow binding of a package" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "simplepackagetobind"
-            val bindName = "simplebind"
-            assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
-                pkg.create(name, params1)
-            }
-            assetHelper.withCleaner(wsk.pkg, bindName) { (pkg, _) =>
-                pkg.bind(name, bindName, params2)
-            }
+  it should "allow binding of a package" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "simplepackagetobind"
+    val bindName = "simplebind"
+    assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
+      pkg.create(name, params1)
     }
+    assetHelper.withCleaner(wsk.pkg, bindName) { (pkg, _) =>
+      pkg.bind(name, bindName, params2)
+    }
+  }
 
-    it should "perform package binds so parameters are inherited" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val packageName = "package1"
-            val bindName = "package2"
-            val actionName = "print"
-            val packageActionName = packageName + "/" + actionName
-            val bindActionName = bindName + "/" + actionName
-            val packageParams = Map("key1a" -> "value1a".toJson, "key1b" -> "value1b".toJson)
-            val bindParams = Map("key2a" -> "value2a".toJson, "key1b" -> "value2b".toJson)
-            val actionParams = Map("key0" -> "value0".toJson)
-            val file = TestCLIUtils.getTestActionFilename("printParams.js")
-            assetHelper.withCleaner(wsk.pkg, packageName) { (pkg, _) =>
-                pkg.create(packageName, packageParams)
-            }
-            assetHelper.withCleaner(wsk.action, packageActionName) { (action, _) =>
-                action.create(packageActionName, Some(file), parameters = actionParams)
-            }
-            assetHelper.withCleaner(wsk.pkg, bindName) { (pkg, _) =>
-                pkg.bind(packageName, bindName, bindParams)
-            }
+  it should "perform package binds so parameters are inherited" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val packageName = "package1"
+    val bindName = "package2"
+    val actionName = "print"
+    val packageActionName = packageName + "/" + actionName
+    val bindActionName = bindName + "/" + actionName
+    val packageParams = Map("key1a" -> "value1a".toJson, "key1b" -> "value1b".toJson)
+    val bindParams = Map("key2a" -> "value2a".toJson, "key1b" -> "value2b".toJson)
+    val actionParams = Map("key0" -> "value0".toJson)
+    val file = TestUtils.getTestActionFilename("printParams.js")
+    assetHelper.withCleaner(wsk.pkg, packageName) { (pkg, _) =>
+      pkg.create(packageName, packageParams)
+    }
+    assetHelper.withCleaner(wsk.action, packageActionName) { (action, _) =>
+      action.create(packageActionName, Some(file), parameters = actionParams)
+    }
+    assetHelper.withCleaner(wsk.pkg, bindName) { (pkg, _) =>
+      pkg.bind(packageName, bindName, bindParams)
+    }
 
-            // Check that the description of packages and actions includes all the inherited parameters.
-            val packageDescription = wsk.pkg.get(packageName).stdout
-            val bindDescription = wsk.pkg.get(bindName).stdout
-            val packageActionDescription = wsk.action.get(packageActionName).stdout
-            val bindActionDescription = wsk.action.get(bindActionName).stdout
-            checkForParameters(packageDescription, packageParams)
-            checkForParameters(bindDescription, packageParams, bindParams)
-            checkForParameters(packageActionDescription, packageParams, actionParams)
-            checkForParameters(bindActionDescription, packageParams, bindParams, actionParams)
+    // Check that the description of packages and actions includes all the inherited parameters.
+    val packageDescription = wsk.pkg.get(packageName).stdout
+    val bindDescription = wsk.pkg.get(bindName).stdout
+    val packageActionDescription = wsk.action.get(packageActionName).stdout
+    val bindActionDescription = wsk.action.get(bindActionName).stdout
+    checkForParameters(packageDescription, packageParams)
+    checkForParameters(bindDescription, packageParams, bindParams)
+    checkForParameters(packageActionDescription, packageParams, actionParams)
+    checkForParameters(bindActionDescription, packageParams, bindParams, actionParams)
 
-            // Check that inherited parameters are passed to the action.
-            val now = new Date().toString()
-            val run = wsk.action.invoke(bindActionName, Map("payload" -> now.toJson))
-            withActivation(wsk.activation, run, totalWait = LOG_DELAY) {
-                _.logs.get.mkString(" ") should include regex (
-                    String.format(".*key0: value0.*key1a: value1a.*key1b: value2b.*key2a: value2a.*payload: %s", now))
-            }
+    // Check that inherited parameters are passed to the action.
+    val now = new Date().toString()
+    val run = wsk.action.invoke(bindActionName, Map("payload" -> now.toJson))
+    withActivation(wsk.activation, run, totalWait = LOG_DELAY) {
+      _.logs.get.mkString(" ") should include regex (String
+        .format(".*key0: value0.*key1a: value1a.*key1b: value2b.*key2a: value2a.*payload: %s", now))
     }
+  }
 
-    /**
-     * Check that a description of an item includes the specified parameters.
-     * Parameters keys in later parameter maps override earlier ones.
-     */
-    def checkForParameters(itemDescription: String, paramSets: Map[String, JsValue]*) {
-        // Merge and the parameters handling overrides.
-        val merged = HashMap.empty[String, JsValue]
-        paramSets.foreach { merged ++= _ }
-        val flatDescription = itemDescription.replace("\n", "").replace("\r", "")
-        merged.foreach {
-            case (key: String, value: JsValue) =>
-                val toFind = s""""key": "${key}",.*"value": ${value.toString}"""
-                flatDescription should include regex toFind
-        }
+  /**
+   * Check that a description of an item includes the specified parameters.
+   * Parameters keys in later parameter maps override earlier ones.
+   */
+  def checkForParameters(itemDescription: String, paramSets: Map[String, JsValue]*) {
+    // Merge and the parameters handling overrides.
+    val merged = HashMap.empty[String, JsValue]
+    paramSets.foreach { merged ++= _ }
+    val flatDescription = itemDescription.replace("\n", "").replace("\r", "")
+    merged.foreach {
+      case (key: String, value: JsValue) =>
+        val toFind = s""""key": "${key}",.*"value": ${value.toString}"""
+        flatDescription should include regex toFind
     }
+  }
 
 }
diff --git a/tests/src/test/scala/system/basic/WskRuleTests.scala b/tests/src/test/scala/system/basic/WskRuleTests.scala
index ae8768d..adc95a7 100644
--- a/tests/src/test/scala/system/basic/WskRuleTests.scala
+++ b/tests/src/test/scala/system/basic/WskRuleTests.scala
@@ -29,364 +29,394 @@ import spray.json.DefaultJsonProtocol._
 import java.time.Instant
 
 @RunWith(classOf[JUnitRunner])
-class WskRuleTests
-    extends TestHelpers
-    with WskTestHelpers {
-
-    implicit val wskprops = WskProps()
-    val wsk = new Wsk
-    val defaultAction = TestCLIUtils.getTestActionFilename("wc.js")
-    val secondAction = TestCLIUtils.getTestActionFilename("hello.js")
-    val testString = "this is a test"
-    val testResult = JsObject("count" -> testString.split(" ").length.toJson)
-
-    /**
-     * Invoker clock skew can sometimes make it appear as if an action was invoked
-     * _before_ the trigger was fired. The "fudge factor" below allows the test to look
-     * for action activations that occur starting at most this amount of time before
-     * the trigger was fired.
-     */
-    val activationTimeSkewFactorMs = 500
-
-    /**
-     * Sets up trigger -> rule -> action triplets. Deduplicates triggers and rules
-     * and links it all up.
-     *
-     * @param rules Tuple3s containing
-     *   (rule, trigger, (action name for created action, action name for the rule binding, actionFile))
-     *   where the action name for the created action is allowed to differ from that used by the rule binding
-     *   for cases that reference actions in a package binding.
-     */
-    def ruleSetup(rules: Seq[(String, String, (String, String, String))], assetHelper: AssetCleaner) = {
-        val triggers = rules.map(_._2).distinct
-        val actions = rules.map(_._3).distinct
-
-        triggers.foreach { trigger =>
-            assetHelper.withCleaner(wsk.trigger, trigger) {
-                (trigger, name) => trigger.create(name)
-            }
-        }
+class WskRuleTests extends TestHelpers with WskTestHelpers {
+
+  implicit val wskprops = WskProps()
+  val wsk = new Wsk
+  val defaultAction = TestCLIUtils.getTestActionFilename("wc.js")
+  val secondAction = TestCLIUtils.getTestActionFilename("hello.js")
+  val testString = "this is a test"
+  val testResult = JsObject("count" -> testString.split(" ").length.toJson)
+
+  /**
+   * Invoker clock skew can sometimes make it appear as if an action was invoked
+   * _before_ the trigger was fired. The "fudge factor" below allows the test to look
+   * for action activations that occur starting at most this amount of time before
+   * the trigger was fired.
+   */
+  val activationTimeSkewFactorMs = 500
+
+  /**
+   * Sets up trigger -> rule -> action triplets. Deduplicates triggers and rules
+   * and links it all up.
+   *
+   * @param rules Tuple3s containing
+   *   (rule, trigger, (action name for created action, action name for the rule binding, actionFile))
+   *   where the action name for the created action is allowed to differ from that used by the rule binding
+   *   for cases that reference actions in a package binding.
+   */
+  def ruleSetup(rules: Seq[(String, String, (String, String, String))], assetHelper: AssetCleaner) = {
+    val triggers = rules.map(_._2).distinct
+    val actions = rules.map(_._3).distinct
+
+    triggers.foreach { trigger =>
+      assetHelper.withCleaner(wsk.trigger, trigger) { (trigger, name) =>
+        trigger.create(name)
+      }
+    }
 
-        actions.foreach {
-            case (actionName, _, file) =>
-                assetHelper.withCleaner(wsk.action, actionName) {
-                    (action, name) => action.create(name, Some(file))
-                }
+    actions.foreach {
+      case (actionName, _, file) =>
+        assetHelper.withCleaner(wsk.action, actionName) { (action, name) =>
+          action.create(name, Some(file))
         }
+    }
 
-        rules.foreach {
-            case (ruleName, triggerName, action) =>
-                assetHelper.withCleaner(wsk.rule, ruleName) {
-                    (rule, name) => rule.create(name, triggerName, action._2)
-                }
+    rules.foreach {
+      case (ruleName, triggerName, action) =>
+        assetHelper.withCleaner(wsk.rule, ruleName) { (rule, name) =>
+          rule.create(name, triggerName, action._2)
         }
     }
+  }
+
+  /**
+   * Append the current timestamp in ms
+   */
+  def withTimestamp(text: String) = s"${text}-${System.currentTimeMillis}"
+
+  behavior of "Whisk rules"
+
+  it should "invoke the action attached on trigger fire, creating an activation for each entity including the cause" in withAssetCleaner(
+    wskprops) { (wp, assetHelper) =>
+    val ruleName = withTimestamp("r1to1")
+    val triggerName = withTimestamp("t1to1")
+    val actionName = withTimestamp("a1 to 1") // spaces in name intended for greater test coverage
+
+    ruleSetup(Seq((ruleName, triggerName, (actionName, actionName, defaultAction))), assetHelper)
+
+    val run = wsk.trigger.fire(triggerName, Map("payload" -> testString.toJson))
+
+    withActivation(wsk.activation, run) { triggerActivation =>
+      triggerActivation.cause shouldBe None
+
+      withActivationsFromEntity(
+        wsk.activation,
+        ruleName,
+        since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
+        _.head.cause shouldBe Some(triggerActivation.activationId)
+      }
+
+      withActivationsFromEntity(
+        wsk.activation,
+        actionName,
+        since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) { activationList =>
+        activationList.head.response.result shouldBe Some(testResult)
+        activationList.head.cause shouldBe None
+      }
+    }
+  }
+
+  it should "invoke the action from a package attached on trigger fire, creating an activation for each entity including the cause" in withAssetCleaner(
+    wskprops) { (wp, assetHelper) =>
+    val ruleName = withTimestamp("pr1to1")
+    val triggerName = withTimestamp("pt1to1")
+    val pkgName = withTimestamp("rule pkg") // spaces in name intended to test uri path encoding
+    val actionName = withTimestamp("a1 to 1")
+    val pkgActionName = s"$pkgName/$actionName"
+
+    assetHelper.withCleaner(wsk.pkg, pkgName) { (pkg, name) =>
+      pkg.create(name)
+    }
 
-    /**
-     * Append the current timestamp in ms
-     */
-    def withTimestamp(text: String) = s"${text}-${System.currentTimeMillis}"
-
-    behavior of "Whisk rules"
-
-    it should "invoke the action attached on trigger fire, creating an activation for each entity including the cause" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val ruleName = withTimestamp("r1to1")
-            val triggerName = withTimestamp("t1to1")
-            val actionName = withTimestamp("a1 to 1") // spaces in name intended for greater test coverage
-
-            ruleSetup(Seq(
-                (ruleName, triggerName, (actionName, actionName, defaultAction))),
-                assetHelper)
+    ruleSetup(Seq((ruleName, triggerName, (pkgActionName, pkgActionName, defaultAction))), assetHelper)
 
-            val run = wsk.trigger.fire(triggerName, Map("payload" -> testString.toJson))
+    val now = Instant.now
+    val run = wsk.trigger.fire(triggerName, Map("payload" -> testString.toJson))
 
-            withActivation(wsk.activation, run) {
-                triggerActivation =>
-                    triggerActivation.cause shouldBe None
+    withActivation(wsk.activation, run) { triggerActivation =>
+      triggerActivation.cause shouldBe None
 
-                    withActivationsFromEntity(wsk.activation, ruleName, since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
-                        _.head.cause shouldBe Some(triggerActivation.activationId)
-                    }
+      withActivationsFromEntity(
+        wsk.activation,
+        ruleName,
+        since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
+        _.head.cause shouldBe Some(triggerActivation.activationId)
+      }
 
-                    withActivationsFromEntity(wsk.activation, actionName, since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) { activationList =>
-                        activationList.head.response.result shouldBe Some(testResult)
-                        activationList.head.cause shouldBe None
-                    }
-            }
+      withActivationsFromEntity(
+        wsk.activation,
+        actionName,
+        since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
+        _.head.response.result shouldBe Some(testResult)
+      }
     }
-
-    it should "invoke the action from a package attached on trigger fire, creating an activation for each entity including the cause" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val ruleName = withTimestamp("pr1to1")
-            val triggerName = withTimestamp("pt1to1")
-            val pkgName = withTimestamp("rule pkg") // spaces in name intended to test uri path encoding
-            val actionName = withTimestamp("a1 to 1")
-            val pkgActionName = s"$pkgName/$actionName"
-
-            assetHelper.withCleaner(wsk.pkg, pkgName) {
-                (pkg, name) => pkg.create(name)
-            }
-
-            ruleSetup(Seq(
-                (ruleName, triggerName, (pkgActionName, pkgActionName, defaultAction))),
-                assetHelper)
-
-            val now = Instant.now
-            val run = wsk.trigger.fire(triggerName, Map("payload" -> testString.toJson))
-
-            withActivation(wsk.activation, run) {
-                triggerActivation =>
-                    triggerActivation.cause shouldBe None
-
-                    withActivationsFromEntity(wsk.activation, ruleName, since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
-                        _.head.cause shouldBe Some(triggerActivation.activationId)
-                    }
-
-                    withActivationsFromEntity(wsk.activation, actionName, since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
-                        _.head.response.result shouldBe Some(testResult)
-                    }
-            }
-    }
-
-    it should "invoke the action from a package binding attached on trigger fire, creating an activation for each entity including the cause" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val ruleName = withTimestamp("pr1to1")
-            val triggerName = withTimestamp("pt1to1")
-            val pkgName = withTimestamp("rule pkg") // spaces in name intended to test uri path encoding
-            val pkgBindingName = withTimestamp("rule pkg binding")
-            val actionName = withTimestamp("a1 to 1")
-            val pkgActionName = s"$pkgName/$actionName"
-
-            assetHelper.withCleaner(wsk.pkg, pkgName) {
-                (pkg, name) => pkg.create(name)
-            }
-
-            assetHelper.withCleaner(wsk.pkg, pkgBindingName) {
-                (pkg, name) => pkg.bind(pkgName, pkgBindingName)
-            }
-
-            ruleSetup(Seq(
-                (ruleName, triggerName, (pkgActionName, s"$pkgBindingName/$actionName", defaultAction))),
-                assetHelper)
-
-            val run = wsk.trigger.fire(triggerName, Map("payload" -> testString.toJson))
-
-            withActivation(wsk.activation, run) {
-                triggerActivation =>
-                    triggerActivation.cause shouldBe None
-
-                    withActivationsFromEntity(wsk.activation, ruleName, since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
-                        _.head.cause shouldBe Some(triggerActivation.activationId)
-                    }
-
-                    withActivationsFromEntity(wsk.activation, actionName, since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
-                        _.head.response.result shouldBe Some(testResult)
-                    }
-            }
+  }
+
+  it should "invoke the action from a package binding attached on trigger fire, creating an activation for each entity including the cause" in withAssetCleaner(
+    wskprops) { (wp, assetHelper) =>
+    val ruleName = withTimestamp("pr1to1")
+    val triggerName = withTimestamp("pt1to1")
+    val pkgName = withTimestamp("rule pkg") // spaces in name intended to test uri path encoding
+    val pkgBindingName = withTimestamp("rule pkg binding")
+    val actionName = withTimestamp("a1 to 1")
+    val pkgActionName = s"$pkgName/$actionName"
+
+    assetHelper.withCleaner(wsk.pkg, pkgName) { (pkg, name) =>
+      pkg.create(name)
     }
 
-    it should "not activate an action if the rule is deleted when the trigger is fired" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val ruleName = withTimestamp("ruleDelete")
-            val triggerName = withTimestamp("ruleDeleteTrigger")
-            val actionName = withTimestamp("ruleDeleteAction")
-
-            assetHelper.withCleaner(wsk.trigger, triggerName) {
-                (trigger, name) => trigger.create(name)
-            }
-            assetHelper.withCleaner(wsk.action, actionName) {
-                (action, name) => action.create(name, Some(defaultAction))
-            }
-            assetHelper.withCleaner(wsk.rule, ruleName, false) {
-                (rule, name) => rule.create(name, triggerName, actionName)
-            }
-
-            val first = wsk.trigger.fire(triggerName, Map("payload" -> "bogus".toJson))
-            wsk.rule.delete(ruleName)
-            wsk.trigger.fire(triggerName, Map("payload" -> "bogus2".toJson))
-
-            withActivation(wsk.activation, first) {
-                activation =>
-                    // tries to find 2 activations for the action, should only find 1
-                    val activations = wsk.activation.pollFor(2, Some(actionName), since = Some(activation.start.minusMillis(activationTimeSkewFactorMs)), retries = 30)
-
-                    activations.length shouldBe 1
-            }
+    assetHelper.withCleaner(wsk.pkg, pkgBindingName) { (pkg, name) =>
+      pkg.bind(pkgName, pkgBindingName)
     }
 
-    it should "enable and disable a rule and check action is activated only when rule is enabled" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val ruleName = withTimestamp("ruleDisable")
-            val triggerName = withTimestamp("ruleDisableTrigger")
-            val actionName = withTimestamp("ruleDisableAction")
-
-            ruleSetup(Seq(
-                (ruleName, triggerName, (actionName, actionName, defaultAction))),
-                assetHelper)
-
-            val first = wsk.trigger.fire(triggerName, Map("payload" -> testString.toJson))
-            wsk.rule.disable(ruleName)
-            wsk.trigger.fire(triggerName, Map("payload" -> s"$testString with added words".toJson))
-            wsk.rule.enable(ruleName)
-            wsk.trigger.fire(triggerName, Map("payload" -> testString.toJson))
-
-            withActivation(wsk.activation, first) {
-                triggerActivation =>
-                    withActivationsFromEntity(wsk.activation, actionName, N = 2, since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
-                        activations =>
-                            val results = activations.map(_.response.result)
-                            results should contain theSameElementsAs Seq(Some(testResult), Some(testResult))
-                    }
-            }
-    }
+    ruleSetup(Seq((ruleName, triggerName, (pkgActionName, s"$pkgBindingName/$actionName", defaultAction))), assetHelper)
 
-    it should "be able to recreate a rule with the same name and match it successfully" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val ruleName = withTimestamp("ruleRecreate")
-            val triggerName1 = withTimestamp("ruleRecreateTrigger1")
-            val triggerName2 = withTimestamp("ruleRecreateTrigger2")
-            val actionName = withTimestamp("ruleRecreateAction")
-
-            assetHelper.withCleaner(wsk.trigger, triggerName1) {
-                (trigger, name) => trigger.create(name)
-            }
-            assetHelper.withCleaner(wsk.action, actionName) {
-                (action, name) => action.create(name, Some(defaultAction))
-            }
-            assetHelper.withCleaner(wsk.rule, ruleName, false) {
-                (rule, name) => rule.create(name, triggerName1, actionName)
-            }
-
-            wsk.rule.delete(ruleName)
-
-            assetHelper.withCleaner(wsk.trigger, triggerName2) {
-                (trigger, name) => trigger.create(name)
-            }
-            assetHelper.withCleaner(wsk.rule, ruleName) {
-                (rule, name) => rule.create(name, triggerName2, actionName)
-            }
-
-            val first = wsk.trigger.fire(triggerName2, Map("payload" -> testString.toJson))
-            withActivation(wsk.activation, first) {
-                triggerActivation =>
-                    withActivationsFromEntity(wsk.activation, actionName, since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
-                        _.head.response.result shouldBe Some(testResult)
-                    }
-            }
-    }
+    val run = wsk.trigger.fire(triggerName, Map("payload" -> testString.toJson))
 
-    it should "connect two triggers via rules to one action and activate it accordingly" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val triggerName1 = withTimestamp("t2to1a")
-            val triggerName2 = withTimestamp("t2to1b")
-            val actionName = withTimestamp("a2to1")
-
-            ruleSetup(Seq(
-                ("r2to1a", triggerName1, (actionName, actionName, defaultAction)),
-                ("r2to1b", triggerName2, (actionName, actionName, defaultAction))),
-                assetHelper)
-
-            val testPayloads = Seq("got three words", "got four words, period")
-
-            val run = wsk.trigger.fire(triggerName1, Map("payload" -> testPayloads(0).toJson))
-            wsk.trigger.fire(triggerName2, Map("payload" -> testPayloads(1).toJson))
-
-            withActivation(wsk.activation, run) {
-                triggerActivation =>
-                    withActivationsFromEntity(wsk.activation, actionName, N = 2, since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
-                        activations =>
-                            val results = activations.map(_.response.result)
-                            val expectedResults = testPayloads.map { payload =>
-                                Some(JsObject("count" -> payload.split(" ").length.toJson))
-                            }
-
-                            results should contain theSameElementsAs expectedResults
-                    }
-            }
-    }
+    withActivation(wsk.activation, run) { triggerActivation =>
+      triggerActivation.cause shouldBe None
 
-    it should "connect one trigger to two different actions, invoking them both eventually" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val triggerName = withTimestamp("t1to2")
-            val actionName1 = withTimestamp("a1to2a")
-            val actionName2 = withTimestamp("a1to2b")
-
-            ruleSetup(Seq(
-                ("r1to2a", triggerName, (actionName1, actionName1, defaultAction)),
-                ("r1to2b", triggerName, (actionName2, actionName2, secondAction))),
-                assetHelper)
-
-            val run = wsk.trigger.fire(triggerName, Map("payload" -> testString.toJson))
-
-            withActivation(wsk.activation, run) {
-                triggerActivation =>
-                    withActivationsFromEntity(wsk.activation, actionName1, since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
-                        _.head.response.result shouldBe Some(testResult)
-                    }
-                    withActivationsFromEntity(wsk.activation, actionName2, since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
-                        _.head.logs.get.mkString(" ") should include(s"hello, $testString")
-                    }
-            }
-    }
+      withActivationsFromEntity(
+        wsk.activation,
+        ruleName,
+        since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
+        _.head.cause shouldBe Some(triggerActivation.activationId)
+      }
 
-    it should "connect two triggers to two different actions, invoking them both eventually" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val triggerName1 = withTimestamp("t1to1a")
-            val triggerName2 = withTimestamp("t1to1b")
-            val actionName1 = withTimestamp("a1to1a")
-            val actionName2 = withTimestamp("a1to1b")
-
-            ruleSetup(Seq(
-                ("r2to2a", triggerName1, (actionName1, actionName1, defaultAction)),
-                ("r2to2b", triggerName1, (actionName2, actionName2, secondAction)),
-                ("r2to2c", triggerName2, (actionName1, actionName1, defaultAction)),
-                ("r2to2d", triggerName2, (actionName2, actionName2, secondAction))),
-                assetHelper)
-
-            val testPayloads = Seq("got three words", "got four words, period")
-            val run = wsk.trigger.fire(triggerName1, Map("payload" -> testPayloads(0).toJson))
-            wsk.trigger.fire(triggerName2, Map("payload" -> testPayloads(1).toJson))
-
-            withActivation(wsk.activation, run) {
-                triggerActivation =>
-                    withActivationsFromEntity(wsk.activation, actionName1, N = 2, since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
-                        activations =>
-                            val results = activations.map(_.response.result)
-                            val expectedResults = testPayloads.map { payload =>
-                                Some(JsObject("count" -> payload.split(" ").length.toJson))
-                            }
-
-                            results should contain theSameElementsAs expectedResults
-                    }
-                    withActivationsFromEntity(wsk.activation, actionName2, N = 2, since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
-                        activations =>
-                            // drops the leftmost 39 characters (timestamp + streamname)
-                            val logs = activations.map(_.logs.get.map(_.drop(39))).flatten
-                            val expectedLogs = testPayloads.map { payload => s"hello, $payload!" }
-
-                            logs should contain theSameElementsAs expectedLogs
-                    }
-            }
+      withActivationsFromEntity(
+        wsk.activation,
+        actionName,
+        since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
+        _.head.response.result shouldBe Some(testResult)
+      }
     }
-
-    it should "disable a rule and check its status is displayed when listed" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val ruleName = withTimestamp("ruleDisable")
-            val ruleName2 = withTimestamp("ruleEnable")
-            val triggerName = withTimestamp("ruleDisableTrigger")
-            val actionName = withTimestamp("ruleDisableAction")
-
-            ruleSetup(Seq(
-                (ruleName, triggerName, (actionName, actionName, defaultAction)),
-                (ruleName2, triggerName, (actionName, actionName, defaultAction))),
-                assetHelper)
-
-            wsk.rule.disable(ruleName)
-            val listOutput = wsk.rule.list().stdout.lines
-            listOutput.find(_.contains(ruleName2)).get should (include(ruleName2) and include("active"))
-            listOutput.find(_.contains(ruleName)).get should (include(ruleName) and include("inactive"))
-            wsk.rule.list().stdout should not include ("Unknown")
+  }
+
+  it should "not activate an action if the rule is deleted when the trigger is fired" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val ruleName = withTimestamp("ruleDelete")
+      val triggerName = withTimestamp("ruleDeleteTrigger")
+      val actionName = withTimestamp("ruleDeleteAction")
+
+      assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, name) =>
+        trigger.create(name)
+      }
+      assetHelper.withCleaner(wsk.action, actionName) { (action, name) =>
+        action.create(name, Some(defaultAction))
+      }
+      assetHelper.withCleaner(wsk.rule, ruleName, false) { (rule, name) =>
+        rule.create(name, triggerName, actionName)
+      }
+
+      val first = wsk.trigger.fire(triggerName, Map("payload" -> "bogus".toJson))
+      wsk.rule.delete(ruleName)
+      wsk.trigger.fire(triggerName, Map("payload" -> "bogus2".toJson))
+
+      withActivation(wsk.activation, first) { activation =>
+        // tries to find 2 activations for the action, should only find 1
+        val activations = wsk.activation.pollFor(
+          2,
+          Some(actionName),
+          since = Some(activation.start.minusMillis(activationTimeSkewFactorMs)),
+          retries = 30)
+
+        activations.length shouldBe 1
+      }
+  }
+
+  it should "enable and disable a rule and check action is activated only when rule is enabled" in withAssetCleaner(
+    wskprops) { (wp, assetHelper) =>
+    val ruleName = withTimestamp("ruleDisable")
+    val triggerName = withTimestamp("ruleDisableTrigger")
+    val actionName = withTimestamp("ruleDisableAction")
+
+    ruleSetup(Seq((ruleName, triggerName, (actionName, actionName, defaultAction))), assetHelper)
+
+    val first = wsk.trigger.fire(triggerName, Map("payload" -> testString.toJson))
+    wsk.rule.disable(ruleName)
+    wsk.trigger.fire(triggerName, Map("payload" -> s"$testString with added words".toJson))
+    wsk.rule.enable(ruleName)
+    wsk.trigger.fire(triggerName, Map("payload" -> testString.toJson))
+
+    withActivation(wsk.activation, first) { triggerActivation =>
+      withActivationsFromEntity(
+        wsk.activation,
+        actionName,
+        N = 2,
+        since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) { activations =>
+        val results = activations.map(_.response.result)
+        results should contain theSameElementsAs Seq(Some(testResult), Some(testResult))
+      }
     }
+  }
+
+  it should "be able to recreate a rule with the same name and match it successfully" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val ruleName = withTimestamp("ruleRecreate")
+      val triggerName1 = withTimestamp("ruleRecreateTrigger1")
+      val triggerName2 = withTimestamp("ruleRecreateTrigger2")
+      val actionName = withTimestamp("ruleRecreateAction")
+
+      assetHelper.withCleaner(wsk.trigger, triggerName1) { (trigger, name) =>
+        trigger.create(name)
+      }
+      assetHelper.withCleaner(wsk.action, actionName) { (action, name) =>
+        action.create(name, Some(defaultAction))
+      }
+      assetHelper.withCleaner(wsk.rule, ruleName, false) { (rule, name) =>
+        rule.create(name, triggerName1, actionName)
+      }
+
+      wsk.rule.delete(ruleName)
+
+      assetHelper.withCleaner(wsk.trigger, triggerName2) { (trigger, name) =>
+        trigger.create(name)
+      }
+      assetHelper.withCleaner(wsk.rule, ruleName) { (rule, name) =>
+        rule.create(name, triggerName2, actionName)
+      }
+
+      val first = wsk.trigger.fire(triggerName2, Map("payload" -> testString.toJson))
+      withActivation(wsk.activation, first) { triggerActivation =>
+        withActivationsFromEntity(
+          wsk.activation,
+          actionName,
+          since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
+          _.head.response.result shouldBe Some(testResult)
+        }
+      }
+  }
+
+  it should "connect two triggers via rules to one action and activate it accordingly" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val triggerName1 = withTimestamp("t2to1a")
+      val triggerName2 = withTimestamp("t2to1b")
+      val actionName = withTimestamp("a2to1")
+
+      ruleSetup(
+        Seq(
+          ("r2to1a", triggerName1, (actionName, actionName, defaultAction)),
+          ("r2to1b", triggerName2, (actionName, actionName, defaultAction))),
+        assetHelper)
+
+      val testPayloads = Seq("got three words", "got four words, period")
+
+      val run = wsk.trigger.fire(triggerName1, Map("payload" -> testPayloads(0).toJson))
+      wsk.trigger.fire(triggerName2, Map("payload" -> testPayloads(1).toJson))
+
+      withActivation(wsk.activation, run) { triggerActivation =>
+        withActivationsFromEntity(
+          wsk.activation,
+          actionName,
+          N = 2,
+          since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) { activations =>
+          val results = activations.map(_.response.result)
+          val expectedResults = testPayloads.map { payload =>
+            Some(JsObject("count" -> payload.split(" ").length.toJson))
+          }
+
+          results should contain theSameElementsAs expectedResults
+        }
+      }
+  }
+
+  it should "connect one trigger to two different actions, invoking them both eventually" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val triggerName = withTimestamp("t1to2")
+      val actionName1 = withTimestamp("a1to2a")
+      val actionName2 = withTimestamp("a1to2b")
+
+      ruleSetup(
+        Seq(
+          ("r1to2a", triggerName, (actionName1, actionName1, defaultAction)),
+          ("r1to2b", triggerName, (actionName2, actionName2, secondAction))),
+        assetHelper)
+
+      val run = wsk.trigger.fire(triggerName, Map("payload" -> testString.toJson))
+
+      withActivation(wsk.activation, run) { triggerActivation =>
+        withActivationsFromEntity(
+          wsk.activation,
+          actionName1,
+          since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
+          _.head.response.result shouldBe Some(testResult)
+        }
+        withActivationsFromEntity(
+          wsk.activation,
+          actionName2,
+          since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) {
+          _.head.logs.get.mkString(" ") should include(s"hello, $testString")
+        }
+      }
+  }
+
+  it should "connect two triggers to two different actions, invoking them both eventually" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val triggerName1 = withTimestamp("t1to1a")
+      val triggerName2 = withTimestamp("t1to1b")
+      val actionName1 = withTimestamp("a1to1a")
+      val actionName2 = withTimestamp("a1to1b")
+
+      ruleSetup(
+        Seq(
+          ("r2to2a", triggerName1, (actionName1, actionName1, defaultAction)),
+          ("r2to2b", triggerName1, (actionName2, actionName2, secondAction)),
+          ("r2to2c", triggerName2, (actionName1, actionName1, defaultAction)),
+          ("r2to2d", triggerName2, (actionName2, actionName2, secondAction))),
+        assetHelper)
+
+      val testPayloads = Seq("got three words", "got four words, period")
+      val run = wsk.trigger.fire(triggerName1, Map("payload" -> testPayloads(0).toJson))
+      wsk.trigger.fire(triggerName2, Map("payload" -> testPayloads(1).toJson))
+
+      withActivation(wsk.activation, run) { triggerActivation =>
+        withActivationsFromEntity(
+          wsk.activation,
+          actionName1,
+          N = 2,
+          since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) { activations =>
+          val results = activations.map(_.response.result)
+          val expectedResults = testPayloads.map { payload =>
+            Some(JsObject("count" -> payload.split(" ").length.toJson))
+          }
+
+          results should contain theSameElementsAs expectedResults
+        }
+        withActivationsFromEntity(
+          wsk.activation,
+          actionName2,
+          N = 2,
+          since = Some(triggerActivation.start.minusMillis(activationTimeSkewFactorMs))) { activations =>
+          // drops the leftmost 39 characters (timestamp + streamname)
+          val logs = activations.map(_.logs.get.map(_.drop(39))).flatten
+          val expectedLogs = testPayloads.map { payload =>
+            s"hello, $payload!"
+          }
+
+          logs should contain theSameElementsAs expectedLogs
+        }
+      }
+  }
+
+  it should "disable a rule and check its status is displayed when listed" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val ruleName = withTimestamp("ruleDisable")
+      val ruleName2 = withTimestamp("ruleEnable")
+      val triggerName = withTimestamp("ruleDisableTrigger")
+      val actionName = withTimestamp("ruleDisableAction")
+
+      ruleSetup(
+        Seq(
+          (ruleName, triggerName, (actionName, actionName, defaultAction)),
+          (ruleName2, triggerName, (actionName, actionName, defaultAction))),
+        assetHelper)
+
+      wsk.rule.disable(ruleName)
+      val listOutput = wsk.rule.list().stdout.lines
+      listOutput.find(_.contains(ruleName2)).get should (include(ruleName2) and include("active"))
+      listOutput.find(_.contains(ruleName)).get should (include(ruleName) and include("inactive"))
+      wsk.rule.list().stdout should not include ("Unknown")
+  }
 
 }
diff --git a/tests/src/test/scala/system/basic/WskSdkTests.scala b/tests/src/test/scala/system/basic/WskSdkTests.scala
index ac448b1..62c8d60 100644
--- a/tests/src/test/scala/system/basic/WskSdkTests.scala
+++ b/tests/src/test/scala/system/basic/WskSdkTests.scala
@@ -33,85 +33,83 @@ import common.WskProps
 import common.WskTestHelpers
 
 @RunWith(classOf[JUnitRunner])
-class WskSdkTests
-    extends TestHelpers
-    with WskTestHelpers {
-
-    implicit val wskprops = WskProps()
-    val wsk = new Wsk
-
-    behavior of "Wsk SDK"
-
-    it should "download docker action sdk" in {
-        val dir = File.createTempFile("wskinstall", ".tmp")
-        dir.delete()
-        dir.mkdir() should be(true)
-        try {
-            wsk.cli(wskprops.overrides ++ Seq("sdk", "install", "docker"), workingDir = dir).
-                stdout should include("The docker skeleton is now installed at the current directory.")
-
-            val sdk = new File(dir, "dockerSkeleton")
-            sdk.exists() should be(true)
-            sdk.isDirectory() should be(true)
-
-            val dockerfile = new File(sdk, "Dockerfile")
-            dockerfile.exists() should be(true)
-            dockerfile.isFile() should be(true)
-            val lines = FileUtils.readLines(dockerfile)
-            // confirm that the image is correct
-            lines.get(1) shouldBe "FROM openwhisk/dockerskeleton"
-
-            val buildAndPushFile = new File(sdk, "buildAndPush.sh")
-            buildAndPushFile.canExecute() should be(true)
-
-            // confirm there is no other divergence from the base dockerfile
-            val originalDockerfile = WhiskProperties.getFileRelativeToWhiskHome("sdk/docker/Dockerfile")
-            val originalLines = FileUtils.readLines(originalDockerfile)
-            lines.get(0) shouldBe originalLines.get(0)
-            lines.drop(2).mkString("\n") shouldBe originalLines.drop(2).mkString("\n")
-        } finally {
-            FileUtils.deleteDirectory(dir)
-        }
+class WskSdkTests extends TestHelpers with WskTestHelpers {
+
+  implicit val wskprops = WskProps()
+  val wsk = new Wsk
+
+  behavior of "Wsk SDK"
+
+  it should "download docker action sdk" in {
+    val dir = File.createTempFile("wskinstall", ".tmp")
+    dir.delete()
+    dir.mkdir() should be(true)
+    try {
+      wsk.cli(wskprops.overrides ++ Seq("sdk", "install", "docker"), workingDir = dir).stdout should include(
+        "The docker skeleton is now installed at the current directory.")
+
+      val sdk = new File(dir, "dockerSkeleton")
+      sdk.exists() should be(true)
+      sdk.isDirectory() should be(true)
+
+      val dockerfile = new File(sdk, "Dockerfile")
+      dockerfile.exists() should be(true)
+      dockerfile.isFile() should be(true)
+      val lines = FileUtils.readLines(dockerfile)
+      // confirm that the image is correct
+      lines.get(1) shouldBe "FROM openwhisk/dockerskeleton"
+
+      val buildAndPushFile = new File(sdk, "buildAndPush.sh")
+      buildAndPushFile.canExecute() should be(true)
+
+      // confirm there is no other divergence from the base dockerfile
+      val originalDockerfile = WhiskProperties.getFileRelativeToWhiskHome("sdk/docker/Dockerfile")
+      val originalLines = FileUtils.readLines(originalDockerfile)
+      lines.get(0) shouldBe originalLines.get(0)
+      lines.drop(2).mkString("\n") shouldBe originalLines.drop(2).mkString("\n")
+    } finally {
+      FileUtils.deleteDirectory(dir)
     }
-
-    it should "download iOS sdk" in {
-        val dir = File.createTempFile("wskinstall", ".tmp")
-        dir.delete()
-        dir.mkdir() should be(true)
-
-        wsk.cli(wskprops.overrides ++ Seq("sdk", "install", "iOS"), workingDir = dir).
-            stdout should include("Downloaded OpenWhisk iOS starter app. Unzip OpenWhiskIOSStarterApp.zip and open the project in Xcode.")
-
-        val sdk = new File(dir, "OpenWhiskIOSStarterApp.zip")
-        sdk.exists() should be(true)
-        sdk.isFile() should be(true)
-        FileUtils.sizeOf(sdk) should be > 20000L
-        FileUtils.deleteDirectory(dir)
+  }
+
+  it should "download iOS sdk" in {
+    val dir = File.createTempFile("wskinstall", ".tmp")
+    dir.delete()
+    dir.mkdir() should be(true)
+
+    wsk.cli(wskprops.overrides ++ Seq("sdk", "install", "iOS"), workingDir = dir).stdout should include(
+      "Downloaded OpenWhisk iOS starter app. Unzip OpenWhiskIOSStarterApp.zip and open the project in Xcode.")
+
+    val sdk = new File(dir, "OpenWhiskIOSStarterApp.zip")
+    sdk.exists() should be(true)
+    sdk.isFile() should be(true)
+    FileUtils.sizeOf(sdk) should be > 20000L
+    FileUtils.deleteDirectory(dir)
+  }
+
+  it should "install the bash auto-completion bash script" in {
+    // Use a temp dir for testing to not disturb user's local folder
+    val dir = File.createTempFile("wskinstall", ".tmp")
+    dir.delete()
+    dir.mkdir() should be(true)
+
+    val scriptfilename = "wsk_cli_bash_completion.sh"
+    var scriptfile = new File(dir.getPath(), scriptfilename)
+    try {
+      val stdout = wsk.cli(Seq("sdk", "install", "bashauto"), workingDir = dir, expectedExitCode = SUCCESS_EXIT).stdout
+      stdout should include("is installed in the current directory")
+      val fileContent = FileUtils.readFileToString(scriptfile)
+      fileContent should include("bash completion for wsk")
+    } finally {
+      scriptfile.delete()
+      FileUtils.deleteDirectory(dir)
     }
+  }
 
-    it should "install the bash auto-completion bash script" in {
-        // Use a temp dir for testing to not disturb user's local folder
-        val dir = File.createTempFile("wskinstall", ".tmp")
-        dir.delete()
-        dir.mkdir() should be(true)
-
-        val scriptfilename = "wsk_cli_bash_completion.sh"
-        var scriptfile = new File(dir.getPath(), scriptfilename)
-        try {
-            val stdout = wsk.cli(Seq("sdk", "install", "bashauto"), workingDir = dir, expectedExitCode = SUCCESS_EXIT).stdout
-            stdout should include("is installed in the current directory")
-            val fileContent = FileUtils.readFileToString(scriptfile)
-            fileContent should include("bash completion for wsk")
-        } finally {
-            scriptfile.delete()
-            FileUtils.deleteDirectory(dir)
-        }
-    }
-
-    it should "print bash command completion script to STDOUT" in {
-        val msg = "bash completion for wsk"    // Subject to change, dependent on Cobra script
+  it should "print bash command completion script to STDOUT" in {
+    val msg = "bash completion for wsk" // Subject to change, dependent on Cobra script
 
-        val stdout = wsk.cli(Seq("sdk", "install", "bashauto", "--stdout")).stdout
-        stdout should include(msg)
-    }
+    val stdout = wsk.cli(Seq("sdk", "install", "bashauto", "--stdout")).stdout
+    stdout should include(msg)
+  }
 }
diff --git a/tests/src/test/scala/system/basic/WskSequenceTests.scala b/tests/src/test/scala/system/basic/WskSequenceTests.scala
index 3a1dbe3..bd5cdc0 100644
--- a/tests/src/test/scala/system/basic/WskSequenceTests.scala
+++ b/tests/src/test/scala/system/basic/WskSequenceTests.scala
@@ -49,481 +49,498 @@ import whisk.http.Messages.sequenceIsTooLong
  */
 
 @RunWith(classOf[JUnitRunner])
-class WskSequenceTests
-    extends TestHelpers
-    with ScalatestRouteTest
-    with WskTestHelpers
-    with StreamLogging {
-
-    implicit val wskprops = WskProps()
-    val wsk = new Wsk
-    val allowedActionDuration = 120 seconds
-    val shortDuration = 10 seconds
-
-    behavior of "Wsk Sequence"
-
-    it should "invoke a sequence with normal payload and payload with error field" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "sequence"
-            val actions = Seq("split", "sort", "head", "cat")
-            for (actionName <- actions) {
-                val file = TestCLIUtils.getTestActionFilename(s"$actionName.js")
-                assetHelper.withCleaner(wsk.action, actionName) { (action, _) =>
-                    action.create(name = actionName, artifact = Some(file), timeout = Some(allowedActionDuration))
-                }
-            }
-
-            println(s"Sequence $actions")
-            assetHelper.withCleaner(wsk.action, name) {
-                val sequence = actions.mkString(",")
-                (action, _) => action.create(name, Some(sequence), kind = Some("sequence"), timeout = Some(allowedActionDuration))
-            }
-
-            val now = "it is now " + new Date()
-            val args = Array("what time is it?", now)
-            val run = wsk.action.invoke(name, Map("payload" -> args.mkString("\n").toJson))
-            withActivation(wsk.activation, run, totalWait = 4 * allowedActionDuration) {
-                activation =>
-                    checkSequenceLogsAndAnnotations(activation, 4) // 4 activations in this sequence
-                    activation.cause shouldBe None // topmost sequence
-                    val result = activation.response.result.get
-                    result.fields.get("payload") shouldBe defined
-                    result.fields.get("length") should not be defined
-                    result.fields.get("lines") shouldBe Some(JsArray(Vector(now.toJson)))
-            }
-
-            // update action sequence and run it with normal payload
-            val newSequence = Seq("split", "sort").mkString(",")
-            println(s"Update sequence to $newSequence")
-            wsk.action.create(name, Some(newSequence), kind = Some("sequence"), timeout = Some(allowedActionDuration), update = true)
-            val secondrun = wsk.action.invoke(name, Map("payload" -> args.mkString("\n").toJson))
-            withActivation(wsk.activation, secondrun, totalWait = 2 * allowedActionDuration) {
-                activation =>
-                    checkSequenceLogsAndAnnotations(activation, 2) // 2 activations in this sequence
-                    val result = activation.response.result.get
-                    result.fields.get("length") shouldBe Some(2.toJson)
-                    result.fields.get("lines") shouldBe Some(args.sortWith(_.compareTo(_) < 0).toArray.toJson)
-            }
-
-            println("Run sequence with error in payload")
-            // run sequence with error in the payload
-            // sequence should run with no problems, error should be ignored in this test case
-            // result of sequence should be identical to previous invocation above
-            val payload = Map("error" -> JsString("irrelevant error string"), "payload" -> args.mkString("\n").toJson)
-            val thirdrun = wsk.action.invoke(name, payload)
-            withActivation(wsk.activation, thirdrun, totalWait = 2 * allowedActionDuration) {
-                activation =>
-                    checkSequenceLogsAndAnnotations(activation, 2) // 2 activations in this sequence
-                    val result = activation.response.result.get
-                    result.fields.get("length") shouldBe Some(2.toJson)
-                    result.fields.get("lines") shouldBe Some(args.sortWith(_.compareTo(_) < 0).toArray.toJson)
-            }
+class WskSequenceTests extends TestHelpers with ScalatestRouteTest with WskTestHelpers with StreamLogging {
+
+  implicit val wskprops = WskProps()
+  val wsk = new Wsk
+  val allowedActionDuration = 120 seconds
+  val shortDuration = 10 seconds
+
+  val whiskConfig = new WhiskConfig(Map(WhiskConfig.actionSequenceMaxLimit -> null))
+  assert(whiskConfig.isValid)
+
+  behavior of "Wsk Sequence"
+
+  it should "invoke a sequence with normal payload and payload with error field" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "sequence"
+      val actions = Seq("split", "sort", "head", "cat")
+      for (actionName <- actions) {
+        val file = TestUtils.getTestActionFilename(s"$actionName.js")
+        assetHelper.withCleaner(wsk.action, actionName) { (action, _) =>
+          action.create(name = actionName, artifact = Some(file), timeout = Some(allowedActionDuration))
+        }
+      }
+
+      println(s"Sequence $actions")
+      assetHelper.withCleaner(wsk.action, name) {
+        val sequence = actions.mkString(",")
+        (action, _) =>
+          action.create(name, Some(sequence), kind = Some("sequence"), timeout = Some(allowedActionDuration))
+      }
+
+      val now = "it is now " + new Date()
+      val args = Array("what time is it?", now)
+      val run = wsk.action.invoke(name, Map("payload" -> args.mkString("\n").toJson))
+      withActivation(wsk.activation, run, totalWait = 4 * allowedActionDuration) { activation =>
+        checkSequenceLogsAndAnnotations(activation, 4) // 4 activations in this sequence
+        activation.cause shouldBe None // topmost sequence
+        val result = activation.response.result.get
+        result.fields.get("payload") shouldBe defined
+        result.fields.get("length") should not be defined
+        result.fields.get("lines") shouldBe Some(JsArray(Vector(now.toJson)))
+      }
+
+      // update action sequence and run it with normal payload
+      val newSequence = Seq("split", "sort").mkString(",")
+      println(s"Update sequence to $newSequence")
+      wsk.action.create(
+        name,
+        Some(newSequence),
+        kind = Some("sequence"),
+        timeout = Some(allowedActionDuration),
+        update = true)
+      val secondrun = wsk.action.invoke(name, Map("payload" -> args.mkString("\n").toJson))
+      withActivation(wsk.activation, secondrun, totalWait = 2 * allowedActionDuration) { activation =>
+        checkSequenceLogsAndAnnotations(activation, 2) // 2 activations in this sequence
+        val result = activation.response.result.get
+        result.fields.get("length") shouldBe Some(2.toJson)
+        result.fields.get("lines") shouldBe Some(args.sortWith(_.compareTo(_) < 0).toArray.toJson)
+      }
+
+      println("Run sequence with error in payload")
+      // run sequence with error in the payload
+      // sequence should run with no problems, error should be ignored in this test case
+      // result of sequence should be identical to previous invocation above
+      val payload = Map("error" -> JsString("irrelevant error string"), "payload" -> args.mkString("\n").toJson)
+      val thirdrun = wsk.action.invoke(name, payload)
+      withActivation(wsk.activation, thirdrun, totalWait = 2 * allowedActionDuration) { activation =>
+        checkSequenceLogsAndAnnotations(activation, 2) // 2 activations in this sequence
+        val result = activation.response.result.get
+        result.fields.get("length") shouldBe Some(2.toJson)
+        result.fields.get("lines") shouldBe Some(args.sortWith(_.compareTo(_) < 0).toArray.toJson)
+      }
+  }
+
+  it should "invoke a sequence with an enclosing sequence action" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val inner_name = "inner_sequence"
+    val outer_name = "outer_sequence"
+    val inner_actions = Seq("sort", "head")
+    val actions = Seq("split") ++ inner_actions ++ Seq("cat")
+    // create atomic actions
+    for (actionName <- actions) {
+      val file = TestUtils.getTestActionFilename(s"$actionName.js")
+      assetHelper.withCleaner(wsk.action, actionName) { (action, _) =>
+        action.create(name = actionName, artifact = Some(file), timeout = Some(allowedActionDuration))
+      }
     }
 
-    it should "invoke a sequence with an enclosing sequence action" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val inner_name = "inner_sequence"
-            val outer_name = "outer_sequence"
-            val inner_actions = Seq("sort", "head")
-            val actions = Seq("split") ++ inner_actions ++ Seq("cat")
-            // create atomic actions
-            for (actionName <- actions) {
-                val file = TestCLIUtils.getTestActionFilename(s"$actionName.js")
-                assetHelper.withCleaner(wsk.action, actionName) { (action, _) =>
-                    action.create(name = actionName, artifact = Some(file), timeout = Some(allowedActionDuration))
-                }
-            }
-
-            // create inner sequence
-            assetHelper.withCleaner(wsk.action, inner_name) {
-                val inner_sequence = inner_actions.mkString(",")
-                (action, _) => action.create(inner_name, Some(inner_sequence), kind = Some("sequence"))
-            }
-
-            // create outer sequence
-            assetHelper.withCleaner(wsk.action, outer_name) {
-                val outer_sequence = Seq("split", "inner_sequence", "cat").mkString(",")
-                (action, _) => action.create(outer_name, Some(outer_sequence), kind = Some("sequence"))
-            }
-
-            val now = "it is now " + new Date()
-            val args = Array("what time is it?", now)
-            val run = wsk.action.invoke(outer_name, Map("payload" -> args.mkString("\n").toJson))
-            withActivation(wsk.activation, run, totalWait = 4 * allowedActionDuration) {
-                activation =>
-                    checkSequenceLogsAndAnnotations(activation, 3) // 3 activations in this sequence
-                    activation.cause shouldBe None // topmost sequence
-                    val result = activation.response.result.get
-                    result.fields.get("payload") shouldBe defined
-                    result.fields.get("length") should not be defined
-                    result.fields.get("lines") shouldBe Some(JsArray(Vector(now.toJson)))
-            }
+    // create inner sequence
+    assetHelper.withCleaner(wsk.action, inner_name) {
+      val inner_sequence = inner_actions.mkString(",")
+      (action, _) =>
+        action.create(inner_name, Some(inner_sequence), kind = Some("sequence"))
     }
 
-    /**
-     * s -> echo, x, echo
-     * x -> echo
-     *
-     * update x -> <limit-1> echo -- should work
-     * run s -> should stop after <limit> echo
-     *
-     * This confirms that a dynamic check on the sequence length holds within the system limit.
-     * This is different from creating a long sequence up front which will report a length error at create time.
-     */
-    it should "replace atomic component in a sequence that is too long and report invoke error" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val xName = "xSequence"
-            val sName = "sSequence"
-            val echo = "echo"
-
-            // create echo action
-            val file = TestCLIUtils.getTestActionFilename(s"$echo.js")
-            assetHelper.withCleaner(wsk.action, echo) { (action, actionName) =>
-                action.create(name = actionName, artifact = Some(file), timeout = Some(allowedActionDuration))
-            }
-            // create x
-            assetHelper.withCleaner(wsk.action, xName) {
-                (action, seqName) => action.create(seqName, Some(echo), kind = Some("sequence"))
-            }
-            // create s
-            assetHelper.withCleaner(wsk.action, sName) {
-                (action, seqName) => action.create(seqName, Some(s"$echo,$xName,$echo"), kind = Some("sequence"))
-            }
-
-            // invoke s
-            val now = "it is now " + new Date()
-            val args = Array("what time is it?", now)
-            val argsJson = args.mkString("\n").toJson
-            val run = wsk.action.invoke(sName, Map("payload" -> argsJson))
-            println(s"RUN: ${run.stdout}")
-            withActivation(wsk.activation, run, totalWait = 2 * allowedActionDuration) {
-                activation =>
-                    checkSequenceLogsAndAnnotations(activation, 3) // 3 activations in this sequence
-                    val result = activation.response.result.get
-                    result.fields.get("payload") shouldBe Some(argsJson)
-            }
-            // update x with limit echo
-            val limit = WhiskProperties.getProperty("defaultLimits.actions.sequence.maxLength").toInt
-            val manyEcho = for (i <- 1 to limit) yield echo
-
-            wsk.action.create(xName, Some(manyEcho.mkString(",")), kind = Some("sequence"), update = true)
-
-            val updateRun = wsk.action.invoke(sName, Map("payload" -> argsJson))
-            withActivation(wsk.activation, updateRun, totalWait = 2 * allowedActionDuration) {
-                activation =>
-                    activation.response.status shouldBe ("application error")
-                    checkSequenceLogsAndAnnotations(activation, 2)
-                    val result = activation.response.result.get
-                    result.fields.get("error") shouldBe Some(JsString(sequenceIsTooLong))
-                    // check that inner sequence had only (limit - 1) activations
-                    val innerSeq = activation.logs.get(1) // the id of the inner sequence activation
-                    val getInnerSeq = wsk.activation.get(Some(innerSeq))
-                    withActivation(wsk.activation, getInnerSeq, totalWait = allowedActionDuration) {
-                        innerSeqActivation =>
-                            innerSeqActivation.logs.get.size shouldBe (limit - 1)
-                            innerSeqActivation.cause shouldBe Some(activation.activationId)
-                    }
-            }
+    // create outer sequence
+    assetHelper.withCleaner(wsk.action, outer_name) {
+      val outer_sequence = Seq("split", "inner_sequence", "cat").mkString(",")
+      (action, _) =>
+        action.create(outer_name, Some(outer_sequence), kind = Some("sequence"))
     }
 
-    it should "create and run a sequence in a package with parameters" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val sName = "sSequence"
-
-            // create a package
-            val pkgName = "echopackage"
-            val pkgStr = "LonelyPackage"
-            assetHelper.withCleaner(wsk.pkg, pkgName) {
-                (pkg, name) => pkg.create(name, Map("payload" -> JsString(pkgStr)))
-            }
-            val helloName = "hello"
-            val helloWithPkg = s"$pkgName/$helloName"
-
-            // create hello action in package
-            val file = TestCLIUtils.getTestActionFilename(s"$helloName.js")
-            val actionStr = "AtomicAction"
-            assetHelper.withCleaner(wsk.action, helloWithPkg) { (action, actionName) =>
-                action.create(name = actionName, artifact = Some(file), timeout = Some(allowedActionDuration), parameters = Map("payload" -> JsString(actionStr)))
-            }
-            // create s
-            assetHelper.withCleaner(wsk.action, sName) {
-                (action, seqName) => action.create(seqName, Some(helloWithPkg), kind = Some("sequence"))
-            }
-            val run = wsk.action.invoke(sName)
-            // action params trump package params
-            checkLogsAtomicAction(0, run, new Regex(actionStr))
-            // run with some parameters
-            val sequenceStr = "AlmightySequence"
-            val sequenceParamRun = wsk.action.invoke(sName, parameters = Map("payload" -> JsString(sequenceStr)))
-            // sequence param should be passed to the first atomic action and trump the action params
-            checkLogsAtomicAction(0, sequenceParamRun, new Regex(sequenceStr))
-            // update action and remove the params by sending an unused param that overrides previous params
-            wsk.action.create(name = helloWithPkg, artifact = Some(file), timeout = Some(allowedActionDuration), parameters = Map("param" -> JsString("irrelevant")), update = true)
-            val sequenceParamSecondRun = wsk.action.invoke(sName, parameters = Map("payload" -> JsString(sequenceStr)))
-            // sequence param should be passed to the first atomic action and trump the package params
-            checkLogsAtomicAction(0, sequenceParamSecondRun, new Regex(sequenceStr))
-            val pkgParamRun = wsk.action.invoke(sName)
-            // no sequence params, no atomic action params used, the pkg params should show up
-            checkLogsAtomicAction(0, pkgParamRun, new Regex(pkgStr))
+    val now = "it is now " + new Date()
+    val args = Array("what time is it?", now)
+    val run = wsk.action.invoke(outer_name, Map("payload" -> args.mkString("\n").toJson))
+    withActivation(wsk.activation, run, totalWait = 4 * allowedActionDuration) { activation =>
+      checkSequenceLogsAndAnnotations(activation, 3) // 3 activations in this sequence
+      activation.cause shouldBe None // topmost sequence
+      val result = activation.response.result.get
+      result.fields.get("payload") shouldBe defined
+      result.fields.get("length") should not be defined
+      result.fields.get("lines") shouldBe Some(JsArray(Vector(now.toJson)))
     }
-
-    it should "run a sequence with an action in a package binding with parameters" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val packageName = "package1"
-            val bindName = "package2"
-            val actionName = "print"
-            val packageActionName = packageName + "/" + actionName
-            val bindActionName = bindName + "/" + actionName
-            val packageParams = Map("key1a" -> "value1a".toJson, "key1b" -> "value1b".toJson)
-            val bindParams = Map("key2a" -> "value2a".toJson, "key1b" -> "value2b".toJson)
-            val actionParams = Map("key0" -> "value0".toJson)
-            val file = TestCLIUtils.getTestActionFilename("printParams.js")
-            assetHelper.withCleaner(wsk.pkg, packageName) { (pkg, _) =>
-                pkg.create(packageName, packageParams)
-            }
-            assetHelper.withCleaner(wsk.action, packageActionName) { (action, _) =>
-                action.create(packageActionName, Some(file), parameters = actionParams)
-            }
-            assetHelper.withCleaner(wsk.pkg, bindName) { (pkg, _) =>
-                pkg.bind(packageName, bindName, bindParams)
-            }
-            // sequence
-            val sName = "sequenceWithBindingParams"
-            assetHelper.withCleaner(wsk.action, sName) {
-                (action, seqName) => action.create(seqName, Some(bindActionName), kind = Some("sequence"))
-            }
-            // Check that inherited parameters are passed to the action.
-            val now = new Date().toString()
-            val run = wsk.action.invoke(sName, Map("payload" -> now.toJson))
-            // action params trump package params
-            checkLogsAtomicAction(0, run, new Regex(String.format(".*key0: value0.*key1a: value1a.*key1b: value2b.*key2a: value2a.*payload: %s", now)))
+  }
+
+  /**
+   * s -> echo, x, echo
+   * x -> echo
+   *
+   * update x -> <limit-1> echo -- should work
+   * run s -> should stop after <limit> echo
+   *
+   * This confirms that a dynamic check on the sequence length holds within the system limit.
+   * This is different from creating a long sequence up front which will report a length error at create time.
+   */
+  it should "replace atomic component in a sequence that is too long and report invoke error" in withAssetCleaner(
+    wskprops) { (wp, assetHelper) =>
+    val xName = "xSequence"
+    val sName = "sSequence"
+    val echo = "echo"
+
+    // create echo action
+    val file = TestUtils.getTestActionFilename(s"$echo.js")
+    assetHelper.withCleaner(wsk.action, echo) { (action, actionName) =>
+      action.create(name = actionName, artifact = Some(file), timeout = Some(allowedActionDuration))
     }
-
-    /**
-     * s -> apperror, echo
-     * only apperror should run
-     */
-    it should "stop execution of a sequence (with no payload) on error" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val sName = "sSequence"
-            val apperror = "applicationError"
-            val echo = "echo"
-
-            // create actions
-            val actions = Seq(apperror, echo)
-            for (actionName <- actions) {
-                val file = TestCLIUtils.getTestActionFilename(s"$actionName.js")
-                assetHelper.withCleaner(wsk.action, actionName) { (action, actionName) =>
-                    action.create(name = actionName, artifact = Some(file), timeout = Some(allowedActionDuration))
-                }
-            }
-            // create sequence s
-            assetHelper.withCleaner(wsk.action, sName) {
-                (action, seqName) => action.create(seqName, artifact = Some(actions.mkString(",")), kind = Some("sequence"))
-            }
-            // run sequence s with no payload
-            val run = wsk.action.invoke(sName)
-            withActivation(wsk.activation, run, totalWait = 2 * allowedActionDuration) {
-                activation =>
-                    checkSequenceLogsAndAnnotations(activation, 1) // only the first action should have run
-                    activation.response.success shouldBe (false)
-                    // the status should be error
-                    activation.response.status shouldBe ("application error")
-                    val result = activation.response.result.get
-                    // the result of the activation should be the application error
-                    result shouldBe (JsObject("error" -> JsString("This error thrown on purpose by the action.")))
-            }
+    // create x
+    assetHelper.withCleaner(wsk.action, xName) { (action, seqName) =>
+      action.create(seqName, Some(echo), kind = Some("sequence"))
     }
-
-    /**
-     * s -> echo, initforever
-     * should run both, but error
-     */
-    it should "propagate execution error (timeout) from atomic action to sequence" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val sName = "sSequence"
-            val initforever = "initforever"
-            val echo = "echo"
-
-            // create actions
-            val actions = Seq(echo, initforever)
-            // timeouts for the action; make the one for initforever short
-            val timeout = Map(echo -> allowedActionDuration, initforever -> shortDuration)
-            for (actionName <- actions) {
-                val file = TestCLIUtils.getTestActionFilename(s"$actionName.js")
-                assetHelper.withCleaner(wsk.action, actionName) { (action, actionName) =>
-                    action.create(name = actionName, artifact = Some(file), timeout = Some(timeout(actionName)))
-                }
-            }
-            // create sequence s
-            assetHelper.withCleaner(wsk.action, sName) {
-                (action, seqName) => action.create(seqName, artifact = Some(actions.mkString(",")), kind = Some("sequence"))
-            }
-            // run sequence s with no payload
-            val run = wsk.action.invoke(sName)
-            withActivation(wsk.activation, run, totalWait = 2 * allowedActionDuration) {
-                activation =>
-                    checkSequenceLogsAndAnnotations(activation, 2) // 2 actions
-                    activation.response.success shouldBe (false)
-                    // the status should be error
-                    //activation.response.status shouldBe("application error")
-                    val result = activation.response.result.get
-                    // the result of the activation should be timeout
-                    result shouldBe (JsObject("error" -> JsString("The action exceeded its time limits of 10000 milliseconds during initialization.")))
-            }
+    // create s
+    assetHelper.withCleaner(wsk.action, sName) { (action, seqName) =>
+      action.create(seqName, Some(s"$echo,$xName,$echo"), kind = Some("sequence"))
     }
 
-    /**
-     * s -> echo, sleep
-     * sleep sleeps for 90s, timeout set at 120s
-     * should run both, the blocking call should be transformed into a non-blocking call, but finish executing
-     */
-    it should "execute a sequence in blocking fashion and finish execution even if longer than blocking response timeout" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val sName = "sSequence"
-            val sleep = "timeout"
-            val echo = "echo"
-
-            // create actions
-            val actions = Seq(echo, sleep)
-            for (actionName <- actions) {
-                val file = TestCLIUtils.getTestActionFilename(s"$actionName.js")
-                assetHelper.withCleaner(wsk.action, actionName) { (action, actionName) =>
-                    action.create(name = actionName, artifact = Some(file), timeout = Some(allowedActionDuration))
-                }
-            }
-            // create sequence s
-            assetHelper.withCleaner(wsk.action, sName) {
-                (action, seqName) => action.create(seqName, artifact = Some(actions.mkString(",")), kind = Some("sequence"))
-            }
-            // run sequence s with sleep equal to payload
-            val payload = 65000
-            val run = wsk.action.invoke(sName, parameters = Map("payload" -> JsNumber(payload)), blocking = true, expectedExitCode = ACCEPTED)
-            withActivation(wsk.activation, run, initialWait = 5 seconds, totalWait = 3 * allowedActionDuration) {
-                activation =>
-                    checkSequenceLogsAndAnnotations(activation, 2) // 2 actions
-                    activation.response.success shouldBe (true)
-                    // the status should be error
-                    //activation.response.status shouldBe("application error")
-                    val result = activation.response.result.get
-                    // the result of the activation should be timeout
-                    result shouldBe (JsObject("msg" -> JsString(s"[OK] message terminated successfully after $payload milliseconds.")))
-            }
+    // invoke s
+    val now = "it is now " + new Date()
+    val args = Array("what time is it?", now)
+    val argsJson = args.mkString("\n").toJson
+    val run = wsk.action.invoke(sName, Map("payload" -> argsJson))
+    println(s"RUN: ${run.stdout}")
+    withActivation(wsk.activation, run, totalWait = 2 * allowedActionDuration) { activation =>
+      checkSequenceLogsAndAnnotations(activation, 3) // 3 activations in this sequence
+      val result = activation.response.result.get
+      result.fields.get("payload") shouldBe Some(argsJson)
     }
-
-    /**
-     * sequence s -> echo
-     * t trigger with payload
-     * rule r: t -> s
-     */
-    it should "execute a sequence that is part of a rule and pass the trigger parameters to the sequence" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val seqName = "seqRule"
-            val actionName = "echo"
-            val triggerName = "trigSeq"
-            val ruleName = "ruleSeq"
-
-            val itIsNow = "it is now " + new Date()
-            // set up all entities
-            // trigger
-            val triggerPayload: Map[String, JsValue] = Map("payload" -> JsString(itIsNow))
-            assetHelper.withCleaner(wsk.trigger, triggerName) {
-                (trigger, name) => trigger.create(name, parameters = triggerPayload)
-            }
-            // action
-            val file = TestCLIUtils.getTestActionFilename(s"$actionName.js")
-            assetHelper.withCleaner(wsk.action, actionName) { (action, actionName) =>
-                action.create(name = actionName, artifact = Some(file), timeout = Some(allowedActionDuration))
-            }
-            // sequence
-            assetHelper.withCleaner(wsk.action, seqName) {
-                (action, seqName) => action.create(seqName, artifact = Some(actionName), kind = Some("sequence"))
-            }
-            // rule
-            assetHelper.withCleaner(wsk.rule, ruleName) {
-                (rule, name) => rule.create(name, triggerName, seqName)
-            }
-            // fire trigger
-            val run = wsk.trigger.fire(triggerName)
-            // check that the sequence was invoked and that the echo action produced the expected result
-            checkEchoSeqRuleResult(run, seqName, JsObject(triggerPayload))
-            // fire trigger with new payload
-            val now = "this is now: " + Instant.now
-            val newPayload = Map("payload" -> JsString(now))
-            val newRun = wsk.trigger.fire(triggerName, newPayload)
-            checkEchoSeqRuleResult(newRun, seqName, JsObject(newPayload))
+    // update x with limit echo
+    val limit = whiskConfig.actionSequenceLimit.toInt
+    val manyEcho = for (i <- 1 to limit) yield echo
+
+    wsk.action.create(xName, Some(manyEcho.mkString(",")), kind = Some("sequence"), update = true)
+
+    val updateRun = wsk.action.invoke(sName, Map("payload" -> argsJson))
+    withActivation(wsk.activation, updateRun, totalWait = 2 * allowedActionDuration) { activation =>
+      activation.response.status shouldBe ("application error")
+      checkSequenceLogsAndAnnotations(activation, 2)
+      val result = activation.response.result.get
+      result.fields.get("error") shouldBe Some(JsString(sequenceIsTooLong))
+      // check that inner sequence had only (limit - 1) activations
+      val innerSeq = activation.logs.get(1) // the id of the inner sequence activation
+      val getInnerSeq = wsk.activation.get(Some(innerSeq))
+      withActivation(wsk.activation, getInnerSeq, totalWait = allowedActionDuration) { innerSeqActivation =>
+        innerSeqActivation.logs.get.size shouldBe (limit - 1)
+        innerSeqActivation.cause shouldBe Some(activation.activationId)
+      }
     }
-
-    /**
-     * checks the result of an echo sequence connected to a trigger through a rule
-     * @param triggerFireRun the run result of firing the trigger
-     * @param seqName the sequence name
-     * @param triggerPayload the payload used for the trigger (that should be reflected in the sequence result)
-     */
-    private def checkEchoSeqRuleResult(triggerFireRun: RunResult, seqName: String, triggerPayload: JsObject) = {
-        withActivation(wsk.activation, triggerFireRun) {
-            triggerActivation =>
-                withActivationsFromEntity(wsk.activation, seqName, since = Some(triggerActivation.start)) { activationList =>
-                    activationList.head.response.result shouldBe Some(triggerPayload)
-                    activationList.head.cause shouldBe None
-                }
+  }
+
+  it should "create and run a sequence in a package with parameters" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val sName = "sSequence"
+
+      // create a package
+      val pkgName = "echopackage"
+      val pkgStr = "LonelyPackage"
+      assetHelper.withCleaner(wsk.pkg, pkgName) { (pkg, name) =>
+        pkg.create(name, Map("payload" -> JsString(pkgStr)))
+      }
+      val helloName = "hello"
+      val helloWithPkg = s"$pkgName/$helloName"
+
+      // create hello action in package
+      val file = TestUtils.getTestActionFilename(s"$helloName.js")
+      val actionStr = "AtomicAction"
+      assetHelper.withCleaner(wsk.action, helloWithPkg) { (action, actionName) =>
+        action.create(
+          name = actionName,
+          artifact = Some(file),
+          timeout = Some(allowedActionDuration),
+          parameters = Map("payload" -> JsString(actionStr)))
+      }
+      // create s
+      assetHelper.withCleaner(wsk.action, sName) { (action, seqName) =>
+        action.create(seqName, Some(helloWithPkg), kind = Some("sequence"))
+      }
+      val run = wsk.action.invoke(sName)
+      // action params trump package params
+      checkLogsAtomicAction(0, run, new Regex(actionStr))
+      // run with some parameters
+      val sequenceStr = "AlmightySequence"
+      val sequenceParamRun = wsk.action.invoke(sName, parameters = Map("payload" -> JsString(sequenceStr)))
+      // sequence param should be passed to the first atomic action and trump the action params
+      checkLogsAtomicAction(0, sequenceParamRun, new Regex(sequenceStr))
+      // update action and remove the params by sending an unused param that overrides previous params
+      wsk.action.create(
+        name = helloWithPkg,
+        artifact = Some(file),
+        timeout = Some(allowedActionDuration),
+        parameters = Map("param" -> JsString("irrelevant")),
+        update = true)
+      val sequenceParamSecondRun = wsk.action.invoke(sName, parameters = Map("payload" -> JsString(sequenceStr)))
+      // sequence param should be passed to the first atomic action and trump the package params
+      checkLogsAtomicAction(0, sequenceParamSecondRun, new Regex(sequenceStr))
+      val pkgParamRun = wsk.action.invoke(sName)
+      // no sequence params, no atomic action params used, the pkg params should show up
+      checkLogsAtomicAction(0, pkgParamRun, new Regex(pkgStr))
+  }
+
+  it should "run a sequence with an action in a package binding with parameters" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val packageName = "package1"
+      val bindName = "package2"
+      val actionName = "print"
+      val packageActionName = packageName + "/" + actionName
+      val bindActionName = bindName + "/" + actionName
+      val packageParams = Map("key1a" -> "value1a".toJson, "key1b" -> "value1b".toJson)
+      val bindParams = Map("key2a" -> "value2a".toJson, "key1b" -> "value2b".toJson)
+      val actionParams = Map("key0" -> "value0".toJson)
+      val file = TestUtils.getTestActionFilename("printParams.js")
+      assetHelper.withCleaner(wsk.pkg, packageName) { (pkg, _) =>
+        pkg.create(packageName, packageParams)
+      }
+      assetHelper.withCleaner(wsk.action, packageActionName) { (action, _) =>
+        action.create(packageActionName, Some(file), parameters = actionParams)
+      }
+      assetHelper.withCleaner(wsk.pkg, bindName) { (pkg, _) =>
+        pkg.bind(packageName, bindName, bindParams)
+      }
+      // sequence
+      val sName = "sequenceWithBindingParams"
+      assetHelper.withCleaner(wsk.action, sName) { (action, seqName) =>
+        action.create(seqName, Some(bindActionName), kind = Some("sequence"))
+      }
+      // Check that inherited parameters are passed to the action.
+      val now = new Date().toString()
+      val run = wsk.action.invoke(sName, Map("payload" -> now.toJson))
+      // action params trump package params
+      checkLogsAtomicAction(
+        0,
+        run,
+        new Regex(String.format(".*key0: value0.*key1a: value1a.*key1b: value2b.*key2a: value2a.*payload: %s", now)))
+  }
+
+  /**
+   * s -> apperror, echo
+   * only apperror should run
+   */
+  it should "stop execution of a sequence (with no payload) on error" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val sName = "sSequence"
+      val apperror = "applicationError"
+      val echo = "echo"
+
+      // create actions
+      val actions = Seq(apperror, echo)
+      for (actionName <- actions) {
+        val file = TestUtils.getTestActionFilename(s"$actionName.js")
+        assetHelper.withCleaner(wsk.action, actionName) { (action, actionName) =>
+          action.create(name = actionName, artifact = Some(file), timeout = Some(allowedActionDuration))
         }
-    }
-
-    /**
-     * checks logs for the activation of a sequence (length/size and ids)
-     * checks that the cause field for composing atomic actions is set properly
-     * checks duration
-     * checks memory
-     */
-    private def checkSequenceLogsAndAnnotations(activation: ActivationResult, size: Int) = {
-        activation.logs shouldBe defined
-        // check that the logs are what they are supposed to be (activation ids)
-        // check that the cause field is properly set for these activations
-        activation.logs.get.size shouldBe (size) // the number of activations in this sequence
-        var totalTime: Long = 0
-        var maxMemory: Long = 0
-        for (id <- activation.logs.get) {
-            withActivation(wsk.activation, id, initialWait = 1 second, pollPeriod = 60 seconds, totalWait = allowedActionDuration) {
-                componentActivation =>
-                    componentActivation.cause shouldBe defined
-                    componentActivation.cause.get shouldBe (activation.activationId)
-                    // check causedBy
-                    val causedBy = componentActivation.getAnnotationValue("causedBy")
-                    causedBy shouldBe defined
-                    causedBy.get shouldBe (JsString("sequence"))
-                    totalTime += componentActivation.duration
-                    // extract memory
-                    val mem = extractMemoryAnnotation(componentActivation)
-                    maxMemory = maxMemory max mem
-            }
+      }
+      // create sequence s
+      assetHelper.withCleaner(wsk.action, sName) { (action, seqName) =>
+        action.create(seqName, artifact = Some(actions.mkString(",")), kind = Some("sequence"))
+      }
+      // run sequence s with no payload
+      val run = wsk.action.invoke(sName)
+      withActivation(wsk.activation, run, totalWait = 2 * allowedActionDuration) { activation =>
+        checkSequenceLogsAndAnnotations(activation, 1) // only the first action should have run
+        activation.response.success shouldBe (false)
+        // the status should be error
+        activation.response.status shouldBe ("application error")
+        val result = activation.response.result.get
+        // the result of the activation should be the application error
+        result shouldBe (JsObject("error" -> JsString("This error thrown on purpose by the action.")))
+      }
+  }
+
+  /**
+   * s -> echo, initforever
+   * should run both, but error
+   */
+  it should "propagate execution error (timeout) from atomic action to sequence" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val sName = "sSequence"
+      val initforever = "initforever"
+      val echo = "echo"
+
+      // create actions
+      val actions = Seq(echo, initforever)
+      // timeouts for the action; make the one for initforever short
+      val timeout = Map(echo -> allowedActionDuration, initforever -> shortDuration)
+      for (actionName <- actions) {
+        val file = TestUtils.getTestActionFilename(s"$actionName.js")
+        assetHelper.withCleaner(wsk.action, actionName) { (action, actionName) =>
+          action.create(name = actionName, artifact = Some(file), timeout = Some(timeout(actionName)))
         }
-        // extract duration
-        activation.duration shouldBe (totalTime)
+      }
+      // create sequence s
+      assetHelper.withCleaner(wsk.action, sName) { (action, seqName) =>
+        action.create(seqName, artifact = Some(actions.mkString(",")), kind = Some("sequence"))
+      }
+      // run sequence s with no payload
+      val run = wsk.action.invoke(sName)
+      withActivation(wsk.activation, run, totalWait = 2 * allowedActionDuration) { activation =>
+        checkSequenceLogsAndAnnotations(activation, 2) // 2 actions
+        activation.response.success shouldBe (false)
+        // the status should be error
+        //activation.response.status shouldBe("application error")
+        val result = activation.response.result.get
+        // the result of the activation should be timeout
+        result shouldBe (JsObject(
+          "error" -> JsString("The action exceeded its time limits of 10000 milliseconds during initialization.")))
+      }
+  }
+
+  /**
+   * s -> echo, sleep
+   * sleep sleeps for 90s, timeout set at 120s
+   * should run both, the blocking call should be transformed into a non-blocking call, but finish executing
+   */
+  it should "execute a sequence in blocking fashion and finish execution even if longer than blocking response timeout" in withAssetCleaner(
+    wskprops) { (wp, assetHelper) =>
+    val sName = "sSequence"
+    val sleep = "timeout"
+    val echo = "echo"
+
+    // create actions
+    val actions = Seq(echo, sleep)
+    for (actionName <- actions) {
+      val file = TestUtils.getTestActionFilename(s"$actionName.js")
+      assetHelper.withCleaner(wsk.action, actionName) { (action, actionName) =>
+        action.create(name = actionName, artifact = Some(file), timeout = Some(allowedActionDuration))
+      }
+    }
+    // create sequence s
+    assetHelper.withCleaner(wsk.action, sName) { (action, seqName) =>
+      action.create(seqName, artifact = Some(actions.mkString(",")), kind = Some("sequence"))
+    }
+    // run sequence s with sleep equal to payload
+    val payload = 65000
+    val run = wsk.action.invoke(
+      sName,
+      parameters = Map("payload" -> JsNumber(payload)),
+      blocking = true,
+      expectedExitCode = ACCEPTED)
+    withActivation(wsk.activation, run, initialWait = 5 seconds, totalWait = 3 * allowedActionDuration) { activation =>
+      checkSequenceLogsAndAnnotations(activation, 2) // 2 actions
+      activation.response.success shouldBe (true)
+      // the status should be error
+      //activation.response.status shouldBe("application error")
+      val result = activation.response.result.get
+      // the result of the activation should be timeout
+      result shouldBe (JsObject(
+        "msg" -> JsString(s"[OK] message terminated successfully after $payload milliseconds.")))
+    }
+  }
+
+  /**
+   * sequence s -> echo
+   * t trigger with payload
+   * rule r: t -> s
+   */
+  it should "execute a sequence that is part of a rule and pass the trigger parameters to the sequence" in withAssetCleaner(
+    wskprops) { (wp, assetHelper) =>
+    val seqName = "seqRule"
+    val actionName = "echo"
+    val triggerName = "trigSeq"
+    val ruleName = "ruleSeq"
+
+    val itIsNow = "it is now " + new Date()
+    // set up all entities
+    // trigger
+    val triggerPayload: Map[String, JsValue] = Map("payload" -> JsString(itIsNow))
+    assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, name) =>
+      trigger.create(name, parameters = triggerPayload)
+    }
+    // action
+    val file = TestUtils.getTestActionFilename(s"$actionName.js")
+    assetHelper.withCleaner(wsk.action, actionName) { (action, actionName) =>
+      action.create(name = actionName, artifact = Some(file), timeout = Some(allowedActionDuration))
+    }
+    // sequence
+    assetHelper.withCleaner(wsk.action, seqName) { (action, seqName) =>
+      action.create(seqName, artifact = Some(actionName), kind = Some("sequence"))
+    }
+    // rule
+    assetHelper.withCleaner(wsk.rule, ruleName) { (rule, name) =>
+      rule.create(name, triggerName, seqName)
+    }
+    // fire trigger
+    val run = wsk.trigger.fire(triggerName)
+    // check that the sequence was invoked and that the echo action produced the expected result
+    checkEchoSeqRuleResult(run, seqName, JsObject(triggerPayload))
+    // fire trigger with new payload
+    val now = "this is now: " + Instant.now
+    val newPayload = Map("payload" -> JsString(now))
+    val newRun = wsk.trigger.fire(triggerName, newPayload)
+    checkEchoSeqRuleResult(newRun, seqName, JsObject(newPayload))
+  }
+
+  /**
+   * checks the result of an echo sequence connected to a trigger through a rule
+   * @param triggerFireRun the run result of firing the trigger
+   * @param seqName the sequence name
+   * @param triggerPayload the payload used for the trigger (that should be reflected in the sequence result)
+   */
+  private def checkEchoSeqRuleResult(triggerFireRun: RunResult, seqName: String, triggerPayload: JsObject) = {
+    withActivation(wsk.activation, triggerFireRun) { triggerActivation =>
+      withActivationsFromEntity(wsk.activation, seqName, since = Some(triggerActivation.start)) { activationList =>
+        activationList.head.response.result shouldBe Some(triggerPayload)
+        activationList.head.cause shouldBe None
+      }
+    }
+  }
+
+  /**
+   * checks logs for the activation of a sequence (length/size and ids)
+   * checks that the cause field for composing atomic actions is set properly
+   * checks duration
+   * checks memory
+   */
+  private def checkSequenceLogsAndAnnotations(activation: ActivationResult, size: Int) = {
+    activation.logs shouldBe defined
+    // check that the logs are what they are supposed to be (activation ids)
+    // check that the cause field is properly set for these activations
+    activation.logs.get.size shouldBe (size) // the number of activations in this sequence
+    var totalTime: Long = 0
+    var maxMemory: Long = 0
+    for (id <- activation.logs.get) {
+      withActivation(
+        wsk.activation,
+        id,
+        initialWait = 1 second,
+        pollPeriod = 60 seconds,
+        totalWait = allowedActionDuration) { componentActivation =>
+        componentActivation.cause shouldBe defined
+        componentActivation.cause.get shouldBe (activation.activationId)
+        // check causedBy
+        val causedBy = componentActivation.getAnnotationValue("causedBy")
+        causedBy shouldBe defined
+        causedBy.get shouldBe (JsString("sequence"))
+        totalTime += componentActivation.duration
         // extract memory
-        activation.annotations shouldBe defined
-        val memory = extractMemoryAnnotation(activation)
-        memory shouldBe (maxMemory)
+        val mem = extractMemoryAnnotation(componentActivation)
+        maxMemory = maxMemory max mem
+      }
     }
-
-    /** checks that the logs of the idx-th atomic action from a sequence contains logsStr */
-    private def checkLogsAtomicAction(atomicActionIdx: Int, run: RunResult, regex: Regex) {
-        withActivation(wsk.activation, run, totalWait = 2 * allowedActionDuration) { activation =>
-            checkSequenceLogsAndAnnotations(activation, 1)
-            val componentId = activation.logs.get(atomicActionIdx)
-            val getComponentActivation = wsk.activation.get(Some(componentId))
-            withActivation(wsk.activation, getComponentActivation, totalWait = allowedActionDuration) { componentActivation =>
-                println(componentActivation)
-                componentActivation.logs shouldBe defined
-                val logs = componentActivation.logs.get.mkString(" ")
-                regex.findFirstIn(logs) shouldBe defined
-            }
-        }
+    // extract duration
+    activation.duration shouldBe (totalTime)
+    // extract memory
+    activation.annotations shouldBe defined
+    val memory = extractMemoryAnnotation(activation)
+    memory shouldBe (maxMemory)
+  }
+
+  /** checks that the logs of the idx-th atomic action from a sequence contains logsStr */
+  private def checkLogsAtomicAction(atomicActionIdx: Int, run: RunResult, regex: Regex) {
+    withActivation(wsk.activation, run, totalWait = 2 * allowedActionDuration) { activation =>
+      checkSequenceLogsAndAnnotations(activation, 1)
+      val componentId = activation.logs.get(atomicActionIdx)
+      val getComponentActivation = wsk.activation.get(Some(componentId))
+      withActivation(wsk.activation, getComponentActivation, totalWait = allowedActionDuration) { componentActivation =>
+        println(componentActivation)
+        componentActivation.logs shouldBe defined
+        val logs = componentActivation.logs.get.mkString(" ")
+        regex.findFirstIn(logs) shouldBe defined
+      }
     }
+  }
 
-    private def extractMemoryAnnotation(activation: ActivationResult): Long = {
-        val limits = activation.getAnnotationValue("limits")
-        limits shouldBe defined
-        limits.get.asJsObject.getFields("memory")(0).convertTo[Long]
-    }
+  private def extractMemoryAnnotation(activation: ActivationResult): Long = {
+    val limits = activation.getAnnotationValue("limits")
+    limits shouldBe defined
+    limits.get.asJsObject.getFields("memory")(0).convertTo[Long]
+  }
 }
diff --git a/tests/src/test/scala/whisk/core/admin/WskAdminTests.scala b/tests/src/test/scala/whisk/core/admin/WskAdminTests.scala
index 66ebd90..c42e2e8 100644
--- a/tests/src/test/scala/whisk/core/admin/WskAdminTests.scala
+++ b/tests/src/test/scala/whisk/core/admin/WskAdminTests.scala
@@ -33,141 +33,150 @@ import whisk.core.entity.Subject
 import common.TestUtils
 
 @RunWith(classOf[JUnitRunner])
-class WskAdminTests
-    extends TestHelpers
-    with Matchers {
-
-    behavior of "Wsk Admin CLI"
-
-    it should "confirm wskadmin exists" in {
-        WskAdmin.exists
+class WskAdminTests extends TestHelpers with Matchers {
+
+  behavior of "Wsk Admin CLI"
+
+  it should "confirm wskadmin exists" in {
+    WskAdmin.exists
+  }
+
+  it should "CRD a subject" in {
+    val wskadmin = new RunWskAdminCmd {}
+    val auth = AuthKey()
+    val subject = Subject().asString
+    try {
+      println(s"CRD subject: $subject")
+      val create = wskadmin.cli(Seq("user", "create", subject))
+      val get = wskadmin.cli(Seq("user", "get", subject))
+      create.stdout should be(get.stdout)
+
+      val authkey = get.stdout.trim
+      authkey should include(":")
+      authkey.split(":")(0).length should be(36)
+      authkey.split(":")(1).length should be >= 64
+
+      wskadmin.cli(Seq("user", "whois", authkey)).stdout.trim should be(
+        Seq(s"subject: $subject", s"namespace: $subject").mkString("\n"))
+
+      whisk.utils.retry({
+        // reverse lookup by namespace
+        wskadmin.cli(Seq("user", "list", "-k", subject)).stdout.trim should be(authkey)
+      }, 10, Some(1.second))
+
+      wskadmin.cli(Seq("user", "delete", subject)).stdout should include("Subject deleted")
+
+      // recreate with explicit
+      val newspace = s"${subject}.myspace"
+      wskadmin.cli(Seq("user", "create", subject, "-ns", newspace, "-u", auth.compact))
+
+      whisk.utils.retry({
+        // reverse lookup by namespace
+        wskadmin.cli(Seq("user", "list", "-k", newspace)).stdout.trim should be(auth.compact)
+      }, 10, Some(1.second))
+
+      wskadmin.cli(Seq("user", "get", subject, "-ns", newspace)).stdout.trim should be(auth.compact)
+
+      // delete namespace
+      wskadmin.cli(Seq("user", "delete", subject, "-ns", newspace)).stdout should include("Namespace deleted")
+    } finally {
+      wskadmin.cli(Seq("user", "delete", subject)).stdout should include("Subject deleted")
     }
-
-    it should "CRD a subject" in {
-        val wskadmin = new RunWskAdminCmd {}
-        val auth = AuthKey()
-        val subject = Subject().asString
-        try {
-            println(s"CRD subject: $subject")
-            val create = wskadmin.cli(Seq("user", "create", subject))
-            val get = wskadmin.cli(Seq("user", "get", subject))
-            create.stdout should be(get.stdout)
-
-            val authkey = get.stdout.trim
-            authkey should include(":")
-            authkey.split(":")(0).length should be(36)
-            authkey.split(":")(1).length should be >= 64
-
-            wskadmin.cli(Seq("user", "whois", authkey)).stdout.trim should be(Seq(s"subject: $subject", s"namespace: $subject").mkString("\n"))
-
-            whisk.utils.retry({
-                // reverse lookup by namespace
-                wskadmin.cli(Seq("user", "list", "-k", subject)).stdout.trim should be(authkey)
-            }, 10, Some(1.second))
-
-            wskadmin.cli(Seq("user", "delete", subject)).stdout should include("Subject deleted")
-
-            // recreate with explicit
-            val newspace = s"${subject}.myspace"
-            wskadmin.cli(Seq("user", "create", subject, "-ns", newspace, "-u", auth.compact))
-
-            whisk.utils.retry({
-                // reverse lookup by namespace
-                wskadmin.cli(Seq("user", "list", "-k", newspace)).stdout.trim should be(auth.compact)
-            }, 10, Some(1.second))
-
-            wskadmin.cli(Seq("user", "get", subject, "-ns", newspace)).stdout.trim should be(auth.compact)
-
-            // delete namespace
-            wskadmin.cli(Seq("user", "delete", subject, "-ns", newspace)).stdout should include("Namespace deleted")
-        } finally {
-            wskadmin.cli(Seq("user", "delete", subject)).stdout should include("Subject deleted")
-        }
+  }
+
+  it should "verify guest account installed correctly" in {
+    val wskadmin = new RunWskAdminCmd {}
+    implicit val wskprops = WskProps()
+    val wsk = new Wsk
+    val ns = wsk.namespace.whois()
+    wskadmin.cli(Seq("user", "get", ns)).stdout.trim should be(wskprops.authKey)
+  }
+
+  it should "block and unblock a user respectively" in {
+    val wskadmin = new RunWskAdminCmd {}
+    val auth = AuthKey()
+    val subject1 = Subject().asString
+    val subject2 = Subject().asString
+    val commonNamespace = "testspace"
+    try {
+      wskadmin.cli(Seq("user", "create", subject1, "-ns", commonNamespace, "-u", auth.compact))
+      wskadmin.cli(Seq("user", "create", subject2, "-ns", commonNamespace))
+
+      whisk.utils.retry({
+        // reverse lookup by namespace
+        val out = wskadmin.cli(Seq("user", "list", "-p", "2", "-k", commonNamespace)).stdout.trim
+        out should include(auth.compact)
+        out.lines should have size 2
+      }, 10, Some(1.second))
+
+      // block the user
+      wskadmin.cli(Seq("user", "block", subject1))
+
+      // wait until the user can no longer be found
+      whisk.utils.retry({
+        wskadmin.cli(Seq("user", "list", "-p", "2", "-k", commonNamespace)).stdout.trim.lines should have size 1
+      }, 10, Some(1.second))
+
+      // unblock the user
+      wskadmin.cli(Seq("user", "unblock", subject1))
+
+      // wait until the user can be found again
+      whisk.utils.retry({
+        val out = wskadmin.cli(Seq("user", "list", "-p", "2", "-k", commonNamespace)).stdout.trim
+        out should include(auth.compact)
+        out.lines should have size 2
+      }, 10, Some(1.second))
+    } finally {
+      wskadmin.cli(Seq("user", "delete", subject1)).stdout should include("Subject deleted")
+      wskadmin.cli(Seq("user", "delete", subject2)).stdout should include("Subject deleted")
     }
-
-    it should "verify guest account installed correctly" in {
-        val wskadmin = new RunWskAdminCmd {}
-        implicit val wskprops = WskProps()
-        val wsk = new Wsk
-        val ns = wsk.namespace.whois()
-        wskadmin.cli(Seq("user", "get", ns)).stdout.trim should be(wskprops.authKey)
+  }
+
+  it should "not allow edits on a blocked subject" in {
+    val wskadmin = new RunWskAdminCmd {}
+    val subject = Subject().asString
+    try {
+      // initially create the subject
+      wskadmin.cli(Seq("user", "create", subject))
+      // editing works
+      wskadmin.cli(Seq("user", "create", subject, "-ns", "testspace1"))
+      // block it
+      wskadmin.cli(Seq("user", "block", subject))
+      // Try to add a namespace, doesn't work
+      wskadmin.cli(Seq("user", "create", subject, "-ns", "testspace2"), expectedExitCode = TestUtils.ERROR_EXIT)
+      // Unblock the user
+      wskadmin.cli(Seq("user", "unblock", subject))
+      // Adding a namespace works
+      wskadmin.cli(Seq("user", "create", subject, "-ns", "testspace2"))
+    } finally {
+      wskadmin.cli(Seq("user", "delete", subject)).stdout should include("Subject deleted")
     }
-
-    it should "block and unblock a user respectively" in {
-        val wskadmin = new RunWskAdminCmd {}
-        val auth = AuthKey()
-        val subject1 = Subject().asString
-        val subject2 = Subject().asString
-        val commonNamespace = "testspace"
-        try {
-            wskadmin.cli(Seq("user", "create", subject1, "-ns", commonNamespace, "-u", auth.compact))
-            wskadmin.cli(Seq("user", "create", subject2, "-ns", commonNamespace))
-
-            whisk.utils.retry({
-                // reverse lookup by namespace
-                val out = wskadmin.cli(Seq("user", "list", "-p", "2", "-k", commonNamespace)).stdout.trim
-                out should include(auth.compact)
-                out.lines should have size 2
-            }, 10, Some(1.second))
-
-            // block the user
-            wskadmin.cli(Seq("user", "block", subject1))
-
-            // wait until the user can no longer be found
-            whisk.utils.retry({
-                wskadmin.cli(Seq("user", "list", "-p", "2", "-k", commonNamespace)).stdout.trim.lines should have size 1
-            }, 10, Some(1.second))
-
-            // unblock the user
-            wskadmin.cli(Seq("user", "unblock", subject1))
-
-            // wait until the user can be found again
-            whisk.utils.retry({
-                val out = wskadmin.cli(Seq("user", "list", "-p", "2", "-k", commonNamespace)).stdout.trim
-                out should include(auth.compact)
-                out.lines should have size 2
-            }, 10, Some(1.second))
-        } finally {
-            wskadmin.cli(Seq("user", "delete", subject1)).stdout should include("Subject deleted")
-            wskadmin.cli(Seq("user", "delete", subject2)).stdout should include("Subject deleted")
-        }
-    }
-
-    it should "not allow edits on a blocked subject" in {
-        val wskadmin = new RunWskAdminCmd {}
-        val subject = Subject().asString
-        try {
-            // initially create the subject
-            wskadmin.cli(Seq("user", "create", subject))
-            // editing works
-            wskadmin.cli(Seq("user", "create", subject, "-ns", "testspace1"))
-            // block it
-            wskadmin.cli(Seq("user", "block", subject))
-            // Try to add a namespace, doesn't work
-            wskadmin.cli(Seq("user", "create", subject, "-ns", "testspace2"), expectedExitCode = TestUtils.ERROR_EXIT)
-            // Unblock the user
-            wskadmin.cli(Seq("user", "unblock", subject))
-            // Adding a namespace works
-            wskadmin.cli(Seq("user", "create", subject, "-ns", "testspace2"))
-        } finally {
-            wskadmin.cli(Seq("user", "delete", subject)).stdout should include("Subject deleted")
-        }
-    }
-
-    it should "adjust throttles for namespace" in {
-        val wskadmin = new RunWskAdminCmd {}
-        val subject = Subject().asString
-        try {
-            // set some limits
-            wskadmin.cli(Seq("limits", "set", subject, "--invocationsPerMinute", "1", "--firesPerMinute", "2", "--concurrentInvocations", "3"))
-            // check correctly set
-            val lines = wskadmin.cli(Seq("limits", "get", subject)).stdout.lines.toSeq
-            lines should have size 3
-            lines(0) shouldBe "invocationsPerMinute = 1"
-            lines(1) shouldBe "firesPerMinute = 2"
-            lines(2) shouldBe "concurrentInvocations = 3"
-        } finally {
-            wskadmin.cli(Seq("limits", "delete", subject)).stdout should include("Limits deleted")
-        }
+  }
+
+  it should "adjust throttles for namespace" in {
+    val wskadmin = new RunWskAdminCmd {}
+    val subject = Subject().asString
+    try {
+      // set some limits
+      wskadmin.cli(
+        Seq(
+          "limits",
+          "set",
+          subject,
+          "--invocationsPerMinute",
+          "1",
+          "--firesPerMinute",
+          "2",
+          "--concurrentInvocations",
+          "3"))
+      // check correctly set
+      val lines = wskadmin.cli(Seq("limits", "get", subject)).stdout.lines.toSeq
+      lines should have size 3
+      lines(0) shouldBe "invocationsPerMinute = 1"
+      lines(1) shouldBe "firesPerMinute = 2"
+      lines(2) shouldBe "concurrentInvocations = 3"
+    } finally {
+      wskadmin.cli(Seq("limits", "delete", subject)).stdout should include("Limits deleted")
     }
+  }
 }
diff --git a/tests/src/test/scala/whisk/core/apigw/actions/test/ApiGwRoutemgmtActionTests.scala b/tests/src/test/scala/whisk/core/apigw/actions/test/ApiGwRoutemgmtActionTests.scala
index 28f9b0f..fa56de6 100644
--- a/tests/src/test/scala/whisk/core/apigw/actions/test/ApiGwRoutemgmtActionTests.scala
+++ b/tests/src/test/scala/whisk/core/apigw/actions/test/ApiGwRoutemgmtActionTests.scala
@@ -36,20 +36,19 @@ import common.WskTestHelpers
 import spray.json._
 import spray.json.DefaultJsonProtocol._
 
-case class ApiAction(
-    name: String,
-    namespace: String,
-    backendMethod: String = "POST",
-    backendUrl: String,
-    authkey: String) {
-    def toJson(): JsObject = {
-        return JsObject(
-            "name" -> name.toJson,
-            "namespace" -> namespace.toJson,
-            "backendMethod" -> backendMethod.toJson,
-            "backendUrl" -> backendUrl.toJson,
-            "authkey" -> authkey.toJson)
-    }
+case class ApiAction(name: String,
+                     namespace: String,
+                     backendMethod: String = "POST",
+                     backendUrl: String,
+                     authkey: String) {
+  def toJson(): JsObject = {
+    return JsObject(
+      "name" -> name.toJson,
+      "namespace" -> namespace.toJson,
+      "backendMethod" -> backendMethod.toJson,
+      "backendUrl" -> backendUrl.toJson,
+      "authkey" -> authkey.toJson)
+  }
 }
 
 /**
@@ -64,284 +63,532 @@ class ApiGwRoutemgmtActionTests
     with JsHelpers
     with StreamLogging {
 
-    val systemId = "whisk.system"
-    implicit val wskprops = WskProps(authKey = WskAdmin.listKeys(systemId)(0)._1, namespace = systemId)
-    val wsk = new Wsk
-
-    def getApis(
-        bpOrName: Option[String],
-        relpath: Option[String] = None,
-        operation: Option[String] = None,
-        docid: Option[String] = None,
-        accesstoken: Option[String] = Some("AnAccessToken"),
-        spaceguid: Option[String] = Some("ASpaceGuid") ): Vector[JsValue] = {
-        val parms = Map[String, JsValue]() ++
-            Map("__ow_user" -> wskprops.namespace.toJson) ++
-            { bpOrName map { b => Map("basepath" -> b.toJson) } getOrElse Map[String, JsValue]() } ++
-            { relpath map { r => Map("relpath" -> r.toJson) } getOrElse Map[String, JsValue]() } ++
-            { operation map { o => Map("operation" -> o.toJson) } getOrElse Map[String, JsValue]() } ++
-            { docid map { d => Map("docid" -> d.toJson) } getOrElse Map[String, JsValue]() } ++
-            { accesstoken map { t => Map("accesstoken" -> t.toJson) } getOrElse Map[String, JsValue]() } ++
-            { spaceguid map { s => Map("spaceguid" -> s.toJson) } getOrElse Map[String, JsValue]() }
+  val systemId = "whisk.system"
+  implicit val wskprops = WskProps(authKey = WskAdmin.listKeys(systemId)(0)._1, namespace = systemId)
+  val wsk = new Wsk
 
-        val rr = wsk.action.invoke(
-            name = "apimgmt/getApi",
-            parameters = parms,
-            blocking = true,
-            result = true,
-            expectedExitCode = SUCCESS_EXIT)(wskprops)
-        var apiJsArray: JsArray =
-            try {
-                var apisobj = rr.stdout.parseJson.asJsObject.fields("apis")
-                apisobj.convertTo[JsArray]
-            } catch {
-                case e: Exception =>
-                    JsArray.empty
-            }
-        return apiJsArray.elements
+  def getApis(bpOrName: Option[String],
+              relpath: Option[String] = None,
+              operation: Option[String] = None,
+              docid: Option[String] = None,
+              accesstoken: Option[String] = Some("AnAccessToken"),
+              spaceguid: Option[String] = Some("ASpaceGuid")): Vector[JsValue] = {
+    val parms = Map[String, JsValue]() ++
+      Map("__ow_user" -> wskprops.namespace.toJson) ++ {
+      bpOrName map { b =>
+        Map("basepath" -> b.toJson)
+      } getOrElse Map[String, JsValue]()
+    } ++ {
+      relpath map { r =>
+        Map("relpath" -> r.toJson)
+      } getOrElse Map[String, JsValue]()
+    } ++ {
+      operation map { o =>
+        Map("operation" -> o.toJson)
+      } getOrElse Map[String, JsValue]()
+    } ++ {
+      docid map { d =>
+        Map("docid" -> d.toJson)
+      } getOrElse Map[String, JsValue]()
+    } ++ {
+      accesstoken map { t =>
+        Map("accesstoken" -> t.toJson)
+      } getOrElse Map[String, JsValue]()
+    } ++ {
+      spaceguid map { s =>
+        Map("spaceguid" -> s.toJson)
+      } getOrElse Map[String, JsValue]()
     }
 
-    def createApi(
-        namespace: Option[String] = Some("_"),
-        basepath: Option[String] = Some("/"),
-        relpath: Option[String],
-        operation: Option[String],
-        apiname: Option[String],
-        action: Option[ApiAction],
-        swagger: Option[String] = None,
-        accesstoken: Option[String] = Some("AnAccessToken"),
-        spaceguid: Option[String] = Some("ASpaceGuid"),
-        expectedExitCode: Int = SUCCESS_EXIT): RunResult = {
-        val parms = Map[String, JsValue]() ++
-            { namespace map { n => Map("namespace" -> n.toJson) } getOrElse Map[String, JsValue]() } ++
-            { basepath map { b => Map("gatewayBasePath" -> b.toJson) } getOrElse Map[String, JsValue]() } ++
-            { relpath map { r => Map("gatewayPath" -> r.toJson) } getOrElse Map[String, JsValue]() } ++
-            { operation map { o => Map("gatewayMethod" -> o.toJson) } getOrElse Map[String, JsValue]() } ++
-            { apiname map { an => Map("apiName" -> an.toJson) } getOrElse Map[String, JsValue]() } ++
-            { action map { a => Map("action" -> a.toJson) } getOrElse Map[String, JsValue]() } ++
-            { swagger map { s => Map("swagger" -> s.toJson) } getOrElse Map[String, JsValue]() }
-        val parm = Map[String, JsValue]("apidoc" -> JsObject(parms)) ++
-            { namespace map { n => Map("__ow_user" -> n.toJson) } getOrElse Map[String, JsValue]() } ++
-            { accesstoken map { t => Map("accesstoken" -> t.toJson) } getOrElse Map[String, JsValue]() } ++
-            { spaceguid map { s => Map("spaceguid" -> s.toJson) } getOrElse Map[String, JsValue]() }
+    val rr = wsk.action.invoke(
+      name = "apimgmt/getApi",
+      parameters = parms,
+      blocking = true,
+      result = true,
+      expectedExitCode = SUCCESS_EXIT)(wskprops)
+    var apiJsArray: JsArray =
+      try {
+        var apisobj = rr.stdout.parseJson.asJsObject.fields("apis")
+        apisobj.convertTo[JsArray]
+      } catch {
+        case e: Exception =>
+          JsArray.empty
+      }
+    return apiJsArray.elements
+  }
 
-        val rr = wsk.action.invoke(
-            name = "apimgmt/createApi",
-            parameters = parm,
-            blocking = true,
-            result = true,
-            expectedExitCode = expectedExitCode)(wskprops)
-        return rr
+  def createApi(namespace: Option[String] = Some("_"),
+                basepath: Option[String] = Some("/"),
+                relpath: Option[String],
+                operation: Option[String],
+                apiname: Option[String],
+                action: Option[ApiAction],
+                swagger: Option[String] = None,
+                accesstoken: Option[String] = Some("AnAccessToken"),
+                spaceguid: Option[String] = Some("ASpaceGuid"),
+                expectedExitCode: Int = SUCCESS_EXIT): RunResult = {
+    val parms = Map[String, JsValue]() ++ {
+      namespace map { n =>
+        Map("namespace" -> n.toJson)
+      } getOrElse Map[String, JsValue]()
+    } ++ {
+      basepath map { b =>
+        Map("gatewayBasePath" -> b.toJson)
+      } getOrElse Map[String, JsValue]()
+    } ++ {
+      relpath map { r =>
+        Map("gatewayPath" -> r.toJson)
+      } getOrElse Map[String, JsValue]()
+    } ++ {
+      operation map { o =>
+        Map("gatewayMethod" -> o.toJson)
+      } getOrElse Map[String, JsValue]()
+    } ++ {
+      apiname map { an =>
+        Map("apiName" -> an.toJson)
+      } getOrElse Map[String, JsValue]()
+    } ++ {
+      action map { a =>
+        Map("action" -> a.toJson)
+      } getOrElse Map[String, JsValue]()
+    } ++ {
+      swagger map { s =>
+        Map("swagger" -> s.toJson)
+      } getOrElse Map[String, JsValue]()
+    }
+    val parm = Map[String, JsValue]("apidoc" -> JsObject(parms)) ++ {
+      namespace map { n =>
+        Map("__ow_user" -> n.toJson)
+      } getOrElse Map[String, JsValue]()
+    } ++ {
+      accesstoken map { t =>
+        Map("accesstoken" -> t.toJson)
+      } getOrElse Map[String, JsValue]()
+    } ++ {
+      spaceguid map { s =>
+        Map("spaceguid" -> s.toJson)
+      } getOrElse Map[String, JsValue]()
     }
 
-    def deleteApi(
-        namespace: Option[String] = Some("_"),
-        basepath: Option[String] = Some("/"),
-        relpath: Option[String] = None,
-        operation: Option[String] = None,
-        apiname: Option[String] = None,
-        accesstoken: Option[String] = Some("AnAccessToken"),
-        spaceguid: Option[String] = Some("ASpaceGuid"),
-        expectedExitCode: Int = SUCCESS_EXIT): RunResult = {
-        val parms = Map[String, JsValue]() ++
-            { namespace map { n => Map("__ow_user" -> n.toJson) } getOrElse Map[String, JsValue]() } ++
-            { basepath map { b => Map("basepath" -> b.toJson) } getOrElse Map[String, JsValue]() } ++
-            { relpath map { r => Map("relpath" -> r.toJson) } getOrElse Map[String, JsValue]() } ++
-            { operation map { o => Map("operation" -> o.toJson) } getOrElse Map[String, JsValue]() } ++
-            { apiname map { an => Map("apiname" -> an.toJson) } getOrElse Map[String, JsValue]() } ++
-            { accesstoken map { t => Map("accesstoken" -> t.toJson) } getOrElse Map[String, JsValue]() } ++
-            { spaceguid map { s => Map("spaceguid" -> s.toJson) } getOrElse Map[String, JsValue]() }
+    val rr = wsk.action.invoke(
+      name = "apimgmt/createApi",
+      parameters = parm,
+      blocking = true,
+      result = true,
+      expectedExitCode = expectedExitCode)(wskprops)
+    return rr
+  }
 
-        val rr = wsk.action.invoke(
-            name = "apimgmt/deleteApi",
-            parameters = parms,
-            blocking = true,
-            result = true,
-            expectedExitCode = expectedExitCode)(wskprops)
-        return rr
+  def deleteApi(namespace: Option[String] = Some("_"),
+                basepath: Option[String] = Some("/"),
+                relpath: Option[String] = None,
+                operation: Option[String] = None,
+                apiname: Option[String] = None,
+                accesstoken: Option[String] = Some("AnAccessToken"),
+                spaceguid: Option[String] = Some("ASpaceGuid"),
+                expectedExitCode: Int = SUCCESS_EXIT): RunResult = {
+    val parms = Map[String, JsValue]() ++ {
+      namespace map { n =>
+        Map("__ow_user" -> n.toJson)
+      } getOrElse Map[String, JsValue]()
+    } ++ {
+      basepath map { b =>
+        Map("basepath" -> b.toJson)
+      } getOrElse Map[String, JsValue]()
+    } ++ {
+      relpath map { r =>
+        Map("relpath" -> r.toJson)
+      } getOrElse Map[String, JsValue]()
+    } ++ {
+      operation map { o =>
+        Map("operation" -> o.toJson)
+      } getOrElse Map[String, JsValue]()
+    } ++ {
+      apiname map { an =>
+        Map("apiname" -> an.toJson)
+      } getOrElse Map[String, JsValue]()
+    } ++ {
+      accesstoken map { t =>
+        Map("accesstoken" -> t.toJson)
+      } getOrElse Map[String, JsValue]()
+    } ++ {
+      spaceguid map { s =>
+        Map("spaceguid" -> s.toJson)
+      } getOrElse Map[String, JsValue]()
     }
 
-    def apiMatch(
-        apiarr: Vector[JsValue],
-        basepath: String = "/",
-        relpath: String = "",
-        operation: String = "",
-        apiname: String = "",
-        action: ApiAction = null): Boolean = {
-        var matches: Boolean = false
-        for (api <- apiarr) {
-            val basepathExists = JsObjectHelper(api.asJsObject).fieldPathExists("value", "apidoc", "basePath")
-            if (basepathExists) {
-                System.out.println("basePath exists")
-                val basepathMatches = (JsObjectHelper(api.asJsObject).getFieldPath("value", "apidoc", "basePath").get.convertTo[String] == basepath)
-                if (basepathMatches) {
-                    System.out.println("basePath matches: " + basepath)
-                    val apinameExists = JsObjectHelper(api.asJsObject).fieldPathExists("value", "apidoc", "info", "title")
-                    if (apinameExists) {
-                        System.out.println("api name exists")
-                        val apinameMatches = (JsObjectHelper(api.asJsObject).getFieldPath("value", "apidoc", "info", "title").get.convertTo[String] == apiname)
-                        if (apinameMatches) {
-                            System.out.println("api name matches: " + apiname)
-                            val endpointMatches = JsObjectHelper(api.asJsObject).fieldPathExists("value", "apidoc", "paths", relpath, operation)
-                            if (endpointMatches) {
-                                System.out.println("endpoint exists/matches : " + relpath + "  " + operation)
-                                val actionConfig = JsObjectHelper(api.asJsObject).getFieldPath("value", "apidoc", "paths", relpath, operation, "x-openwhisk").get.asJsObject
-                                val actionMatches = actionMatch(actionConfig, action)
-                                if (actionMatches) {
-                                    System.out.println("endpoint action matches")
-                                    matches = true;
-                                }
-                            }
-                        }
-                    }
+    val rr = wsk.action.invoke(
+      name = "apimgmt/deleteApi",
+      parameters = parms,
+      blocking = true,
+      result = true,
+      expectedExitCode = expectedExitCode)(wskprops)
+    return rr
+  }
+
+  def apiMatch(apiarr: Vector[JsValue],
+               basepath: String = "/",
+               relpath: String = "",
+               operation: String = "",
+               apiname: String = "",
+               action: ApiAction = null): Boolean = {
+    var matches: Boolean = false
+    for (api <- apiarr) {
+      val basepathExists = JsObjectHelper(api.asJsObject).fieldPathExists("value", "apidoc", "basePath")
+      if (basepathExists) {
+        System.out.println("basePath exists")
+        val basepathMatches = (JsObjectHelper(api.asJsObject)
+          .getFieldPath("value", "apidoc", "basePath")
+          .get
+          .convertTo[String] == basepath)
+        if (basepathMatches) {
+          System.out.println("basePath matches: " + basepath)
+          val apinameExists = JsObjectHelper(api.asJsObject).fieldPathExists("value", "apidoc", "info", "title")
+          if (apinameExists) {
+            System.out.println("api name exists")
+            val apinameMatches = (JsObjectHelper(api.asJsObject)
+              .getFieldPath("value", "apidoc", "info", "title")
+              .get
+              .convertTo[String] == apiname)
+            if (apinameMatches) {
+              System.out.println("api name matches: " + apiname)
+              val endpointMatches =
+                JsObjectHelper(api.asJsObject).fieldPathExists("value", "apidoc", "paths", relpath, operation)
+              if (endpointMatches) {
+                System.out.println("endpoint exists/matches : " + relpath + "  " + operation)
+                val actionConfig = JsObjectHelper(api.asJsObject)
+                  .getFieldPath("value", "apidoc", "paths", relpath, operation, "x-openwhisk")
+                  .get
+                  .asJsObject
+                val actionMatches = actionMatch(actionConfig, action)
+                if (actionMatches) {
+                  System.out.println("endpoint action matches")
+                  matches = true;
                 }
+              }
             }
+          }
         }
-        return matches
+      }
     }
+    return matches
+  }
 
-    def actionMatch(
-        jsAction: JsObject,
-        action: ApiAction): Boolean = {
-        System.out.println("actionMatch: url " + jsAction.fields("url").convertTo[String] + "; backendUrl " + action.backendUrl)
-        System.out.println("actionMatch: namespace " + jsAction.fields("namespace").convertTo[String] + "; namespace " + action.namespace)
-        System.out.println("actionMatch: action " + jsAction.fields("action").convertTo[String] + "; action " + action.name)
-        val matches = jsAction.fields("url").convertTo[String] == action.backendUrl &&
-            jsAction.fields("namespace").convertTo[String] == action.namespace &&
-            jsAction.fields("action").convertTo[String] == action.name
-        return matches
-    }
+  def actionMatch(jsAction: JsObject, action: ApiAction): Boolean = {
+    System.out.println(
+      "actionMatch: url " + jsAction.fields("url").convertTo[String] + "; backendUrl " + action.backendUrl)
+    System.out.println(
+      "actionMatch: namespace " + jsAction.fields("namespace").convertTo[String] + "; namespace " + action.namespace)
+    System.out.println("actionMatch: action " + jsAction.fields("action").convertTo[String] + "; action " + action.name)
+    val matches = jsAction.fields("url").convertTo[String] == action.backendUrl &&
+      jsAction.fields("namespace").convertTo[String] == action.namespace &&
+      jsAction.fields("action").convertTo[String] == action.name
+    return matches
+  }
 
-    behavior of "API Gateway apimgmt action parameter validation"
+  behavior of "API Gateway apimgmt action parameter validation"
 
-    it should "verify successful creation of a new API" in {
-        val testName = "APIGWTEST1"
-        val testbasepath = "/" + testName + "_bp"
-        val testrelpath = "/path"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val actionName = testName + "_action"
-        val actionNamespace = wskprops.namespace
-        val actionUrl = "https://some.whisk.host/api/v1/web/" + actionNamespace + "/default/" + actionName + ".json"
-        val actionAuthKey = testName + "_authkey"
-        val testaction = ApiAction(name = actionName, namespace = actionNamespace, backendUrl = actionUrl, authkey = actionAuthKey)
+  it should "verify successful creation of a new API" in {
+    val testName = "APIGWTEST1"
+    val testbasepath = "/" + testName + "_bp"
+    val testrelpath = "/path"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val actionName = testName + "_action"
+    val actionNamespace = wskprops.namespace
+    val actionUrl = "https://some.whisk.host/api/v1/web/" + actionNamespace + "/default/" + actionName + ".json"
+    val actionAuthKey = testName + "_authkey"
+    val testaction =
+      ApiAction(name = actionName, namespace = actionNamespace, backendUrl = actionUrl, authkey = actionAuthKey)
 
-        try {
-            val createResult = createApi(namespace = Some(wskprops.namespace), basepath = Some(testbasepath), relpath = Some(testrelpath),
-                operation = Some(testurlop), apiname = Some(testapiname), action = Some(testaction))
-            JsObjectHelper(createResult.stdout.parseJson.asJsObject).fieldPathExists("apidoc") should be(true)
-            val apiVector = getApis(bpOrName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
-            apiVector.size should be > 0
-            apiMatch(apiVector, testbasepath, testrelpath, testurlop, testapiname, testaction) should be(true)
-        } finally {
-            val deleteResult = deleteApi(namespace = Some(wskprops.namespace), basepath = Some(testbasepath), expectedExitCode = DONTCARE_EXIT)
-        }
+    try {
+      val createResult = createApi(
+        namespace = Some(wskprops.namespace),
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        apiname = Some(testapiname),
+        action = Some(testaction))
+      JsObjectHelper(createResult.stdout.parseJson.asJsObject).fieldPathExists("apidoc") should be(true)
+      val apiVector = getApis(bpOrName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
+      apiVector.size should be > 0
+      apiMatch(apiVector, testbasepath, testrelpath, testurlop, testapiname, testaction) should be(true)
+    } finally {
+      val deleteResult =
+        deleteApi(namespace = Some(wskprops.namespace), basepath = Some(testbasepath), expectedExitCode = DONTCARE_EXIT)
     }
+  }
 
-    it should "verify successful API deletion using basepath" in {
-        val testName = "APIGWTEST2"
-        val testbasepath = "/" + testName + "_bp"
-        val testrelpath = "/path"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val actionName = testName + "_action"
-        val actionNamespace = wskprops.namespace
-        val actionUrl = "https://some.whisk.host/api/v1/web/" + actionNamespace + "/default/" + actionName + ".json"
-        val actionAuthKey = testName + "_authkey"
-        val testaction = ApiAction(name = actionName, namespace = actionNamespace, backendUrl = actionUrl, authkey = actionAuthKey)
+  it should "verify successful API deletion using basepath" in {
+    val testName = "APIGWTEST2"
+    val testbasepath = "/" + testName + "_bp"
+    val testrelpath = "/path"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val actionName = testName + "_action"
+    val actionNamespace = wskprops.namespace
+    val actionUrl = "https://some.whisk.host/api/v1/web/" + actionNamespace + "/default/" + actionName + ".json"
+    val actionAuthKey = testName + "_authkey"
+    val testaction =
+      ApiAction(name = actionName, namespace = actionNamespace, backendUrl = actionUrl, authkey = actionAuthKey)
 
-        try {
-            val createResult = createApi(namespace = Some(wskprops.namespace), basepath = Some(testbasepath), relpath = Some(testrelpath),
-                operation = Some(testurlop), apiname = Some(testapiname), action = Some(testaction))
-            JsObjectHelper(createResult.stdout.parseJson.asJsObject).fieldPathExists("apidoc") should be(true)
-            var apiVector = getApis(bpOrName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
-            apiVector.size should be > 0
-            apiMatch(apiVector, testbasepath, testrelpath, testurlop, testapiname, testaction) should be(true)
-            val deleteResult = deleteApi(namespace = Some(wskprops.namespace), basepath = Some(testbasepath))
-            apiVector = getApis(bpOrName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
-            apiMatch(apiVector, testbasepath, testrelpath, testurlop, testapiname, testaction) should be(false)
-        } finally {
-            val deleteResult = deleteApi(namespace = Some(wskprops.namespace), basepath = Some(testbasepath), expectedExitCode = DONTCARE_EXIT)
-        }
+    try {
+      val createResult = createApi(
+        namespace = Some(wskprops.namespace),
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        apiname = Some(testapiname),
+        action = Some(testaction))
+      JsObjectHelper(createResult.stdout.parseJson.asJsObject).fieldPathExists("apidoc") should be(true)
+      var apiVector = getApis(bpOrName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
+      apiVector.size should be > 0
+      apiMatch(apiVector, testbasepath, testrelpath, testurlop, testapiname, testaction) should be(true)
+      val deleteResult = deleteApi(namespace = Some(wskprops.namespace), basepath = Some(testbasepath))
+      apiVector = getApis(bpOrName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
+      apiMatch(apiVector, testbasepath, testrelpath, testurlop, testapiname, testaction) should be(false)
+    } finally {
+      val deleteResult =
+        deleteApi(namespace = Some(wskprops.namespace), basepath = Some(testbasepath), expectedExitCode = DONTCARE_EXIT)
     }
+  }
 
-    it should "verify successful addition of new relative path to existing API" in {
-        val testName = "APIGWTEST3"
-        val testbasepath = "/" + testName + "_bp"
-        val testrelpath = "/path"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testnewurlop = "delete"
-        val testapiname = testName + " API Name"
-        val actionName = testName + "_action"
-        val actionNamespace = wskprops.namespace
-        val actionUrl = "https://some.whisk.host/api/v1/web/" + actionNamespace + "/default/" + actionName + ".json"
-        val actionAuthKey = testName + "_authkey"
-        val testaction = ApiAction(name = actionName, namespace = actionNamespace, backendUrl = actionUrl, authkey = actionAuthKey)
+  it should "verify successful addition of new relative path to existing API" in {
+    val testName = "APIGWTEST3"
+    val testbasepath = "/" + testName + "_bp"
+    val testrelpath = "/path"
+    val testnewrelpath = "/path_new"
+    val testurlop = "get"
+    val testnewurlop = "delete"
+    val testapiname = testName + " API Name"
+    val actionName = testName + "_action"
+    val actionNamespace = wskprops.namespace
+    val actionUrl = "https://some.whisk.host/api/v1/web/" + actionNamespace + "/default/" + actionName + ".json"
+    val actionAuthKey = testName + "_authkey"
+    val testaction =
+      ApiAction(name = actionName, namespace = actionNamespace, backendUrl = actionUrl, authkey = actionAuthKey)
 
-        try {
-            var createResult = createApi(namespace = Some(wskprops.namespace), basepath = Some(testbasepath), relpath = Some(testrelpath),
-                operation = Some(testurlop), apiname = Some(testapiname), action = Some(testaction))
-            createResult = createApi(namespace = Some(wskprops.namespace), basepath = Some(testbasepath), relpath = Some(testnewrelpath),
-                operation = Some(testnewurlop), apiname = Some(testapiname), action = Some(testaction))
-            JsObjectHelper(createResult.stdout.parseJson.asJsObject).fieldPathExists("apidoc") should be(true)
-            var apiVector = getApis(bpOrName = Some(testbasepath))
-            apiVector.size should be > 0
-            apiMatch(apiVector, testbasepath, testrelpath, testurlop, testapiname, testaction) should be(true)
-            apiMatch(apiVector, testbasepath, testnewrelpath, testnewurlop, testapiname, testaction) should be(true)
-        } finally {
-            val deleteResult = deleteApi(namespace = Some(wskprops.namespace), basepath = Some(testbasepath), expectedExitCode = DONTCARE_EXIT)
-        }
+    try {
+      var createResult = createApi(
+        namespace = Some(wskprops.namespace),
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        apiname = Some(testapiname),
+        action = Some(testaction))
+      createResult = createApi(
+        namespace = Some(wskprops.namespace),
+        basepath = Some(testbasepath),
+        relpath = Some(testnewrelpath),
+        operation = Some(testnewurlop),
+        apiname = Some(testapiname),
+        action = Some(testaction))
+      JsObjectHelper(createResult.stdout.parseJson.asJsObject).fieldPathExists("apidoc") should be(true)
+      var apiVector = getApis(bpOrName = Some(testbasepath))
+      apiVector.size should be > 0
+      apiMatch(apiVector, testbasepath, testrelpath, testurlop, testapiname, testaction) should be(true)
+      apiMatch(apiVector, testbasepath, testnewrelpath, testnewurlop, testapiname, testaction) should be(true)
+    } finally {
+      val deleteResult =
+        deleteApi(namespace = Some(wskprops.namespace), basepath = Some(testbasepath), expectedExitCode = DONTCARE_EXIT)
     }
+  }
 
-    it should "reject apimgmt actions that are invoked with not enough parameters" in {
-        val invalidArgs = Seq(
-            //getApi
-            ("/whisk.system/apimgmt/getApi", ANY_ERROR_EXIT, "Invalid authentication.", Seq()),
+  it should "reject apimgmt actions that are invoked with not enough parameters" in {
+    val invalidArgs = Seq(
+      //getApi
+      ("/whisk.system/apimgmt/getApi", ANY_ERROR_EXIT, "Invalid authentication.", Seq()),
+      //deleteApi
+      (
+        "/whisk.system/apimgmt/deleteApi",
+        ANY_ERROR_EXIT,
+        "Invalid authentication.",
+        Seq("-p", "basepath", "/ApiGwRoutemgmtActionTests_bp")),
+      (
+        "/whisk.system/apimgmt/deleteApi",
+        ANY_ERROR_EXIT,
+        "basepath is required",
+        Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN")),
+      (
+        "/whisk.system/apimgmt/deleteApi",
+        ANY_ERROR_EXIT,
+        "When specifying an operation, the path is required",
+        Seq(
+          "-p",
+          "__ow_user",
+          "_",
+          "-p",
+          "accesstoken",
+          "TOKEN",
+          "-p",
+          "basepath",
+          "/ApiGwRoutemgmtActionTests_bp",
+          "-p",
+          "operation",
+          "get")),
+      //createApi
+      (
+        "/whisk.system/apimgmt/createApi",
+        ANY_ERROR_EXIT,
+        "apidoc is required",
+        Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN")),
+      (
+        "/whisk.system/apimgmt/createApi",
+        ANY_ERROR_EXIT,
+        "apidoc is missing the namespace field",
+        Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "apidoc", "{}")),
+      (
+        "/whisk.system/apimgmt/createApi",
+        ANY_ERROR_EXIT,
+        "apidoc is missing the gatewayBasePath field",
+        Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "apidoc", """{"namespace":"_"}""")),
+      (
+        "/whisk.system/apimgmt/createApi",
+        ANY_ERROR_EXIT,
+        "apidoc is missing the gatewayPath field",
+        Seq(
+          "-p",
+          "__ow_user",
+          "_",
+          "-p",
+          "accesstoken",
+          "TOKEN",
+          "-p",
+          "apidoc",
+          """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp"}""")),
+      (
+        "/whisk.system/apimgmt/createApi",
+        ANY_ERROR_EXIT,
+        "apidoc is missing the gatewayMethod field",
+        Seq(
+          "-p",
+          "__ow_user",
+          "_",
+          "-p",
+          "accesstoken",
+          "TOKEN",
+          "-p",
+          "apidoc",
+          """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp"}""")),
+      (
+        "/whisk.system/apimgmt/createApi",
+        ANY_ERROR_EXIT,
+        "apidoc is missing the action field",
+        Seq(
+          "-p",
+          "__ow_user",
+          "_",
+          "-p",
+          "accesstoken",
+          "TOKEN",
+          "-p",
+          "apidoc",
+          """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get"}""")),
+      (
+        "/whisk.system/apimgmt/createApi",
+        ANY_ERROR_EXIT,
+        "action is missing the backendMethod field",
+        Seq(
+          "-p",
+          "__ow_user",
+          "_",
+          "-p",
+          "accesstoken",
+          "TOKEN",
+          "-p",
+          "apidoc",
+          """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{}}""")),
+      (
+        "/whisk.system/apimgmt/createApi",
+        ANY_ERROR_EXIT,
+        "action is missing the backendUrl field",
+        Seq(
+          "-p",
+          "__ow_user",
+          "_",
+          "-p",
+          "accesstoken",
+          "TOKEN",
+          "-p",
+          "apidoc",
+          """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post"}}""")),
+      (
+        "/whisk.system/apimgmt/createApi",
+        ANY_ERROR_EXIT,
+        "action is missing the namespace field",
+        Seq(
+          "-p",
+          "__ow_user",
+          "_",
+          "-p",
+          "accesstoken",
+          "TOKEN",
+          "-p",
+          "apidoc",
+          """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL"}}""")),
+      (
+        "/whisk.system/apimgmt/createApi",
+        ANY_ERROR_EXIT,
+        "action is missing the name field",
+        Seq(
+          "-p",
+          "__ow_user",
+          "_",
+          "-p",
+          "accesstoken",
+          "TOKEN",
+          "-p",
+          "apidoc",
+          """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL","namespace":"_"}}""")),
+      (
+        "/whisk.system/apimgmt/createApi",
+        ANY_ERROR_EXIT,
+        "action is missing the authkey field",
+        Seq(
+          "-p",
+          "__ow_user",
+          "_",
+          "-p",
+          "accesstoken",
+          "TOKEN",
+          "-p",
+          "apidoc",
+          """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL","namespace":"_","name":"N"}}""")),
+      (
+        "/whisk.system/apimgmt/createApi",
+        ANY_ERROR_EXIT,
+        "swagger and gatewayBasePath are mutually exclusive and cannot be specified together",
+        Seq(
+          "-p",
+          "__ow_user",
+          "_",
+          "-p",
+          "accesstoken",
+          "TOKEN",
+          "-p",
+          "apidoc",
+          """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL","namespace":"_","name":"N","authkey":"XXXX"},"swagger":{}}""")),
+      (
+        "/whisk.system/apimgmt/createApi",
+        ANY_ERROR_EXIT,
+        "apidoc field cannot be parsed. Ensure it is valid JSON",
+        Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "apidoc", "{1:[}}}")))
 
-            //deleteApi
-            ("/whisk.system/apimgmt/deleteApi", ANY_ERROR_EXIT, "Invalid authentication.", Seq("-p", "basepath", "/ApiGwRoutemgmtActionTests_bp")),
-            ("/whisk.system/apimgmt/deleteApi", ANY_ERROR_EXIT, "basepath is required", Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN")),
-            ("/whisk.system/apimgmt/deleteApi", ANY_ERROR_EXIT, "When specifying an operation, the path is required",
-              Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "basepath", "/ApiGwRoutemgmtActionTests_bp", "-p", "operation", "get")),
-
-            //createApi
-            ("/whisk.system/apimgmt/createApi", ANY_ERROR_EXIT, "apidoc is required", Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN")),
-            ("/whisk.system/apimgmt/createApi", ANY_ERROR_EXIT, "apidoc is missing the namespace field",
-              Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "apidoc", "{}")),
-            ("/whisk.system/apimgmt/createApi", ANY_ERROR_EXIT, "apidoc is missing the gatewayBasePath field",
-              Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "apidoc", """{"namespace":"_"}""")),
-            ("/whisk.system/apimgmt/createApi", ANY_ERROR_EXIT, "apidoc is missing the gatewayPath field",
-              Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp"}""")),
-            ("/whisk.system/apimgmt/createApi", ANY_ERROR_EXIT, "apidoc is missing the gatewayMethod field",
-              Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp"}""")),
-            ("/whisk.system/apimgmt/createApi", ANY_ERROR_EXIT, "apidoc is missing the action field",
-              Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get"}""")),
-            ("/whisk.system/apimgmt/createApi", ANY_ERROR_EXIT, "action is missing the backendMethod field",
-              Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{}}""")),
-            ("/whisk.system/apimgmt/createApi", ANY_ERROR_EXIT, "action is missing the backendUrl field",
-              Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post"}}""")),
-            ("/whisk.system/apimgmt/createApi", ANY_ERROR_EXIT, "action is missing the namespace field",
-              Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL"}}""")),
-            ("/whisk.system/apimgmt/createApi", ANY_ERROR_EXIT, "action is missing the name field",
-              Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL","namespace":"_"}}""")),
-            ("/whisk.system/apimgmt/createApi", ANY_ERROR_EXIT, "action is missing the authkey field",
-              Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL","namespace":"_","name":"N"}}""")),
-            ("/whisk.system/apimgmt/createApi", ANY_ERROR_EXIT, "swagger and gatewayBasePath are mutually exclusive and cannot be specified together",
-              Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL","namespace":"_","name":"N","authkey":"XXXX"},"swagger":{}}""")),
-            ("/whisk.system/apimgmt/createApi", ANY_ERROR_EXIT, "apidoc field cannot be parsed. Ensure it is valid JSON",
-              Seq("-p", "__ow_user", "_", "-p", "accesstoken", "TOKEN", "-p", "apidoc", "{1:[}}}")))
-
-        invalidArgs foreach {
-            case (action: String, exitcode: Int, errmsg: String, params: Seq[String]) =>
-                val cmd: Seq[String] = Seq("action",
-                    "invoke",
-                    action,
-                    "-i", "-b", "-r",
-                    "--apihost", wskprops.apihost,
-                    "--auth", wskprops.authKey) ++ params
-                val rr = wsk.cli(cmd, expectedExitCode = exitcode)
-                rr.stderr should include regex (errmsg)
-        }
+    invalidArgs foreach {
+      case (action: String, exitcode: Int, errmsg: String, params: Seq[String]) =>
+        val cmd: Seq[String] = Seq(
+          "action",
+          "invoke",
+          action,
+          "-i",
+          "-b",
+          "-r",
+          "--apihost",
+          wskprops.apihost,
+          "--auth",
+          wskprops.authKey) ++ params
+        val rr = wsk.cli(cmd, expectedExitCode = exitcode)
+        rr.stderr should include regex (errmsg)
     }
+  }
 }
diff --git a/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala b/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
index ac0f01c..5b7c304 100644
--- a/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
@@ -43,189 +43,209 @@ import common.WskTestHelpers
  * Tests for testing the CLI "api" subcommand.  Most of these tests require a deployed backend.
  */
 @RunWith(classOf[JUnitRunner])
-class ApiGwTests
-    extends TestHelpers
-    with WskTestHelpers
-    with BeforeAndAfterEach
-    with BeforeAndAfterAll {
-
-    implicit val wskprops = WskProps()
-    val wsk = new Wsk
-    val clinamespace = wsk.namespace.whois()
-
-    // This test suite makes enough CLI invocations in 60 seconds to trigger the OpenWhisk
-    // throttling restriction.  To avoid CLI failures due to being throttled, track the
-    // CLI invocation calls and when at the throttle limit, pause the next CLI invocation
-    // with exactly enough time to relax the throttling.
-    val maxActionsPerMin = WhiskProperties.getMaxActionInvokesPerMinute()
-    val invocationTimes = new ArrayBuffer[Instant]()
-
-    // Custom CLI properties file
-    val cliWskPropsFile = File.createTempFile("wskprops", ".tmp")
-
-    /**
-     * Expected to be called before each test.
-     * Assumes that each test will not invoke more than 5 actions and
-     * settle the throttle when there isn't enough capacity to handle the test.
-     */
-    def checkThrottle(maxInvocationsBeforeThrottle: Int = maxActionsPerMin, expectedActivationsPerTest: Int = 5) = {
-        val t = Instant.now
-        val tminus60 = t.minusSeconds(60)
-        val invocationsLast60Seconds = invocationTimes.filter(_.isAfter(tminus60)).sorted
-        val invocationCount = invocationsLast60Seconds.length
-        println(s"Action invokes within last minute: ${invocationCount}")
-
-        if (invocationCount >= maxInvocationsBeforeThrottle) {
-            // Instead of waiting a fixed 60 seconds to settle the throttle,
-            // calculate a wait time that will clear out about half of the
-            // current invocations (assuming even distribution) from the
-            // next 60 second period.
-            val oldestInvocationInLast60Seconds = invocationsLast60Seconds.head
-
-            // Take the oldest invocation time in this 60 second period.  To clear
-            // this invocation from the next 60 second period, the wait time will be
-            // (60sec - oldest invocation's delta time away from the period end).
-            // This will clear all of the invocations from the next period at the
-            // expense of potentially waiting uncessarily long. Instead, this calculation
-            // halves the delta time as a compromise.
-            val throttleTime = 60.seconds.toMillis - ((t.toEpochMilli - oldestInvocationInLast60Seconds.toEpochMilli) / 2)
-            println(s"Waiting ${throttleTime} milliseconds to settle the throttle")
-            Thread.sleep(throttleTime)
-        }
-
-        invocationTimes += Instant.now
+class ApiGwTests extends TestHelpers with WskTestHelpers with BeforeAndAfterEach with BeforeAndAfterAll {
+
+  implicit val wskprops = WskProps()
+  val wsk = new Wsk
+  val clinamespace = wsk.namespace.whois()
+
+  // This test suite makes enough CLI invocations in 60 seconds to trigger the OpenWhisk
+  // throttling restriction.  To avoid CLI failures due to being throttled, track the
+  // CLI invocation calls and when at the throttle limit, pause the next CLI invocation
+  // with exactly enough time to relax the throttling.
+  val maxActionsPerMin = WhiskProperties.getMaxActionInvokesPerMinute()
+  val invocationTimes = new ArrayBuffer[Instant]()
+
+  // Custom CLI properties file
+  val cliWskPropsFile = File.createTempFile("wskprops", ".tmp")
+
+  /**
+   * Expected to be called before each test.
+   * Assumes that each test will not invoke more than 5 actions and
+   * settle the throttle when there isn't enough capacity to handle the test.
+   */
+  def checkThrottle(maxInvocationsBeforeThrottle: Int = maxActionsPerMin, expectedActivationsPerTest: Int = 5) = {
+    val t = Instant.now
+    val tminus60 = t.minusSeconds(60)
+    val invocationsLast60Seconds = invocationTimes.filter(_.isAfter(tminus60)).sorted
+    val invocationCount = invocationsLast60Seconds.length
+    println(s"Action invokes within last minute: ${invocationCount}")
+
+    if (invocationCount >= maxInvocationsBeforeThrottle) {
+      // Instead of waiting a fixed 60 seconds to settle the throttle,
+      // calculate a wait time that will clear out about half of the
+      // current invocations (assuming even distribution) from the
+      // next 60 second period.
+      val oldestInvocationInLast60Seconds = invocationsLast60Seconds.head
+
+      // Take the oldest invocation time in this 60 second period.  To clear
+      // this invocation from the next 60 second period, the wait time will be
+      // (60sec - oldest invocation's delta time away from the period end).
+      // This will clear all of the invocations from the next period at the
+      // expense of potentially waiting uncessarily long. Instead, this calculation
+      // halves the delta time as a compromise.
+      val throttleTime = 60.seconds.toMillis - ((t.toEpochMilli - oldestInvocationInLast60Seconds.toEpochMilli) / 2)
+      println(s"Waiting ${throttleTime} milliseconds to settle the throttle")
+      Thread.sleep(throttleTime)
     }
 
-    override def beforeEach() = {
-        //checkThrottle()
-    }
-
-    /*
-     * Create a CLI properties file for use by the tests
-     */
-    override def beforeAll() = {
-        cliWskPropsFile.deleteOnExit()
-        val wskprops = WskProps(token = "SOME TOKEN")
-        wskprops.writeFile(cliWskPropsFile)
-        println(s"wsk temporary props file created here: ${cliWskPropsFile.getCanonicalPath()}")
-    }
-
-    /*
-     * Forcibly clear the throttle so that downstream tests are not affected by
-     * this test suite
-     */
-    override def afterAll() = {
-        // Check and settle the throttle so that this test won't cause issues with and follow on tests
-        checkThrottle(30)
-    }
-
-    def apiCreate(
-        basepath: Option[String] = None,
-        relpath: Option[String] = None,
-        operation: Option[String] = None,
-        action: Option[String] = None,
-        apiname: Option[String] = None,
-        swagger: Option[String] = None,
-        responsetype: Option[String] = None,
-        expectedExitCode: Int = SUCCESS_EXIT,
-        cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath()))(implicit wskpropsOverride: WskProps): RunResult = {
-
-        checkThrottle()
-        wsk.api.create(basepath, relpath, operation, action, apiname, swagger, responsetype, expectedExitCode, cliCfgFile)(wskpropsOverride)
-    }
-
-    def apiList(
-        basepathOrApiName: Option[String] = None,
-        relpath: Option[String] = None,
-        operation: Option[String] = None,
-        limit: Option[Int] = None,
-        since: Option[Instant] = None,
-        full: Option[Boolean] = None,
-        nameSort: Option[Boolean] = None,
-        expectedExitCode: Int = SUCCESS_EXIT,
-        cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath())): RunResult = {
-
-        checkThrottle()
-        wsk.api.list(basepathOrApiName, relpath, operation, limit, since, full, nameSort, expectedExitCode, cliCfgFile)
-    }
-
-    def apiGet(
-        basepathOrApiName: Option[String] = None,
-        full: Option[Boolean] = None,
-        expectedExitCode: Int = SUCCESS_EXIT,
-        cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath()),
-        format: Option[String] = None): RunResult = {
-
-        checkThrottle()
-        wsk.api.get(basepathOrApiName, full, expectedExitCode, cliCfgFile, format)
-    }
-
-    def apiDelete(
-        basepathOrApiName: String,
-        relpath: Option[String] = None,
-        operation: Option[String] = None,
-        expectedExitCode: Int = SUCCESS_EXIT,
-        cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath())): RunResult = {
-
-        checkThrottle()
-        wsk.api.delete(basepathOrApiName, relpath, operation, expectedExitCode, cliCfgFile)
-    }
-
-    behavior of "Wsk api"
-
-    it should "reject an api commands with an invalid path parameter" in {
-        val badpath = "badpath"
-
-        var rr = apiCreate(basepath = Some("/basepath"), relpath = Some(badpath), operation = Some("GET"), action = Some("action"), expectedExitCode = ANY_ERROR_EXIT)
-        rr.stderr should include(s"'${badpath}' must begin with '/'")
-
-        rr = apiDelete(basepathOrApiName = "/basepath", relpath = Some(badpath), operation = Some("GET"), expectedExitCode = ANY_ERROR_EXIT)
-        rr.stderr should include(s"'${badpath}' must begin with '/'")
-
-        rr = apiList(basepathOrApiName = Some("/basepath"), relpath = Some(badpath), operation = Some("GET"), expectedExitCode = ANY_ERROR_EXIT)
-        rr.stderr should include(s"'${badpath}' must begin with '/'")
-    }
-
-    it should "reject an api commands with an invalid verb parameter" in {
-        val badverb = "badverb"
-
-        var rr = apiCreate(basepath = Some("/basepath"), relpath = Some("/path"), operation = Some(badverb), action = Some("action"), expectedExitCode = ANY_ERROR_EXIT)
-        rr.stderr should include(s"'${badverb}' is not a valid API verb.  Valid values are:")
-
-        rr = apiDelete(basepathOrApiName = "/basepath", relpath = Some("/path"), operation = Some(badverb), expectedExitCode = ANY_ERROR_EXIT)
-        rr.stderr should include(s"'${badverb}' is not a valid API verb.  Valid values are:")
-
-        rr = apiList(basepathOrApiName = Some("/basepath"), relpath = Some("/path"), operation = Some(badverb), expectedExitCode = ANY_ERROR_EXIT)
-        rr.stderr should include(s"'${badverb}' is not a valid API verb.  Valid values are:")
-    }
-
-    it should "reject an api create command that specifies a nonexistent configuration file" in {
-        val configfile = "/nonexistent/file"
-
-        val rr = apiCreate(swagger = Some(configfile), expectedExitCode = ANY_ERROR_EXIT)
-        rr.stderr should include(s"Error reading swagger file '${configfile}':")
-    }
-
-    it should "reject an api create command specifying a non-JSON configuration file" in {
-        val file = File.createTempFile("api.json", ".txt")
-        file.deleteOnExit()
-        val filename = file.getAbsolutePath()
-
-        val bw = new BufferedWriter(new FileWriter(file))
-        bw.write("a=A")
-        bw.close()
-
-        val rr = apiCreate(swagger = Some(filename), expectedExitCode = ANY_ERROR_EXIT)
-        rr.stderr should include(s"Error parsing swagger file '${filename}':")
-    }
-
-    it should "reject an api create command specifying a non-swagger JSON configuration file" in {
-        val file = File.createTempFile("api.json", ".txt")
-        file.deleteOnExit()
-        val filename = file.getAbsolutePath()
-
-        val bw = new BufferedWriter(new FileWriter(file))
-        bw.write("""|{
+    invocationTimes += Instant.now
+  }
+
+  override def beforeEach() = {
+    //checkThrottle()
+  }
+
+  /*
+   * Create a CLI properties file for use by the tests
+   */
+  override def beforeAll() = {
+    cliWskPropsFile.deleteOnExit()
+    val wskprops = WskProps(token = "SOME TOKEN")
+    wskprops.writeFile(cliWskPropsFile)
+    println(s"wsk temporary props file created here: ${cliWskPropsFile.getCanonicalPath()}")
+  }
+
+  /*
+   * Forcibly clear the throttle so that downstream tests are not affected by
+   * this test suite
+   */
+  override def afterAll() = {
+    // Check and settle the throttle so that this test won't cause issues with and follow on tests
+    checkThrottle(30)
+  }
+
+  def apiCreate(basepath: Option[String] = None,
+                relpath: Option[String] = None,
+                operation: Option[String] = None,
+                action: Option[String] = None,
+                apiname: Option[String] = None,
+                swagger: Option[String] = None,
+                responsetype: Option[String] = None,
+                expectedExitCode: Int = SUCCESS_EXIT,
+                cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath()))(
+    implicit wskpropsOverride: WskProps): RunResult = {
+
+    checkThrottle()
+    wsk.api.create(basepath, relpath, operation, action, apiname, swagger, responsetype, expectedExitCode, cliCfgFile)(
+      wskpropsOverride)
+  }
+
+  def apiList(basepathOrApiName: Option[String] = None,
+              relpath: Option[String] = None,
+              operation: Option[String] = None,
+              limit: Option[Int] = None,
+              since: Option[Instant] = None,
+              full: Option[Boolean] = None,
+              nameSort: Option[Boolean] = None,
+              expectedExitCode: Int = SUCCESS_EXIT,
+              cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath())): RunResult = {
+
+    checkThrottle()
+    wsk.api.list(basepathOrApiName, relpath, operation, limit, since, full, nameSort, expectedExitCode, cliCfgFile)
+  }
+
+  def apiGet(basepathOrApiName: Option[String] = None,
+             full: Option[Boolean] = None,
+             expectedExitCode: Int = SUCCESS_EXIT,
+             cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath()),
+             format: Option[String] = None): RunResult = {
+
+    checkThrottle()
+    wsk.api.get(basepathOrApiName, full, expectedExitCode, cliCfgFile, format)
+  }
+
+  def apiDelete(basepathOrApiName: String,
+                relpath: Option[String] = None,
+                operation: Option[String] = None,
+                expectedExitCode: Int = SUCCESS_EXIT,
+                cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath())): RunResult = {
+
+    checkThrottle()
+    wsk.api.delete(basepathOrApiName, relpath, operation, expectedExitCode, cliCfgFile)
+  }
+
+  behavior of "Wsk api"
+
+  it should "reject an api commands with an invalid path parameter" in {
+    val badpath = "badpath"
+
+    var rr = apiCreate(
+      basepath = Some("/basepath"),
+      relpath = Some(badpath),
+      operation = Some("GET"),
+      action = Some("action"),
+      expectedExitCode = ANY_ERROR_EXIT)
+    rr.stderr should include(s"'${badpath}' must begin with '/'")
+
+    rr = apiDelete(
+      basepathOrApiName = "/basepath",
+      relpath = Some(badpath),
+      operation = Some("GET"),
+      expectedExitCode = ANY_ERROR_EXIT)
+    rr.stderr should include(s"'${badpath}' must begin with '/'")
+
+    rr = apiList(
+      basepathOrApiName = Some("/basepath"),
+      relpath = Some(badpath),
+      operation = Some("GET"),
+      expectedExitCode = ANY_ERROR_EXIT)
+    rr.stderr should include(s"'${badpath}' must begin with '/'")
+  }
+
+  it should "reject an api commands with an invalid verb parameter" in {
+    val badverb = "badverb"
+
+    var rr = apiCreate(
+      basepath = Some("/basepath"),
+      relpath = Some("/path"),
+      operation = Some(badverb),
+      action = Some("action"),
+      expectedExitCode = ANY_ERROR_EXIT)
+    rr.stderr should include(s"'${badverb}' is not a valid API verb.  Valid values are:")
+
+    rr = apiDelete(
+      basepathOrApiName = "/basepath",
+      relpath = Some("/path"),
+      operation = Some(badverb),
+      expectedExitCode = ANY_ERROR_EXIT)
+    rr.stderr should include(s"'${badverb}' is not a valid API verb.  Valid values are:")
+
+    rr = apiList(
+      basepathOrApiName = Some("/basepath"),
+      relpath = Some("/path"),
+      operation = Some(badverb),
+      expectedExitCode = ANY_ERROR_EXIT)
+    rr.stderr should include(s"'${badverb}' is not a valid API verb.  Valid values are:")
+  }
+
+  it should "reject an api create command that specifies a nonexistent configuration file" in {
+    val configfile = "/nonexistent/file"
+
+    val rr = apiCreate(swagger = Some(configfile), expectedExitCode = ANY_ERROR_EXIT)
+    rr.stderr should include(s"Error reading swagger file '${configfile}':")
+  }
+
+  it should "reject an api create command specifying a non-JSON configuration file" in {
+    val file = File.createTempFile("api.json", ".txt")
+    file.deleteOnExit()
+    val filename = file.getAbsolutePath()
+
+    val bw = new BufferedWriter(new FileWriter(file))
+    bw.write("a=A")
+    bw.close()
+
+    val rr = apiCreate(swagger = Some(filename), expectedExitCode = ANY_ERROR_EXIT)
+    rr.stderr should include(s"Error parsing swagger file '${filename}':")
+  }
+
+  it should "reject an api create command specifying a non-swagger JSON configuration file" in {
+    val file = File.createTempFile("api.json", ".txt")
+    file.deleteOnExit()
+    val filename = file.getAbsolutePath()
+
+    val bw = new BufferedWriter(new FileWriter(file))
+    bw.write("""|{
                     |   "swagger": "2.0",
                     |   "info": {
                     |      "title": "My API",
@@ -238,706 +258,807 @@ class ApiGwTests
                     |     }
                     |   }
                     |}""".stripMargin)
-        bw.close()
-
-        val rr = apiCreate(swagger = Some(filename), expectedExitCode = ANY_ERROR_EXIT)
-        rr.stderr should include(s"Swagger file is invalid (missing basePath, info, paths, or swagger fields")
+    bw.close()
+
+    val rr = apiCreate(swagger = Some(filename), expectedExitCode = ANY_ERROR_EXIT)
+    rr.stderr should include(s"Swagger file is invalid (missing basePath, info, paths, or swagger fields")
+  }
+
+  it should "verify full list output" in {
+    val testName = "CLI_APIGWTEST_RO1"
+    val testbasepath = "/" + testName + "_bp"
+    val testrelpath = "/path"
+    val testnewrelpath = "/path_new"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val actionName = testName + "_action"
+    try {
+      println("cli namespace: " + clinamespace)
+      // Create the action for the API.  It must be a "web-action" action.
+      val file = TestUtils.getTestActionFilename(s"echo.js")
+      wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+
+      var rr = apiCreate(
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname))
+      println("api create: " + rr.stdout)
+      rr.stdout should include("ok: created API")
+      rr = apiList(
+        basepathOrApiName = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        full = Some(true))
+      println("api list: " + rr.stdout)
+      rr.stdout should include("ok: APIs")
+      rr.stdout should include regex (s"Action:\\s+/${clinamespace}/${actionName}\n")
+      rr.stdout should include regex (s"Verb:\\s+${testurlop}\n")
+      rr.stdout should include regex (s"Base path:\\s+${testbasepath}\n")
+      rr.stdout should include regex (s"Path:\\s+${testrelpath}\n")
+      rr.stdout should include regex (s"API Name:\\s+${testapiname}\n")
+      rr.stdout should include regex (s"URL:\\s+")
+      rr.stdout should include(testbasepath + testrelpath)
+    } finally {
+      wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+      apiDelete(basepathOrApiName = testbasepath)
     }
-
-    it should "verify full list output" in {
-        val testName = "CLI_APIGWTEST_RO1"
-        val testbasepath = "/" + testName + "_bp"
-        val testrelpath = "/path"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val actionName = testName + "_action"
-        try {
-            println("cli namespace: " + clinamespace)
-            // Create the action for the API.  It must be a "web-action" action.
-            val file = TestCLIUtils.getTestActionFilename(s"echo.js")
-            wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
-
-            var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
-            println("api create: " + rr.stdout)
-            rr.stdout should include("ok: created API")
-            rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), full = Some(true))
-            println("api list: " + rr.stdout)
-            rr.stdout should include("ok: APIs")
-            rr.stdout should include regex (s"Action:\\s+/${clinamespace}/${actionName}\n")
-            rr.stdout should include regex (s"Verb:\\s+${testurlop}\n")
-            rr.stdout should include regex (s"Base path:\\s+${testbasepath}\n")
-            rr.stdout should include regex (s"Path:\\s+${testrelpath}\n")
-            rr.stdout should include regex (s"API Name:\\s+${testapiname}\n")
-            rr.stdout should include regex (s"URL:\\s+")
-            rr.stdout should include(testbasepath + testrelpath)
-        } finally {
-            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            apiDelete(basepathOrApiName = testbasepath)
-        }
+  }
+
+  it should "verify successful creation and deletion of a new API" in {
+    val testName = "CLI_APIGWTEST1"
+    val testbasepath = "/" + testName + "_bp"
+    val testrelpath = "/path/with/sub_paths/in/it"
+    val testnewrelpath = "/path_new"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val actionName = testName + "_action"
+    try {
+      println("cli namespace: " + clinamespace)
+
+      // Create the action for the API.  It must be a "web-action" action.
+      val file = TestUtils.getTestActionFilename(s"echo.js")
+      wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+
+      var rr = apiCreate(
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname))
+      rr.stdout should include("ok: created API")
+      rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
+      rr.stdout should include("ok: APIs")
+      rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+      rr.stdout should include(testbasepath + testrelpath)
+      rr = apiGet(basepathOrApiName = Some(testbasepath))
+      rr.stdout should include regex (s""""operationId":\\s+"getPathWithSub_pathsInIt"""")
+      val deleteresult = apiDelete(basepathOrApiName = testbasepath)
+      deleteresult.stdout should include("ok: deleted API")
+    } finally {
+      wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "verify successful creation and deletion of a new API" in {
-        val testName = "CLI_APIGWTEST1"
-        val testbasepath = "/" + testName + "_bp"
-        val testrelpath = "/path/with/sub_paths/in/it"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val actionName = testName + "_action"
-        try {
-            println("cli namespace: " + clinamespace)
-
-            // Create the action for the API.  It must be a "web-action" action.
-            val file = TestCLIUtils.getTestActionFilename(s"echo.js")
-            wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
-
-            var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
-            rr.stdout should include("ok: created API")
-            rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
-            rr.stdout should include("ok: APIs")
-            rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
-            rr.stdout should include(testbasepath + testrelpath)
-            rr = apiGet(basepathOrApiName = Some(testbasepath))
-            rr.stdout should include regex (s""""operationId":\\s+"getPathWithSub_pathsInIt"""")
-            val deleteresult = apiDelete(basepathOrApiName = testbasepath)
-            deleteresult.stdout should include("ok: deleted API")
-        } finally {
-            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-        }
+  }
+
+  it should "verify get API name " in {
+    val testName = "CLI_APIGWTEST3"
+    val testbasepath = "/" + testName + "_bp"
+    val testrelpath = "/path"
+    val testnewrelpath = "/path_new"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val actionName = testName + "_action"
+    try {
+      // Create the action for the API.  It must be a "web-action" action.
+      val file = TestUtils.getTestActionFilename(s"echo.js")
+      wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+
+      var rr = apiCreate(
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname))
+      rr.stdout should include("ok: created API")
+      rr = apiGet(basepathOrApiName = Some(testapiname))
+      rr.stdout should include(testbasepath)
+      rr.stdout should include(s"${actionName}")
+      rr.stdout should include regex (""""cors":\s*\{\s*\n\s*"enabled":\s*true""")
+      rr.stdout should include regex (s""""target-url":\\s+.*${actionName}.json""")
+    } finally {
+      wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "verify get API name " in {
-        val testName = "CLI_APIGWTEST3"
-        val testbasepath = "/" + testName + "_bp"
-        val testrelpath = "/path"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val actionName = testName + "_action"
-        try {
-            // Create the action for the API.  It must be a "web-action" action.
-            val file = TestCLIUtils.getTestActionFilename(s"echo.js")
-            wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
-
-            var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
-            rr.stdout should include("ok: created API")
-            rr = apiGet(basepathOrApiName = Some(testapiname))
-            rr.stdout should include(testbasepath)
-            rr.stdout should include(s"${actionName}")
-            rr.stdout should include regex (""""cors":\s*\{\s*\n\s*"enabled":\s*true""")
-            rr.stdout should include regex (s""""target-url":\\s+.*${actionName}.json""")
-        } finally {
-            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-        }
+  }
+
+  it should "verify delete API name " in {
+    val testName = "CLI_APIGWTEST4"
+    val testbasepath = "/" + testName + "_bp"
+    val testrelpath = "/path"
+    val testnewrelpath = "/path_new"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val actionName = testName + "_action"
+    try {
+      // Create the action for the API.  It must be a "web-action" action.
+      val file = TestUtils.getTestActionFilename(s"echo.js")
+      wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+
+      var rr = apiCreate(
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname))
+      rr.stdout should include("ok: created API")
+      rr = apiDelete(basepathOrApiName = testapiname)
+      rr.stdout should include("ok: deleted API")
+    } finally {
+      wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "verify delete API name " in {
-        val testName = "CLI_APIGWTEST4"
-        val testbasepath = "/" + testName + "_bp"
-        val testrelpath = "/path"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val actionName = testName + "_action"
-        try {
-            // Create the action for the API.  It must be a "web-action" action.
-            val file = TestCLIUtils.getTestActionFilename(s"echo.js")
-            wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
-
-            var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
-            rr.stdout should include("ok: created API")
-            rr = apiDelete(basepathOrApiName = testapiname)
-            rr.stdout should include("ok: deleted API")
-        } finally {
-            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-        }
+  }
+
+  it should "verify delete API basepath " in {
+    val testName = "CLI_APIGWTEST5"
+    val testbasepath = "/" + testName + "_bp"
+    val testrelpath = "/path"
+    val testnewrelpath = "/path_new"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val actionName = testName + "_action"
+    try {
+      // Create the action for the API.  It must be a "web-action" action.
+      val file = TestUtils.getTestActionFilename(s"echo.js")
+      wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+
+      var rr = apiCreate(
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname))
+      rr.stdout should include("ok: created API")
+      rr = apiDelete(basepathOrApiName = testbasepath)
+      rr.stdout should include("ok: deleted API")
+    } finally {
+      wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "verify delete API basepath " in {
-        val testName = "CLI_APIGWTEST5"
-        val testbasepath = "/" + testName + "_bp"
-        val testrelpath = "/path"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val actionName = testName + "_action"
-        try {
-            // Create the action for the API.  It must be a "web-action" action.
-            val file = TestCLIUtils.getTestActionFilename(s"echo.js")
-            wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
-
-            var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
-            rr.stdout should include("ok: created API")
-            rr = apiDelete(basepathOrApiName = testbasepath)
-            rr.stdout should include("ok: deleted API")
-        } finally {
-            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-        }
+  }
+
+  it should "verify adding endpoints to existing api" in {
+    val testName = "CLI_APIGWTEST6"
+    val testbasepath = "/" + testName + "_bp"
+    val testrelpath = "/path2"
+    val testnewrelpath = "/path_new"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val actionName = testName + "_action"
+    val newEndpoint = "/newEndpoint"
+    try {
+      // Create the action for the API.  It must be a "web-action" action.
+      val file = TestUtils.getTestActionFilename(s"echo.js")
+      wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+
+      var rr = apiCreate(
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname))
+      rr.stdout should include("ok: created API")
+      rr = apiCreate(
+        basepath = Some(testbasepath),
+        relpath = Some(newEndpoint),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname))
+      rr.stdout should include("ok: created API")
+      rr = apiList(basepathOrApiName = Some(testbasepath))
+      rr.stdout should include("ok: APIs")
+      rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+      rr.stdout should include(testbasepath + testrelpath)
+      rr.stdout should include(testbasepath + newEndpoint)
+    } finally {
+      wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "verify adding endpoints to existing api" in {
-        val testName = "CLI_APIGWTEST6"
-        val testbasepath = "/" + testName + "_bp"
-        val testrelpath = "/path2"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val actionName = testName + "_action"
-        val newEndpoint = "/newEndpoint"
-        try {
-            // Create the action for the API.  It must be a "web-action" action.
-            val file = TestCLIUtils.getTestActionFilename(s"echo.js")
-            wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
-
-            var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
-            rr.stdout should include("ok: created API")
-            rr = apiCreate(basepath = Some(testbasepath), relpath = Some(newEndpoint), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
-            rr.stdout should include("ok: created API")
-            rr = apiList(basepathOrApiName = Some(testbasepath))
-            rr.stdout should include("ok: APIs")
-            rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
-            rr.stdout should include(testbasepath + testrelpath)
-            rr.stdout should include(testbasepath + newEndpoint)
-        } finally {
-            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-        }
+  }
+
+  it should "verify successful creation with swagger doc as input" in {
+    // NOTE: These values must match the swagger file contents
+    val testName = "CLI_APIGWTEST7"
+    val testbasepath = "/" + testName + "_bp"
+    val testrelpath = "/path"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val actionName = testName + "_action"
+    val swaggerPath = TestUtils.getTestApiGwFilename("testswaggerdoc1")
+    try {
+      var rr = apiCreate(swagger = Some(swaggerPath))
+      rr.stdout should include("ok: created API")
+      rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
+      println("list stdout: " + rr.stdout)
+      println("list stderr: " + rr.stderr)
+      rr.stdout should include("ok: APIs")
+      // Actual CLI namespace will vary from local dev to automated test environments, so don't check
+      rr.stdout should include regex (s"/[@\\w._\\-]+/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+      rr.stdout should include(testbasepath + testrelpath)
+    } finally {
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "verify successful creation with swagger doc as input" in {
-        // NOTE: These values must match the swagger file contents
-        val testName = "CLI_APIGWTEST7"
-        val testbasepath = "/" + testName + "_bp"
-        val testrelpath = "/path"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val actionName = testName + "_action"
-        val swaggerPath = TestCLIUtils.getTestApiGwFilename("testswaggerdoc1")
-        try {
-            var rr = apiCreate(swagger = Some(swaggerPath))
-            rr.stdout should include("ok: created API")
-            rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
-            println("list stdout: " + rr.stdout)
-            println("list stderr: " + rr.stderr)
-            rr.stdout should include("ok: APIs")
-            // Actual CLI namespace will vary from local dev to automated test environments, so don't check
-            rr.stdout should include regex (s"/[@\\w._\\-]+/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
-            rr.stdout should include(testbasepath + testrelpath)
-        } finally {
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-        }
+  }
+
+  it should "verify adding endpoints to two existing apis" in {
+    val testName = "CLI_APIGWTEST8"
+    val testbasepath = "/" + testName + "_bp"
+    val testbasepath2 = "/" + testName + "_bp2"
+    val testrelpath = "/path2"
+    val testnewrelpath = "/path_new"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val testapiname2 = testName + " API Name 2"
+    val actionName = testName + "_action"
+    val newEndpoint = "/newEndpoint"
+    try {
+      // Create the action for the API.  It must be a "web-action" action.
+      val file = TestUtils.getTestActionFilename(s"echo.js")
+      wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+
+      var rr = apiCreate(
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname))
+      rr.stdout should include("ok: created API")
+      rr = apiCreate(
+        basepath = Some(testbasepath2),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname2))
+      rr.stdout should include("ok: created API")
+
+      // Update both APIs - each with a new endpoint
+      rr = apiCreate(
+        basepath = Some(testbasepath),
+        relpath = Some(newEndpoint),
+        operation = Some(testurlop),
+        action = Some(actionName))
+      rr.stdout should include("ok: created API")
+      rr = apiCreate(
+        basepath = Some(testbasepath2),
+        relpath = Some(newEndpoint),
+        operation = Some(testurlop),
+        action = Some(actionName))
+      rr.stdout should include("ok: created API")
+
+      rr = apiList(basepathOrApiName = Some(testbasepath))
+      rr.stdout should include("ok: APIs")
+      rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+      rr.stdout should include(testbasepath + testrelpath)
+      rr.stdout should include(testbasepath + newEndpoint)
+
+      rr = apiList(basepathOrApiName = Some(testbasepath2))
+      rr.stdout should include("ok: APIs")
+      rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+      rr.stdout should include(testbasepath2 + testrelpath)
+      rr.stdout should include(testbasepath2 + newEndpoint)
+    } finally {
+      wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+      apiDelete(basepathOrApiName = testbasepath2, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "verify adding endpoints to two existing apis" in {
-        val testName = "CLI_APIGWTEST8"
-        val testbasepath = "/" + testName + "_bp"
-        val testbasepath2 = "/" + testName + "_bp2"
-        val testrelpath = "/path2"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val testapiname2 = testName + " API Name 2"
-        val actionName = testName + "_action"
-        val newEndpoint = "/newEndpoint"
-        try {
-            // Create the action for the API.  It must be a "web-action" action.
-            val file = TestCLIUtils.getTestActionFilename(s"echo.js")
-            wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
-
-            var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
-            rr.stdout should include("ok: created API")
-            rr = apiCreate(basepath = Some(testbasepath2), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname2))
-            rr.stdout should include("ok: created API")
-
-            // Update both APIs - each with a new endpoint
-            rr = apiCreate(basepath = Some(testbasepath), relpath = Some(newEndpoint), operation = Some(testurlop), action = Some(actionName))
-            rr.stdout should include("ok: created API")
-            rr = apiCreate(basepath = Some(testbasepath2), relpath = Some(newEndpoint), operation = Some(testurlop), action = Some(actionName))
-            rr.stdout should include("ok: created API")
-
-            rr = apiList(basepathOrApiName = Some(testbasepath))
-            rr.stdout should include("ok: APIs")
-            rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
-            rr.stdout should include(testbasepath + testrelpath)
-            rr.stdout should include(testbasepath + newEndpoint)
-
-            rr = apiList(basepathOrApiName = Some(testbasepath2))
-            rr.stdout should include("ok: APIs")
-            rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
-            rr.stdout should include(testbasepath2 + testrelpath)
-            rr.stdout should include(testbasepath2 + newEndpoint)
-        } finally {
-            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-            apiDelete(basepathOrApiName = testbasepath2, expectedExitCode = DONTCARE_EXIT)
-        }
+  }
+
+  it should "verify successful creation of a new API using an action name using all allowed characters" in {
+    // Be aware: full action name is close to being truncated by the 'list' command
+    // e.g. /lime@us.ibm.com/CLI_APIGWTEST9a-c@t ion  is currently at the 40 char 'list' display max
+    val testName = "CLI_APIGWTEST9"
+    val testbasepath = "/" + testName + "_bp"
+    val testrelpath = "/path"
+    val testnewrelpath = "/path_new"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val actionName = testName + "a-c@t ion"
+    try {
+      println("cli namespace: " + clinamespace)
+
+      // Create the action for the API.  It must be a "web-action" action.
+      val file = TestUtils.getTestActionFilename(s"echo.js")
+      wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+
+      var rr = apiCreate(
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname))
+      rr.stdout should include("ok: created API")
+      rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
+      rr.stdout should include("ok: APIs")
+      rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+      rr.stdout should include(testbasepath + testrelpath)
+      val deleteresult = apiDelete(basepathOrApiName = testbasepath)
+      deleteresult.stdout should include("ok: deleted API")
+    } finally {
+      wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "verify successful creation of a new API using an action name using all allowed characters" in {
-        // Be aware: full action name is close to being truncated by the 'list' command
-        // e.g. /lime@us.ibm.com/CLI_APIGWTEST9a-c@t ion  is currently at the 40 char 'list' display max
-        val testName = "CLI_APIGWTEST9"
-        val testbasepath = "/" + testName + "_bp"
-        val testrelpath = "/path"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val actionName = testName + "a-c@t ion"
-        try {
-            println("cli namespace: " + clinamespace)
-
-            // Create the action for the API.  It must be a "web-action" action.
-            val file = TestCLIUtils.getTestActionFilename(s"echo.js")
-            wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
-
-            var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
-            rr.stdout should include("ok: created API")
-            rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
-            rr.stdout should include("ok: APIs")
-            rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
-            rr.stdout should include(testbasepath + testrelpath)
-            val deleteresult = apiDelete(basepathOrApiName = testbasepath)
-            deleteresult.stdout should include("ok: deleted API")
-        } finally {
-            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-        }
+  }
+
+  it should "verify failed creation with invalid swagger doc as input" in {
+    val testName = "CLI_APIGWTEST10"
+    val testbasepath = "/" + testName + "_bp"
+    val testrelpath = "/path"
+    val testnewrelpath = "/path_new"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val actionName = testName + "_action"
+    val swaggerPath = TestUtils.getTestApiGwFilename(s"testswaggerdocinvalid")
+    try {
+      val rr = apiCreate(swagger = Some(swaggerPath), expectedExitCode = ANY_ERROR_EXIT)
+      println("api create stdout: " + rr.stdout)
+      println("api create stderr: " + rr.stderr)
+      rr.stderr should include(s"Swagger file is invalid")
+    } finally {
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "verify failed creation with invalid swagger doc as input" in {
-        val testName = "CLI_APIGWTEST10"
-        val testbasepath = "/" + testName + "_bp"
-        val testrelpath = "/path"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val actionName = testName + "_action"
-        val swaggerPath = TestCLIUtils.getTestApiGwFilename(s"testswaggerdocinvalid")
-        try {
-            val rr = apiCreate(swagger = Some(swaggerPath), expectedExitCode = ANY_ERROR_EXIT)
-            println("api create stdout: " + rr.stdout)
-            println("api create stderr: " + rr.stderr)
-            rr.stderr should include(s"Swagger file is invalid")
-        } finally {
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-        }
+  }
+
+  it should "verify delete basepath/path " in {
+    val testName = "CLI_APIGWTEST11"
+    val testbasepath = "/" + testName + "_bp"
+    val testrelpath = "/path"
+    val testnewrelpath = "/path_new"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val actionName = testName + "_action"
+    try {
+      // Create the action for the API.  It must be a "web-action" action.
+      val file = TestUtils.getTestActionFilename(s"echo.js")
+      wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+
+      var rr = apiCreate(
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname))
+      rr.stdout should include("ok: created API")
+      var rr2 = apiCreate(
+        basepath = Some(testbasepath),
+        relpath = Some(testnewrelpath),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname))
+      rr2.stdout should include("ok: created API")
+      rr = apiDelete(basepathOrApiName = testbasepath, relpath = Some(testrelpath))
+      rr.stdout should include("ok: deleted " + testrelpath + " from " + testbasepath)
+      rr2 = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testnewrelpath))
+      rr2.stdout should include("ok: APIs")
+      rr2.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+      rr2.stdout should include(testbasepath + testnewrelpath)
+    } finally {
+      wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "verify delete basepath/path " in {
-        val testName = "CLI_APIGWTEST11"
-        val testbasepath = "/" + testName + "_bp"
-        val testrelpath = "/path"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val actionName = testName + "_action"
-        try {
-            // Create the action for the API.  It must be a "web-action" action.
-            val file = TestCLIUtils.getTestActionFilename(s"echo.js")
-            wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
-
-            var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
-            rr.stdout should include("ok: created API")
-            var rr2 = apiCreate(basepath = Some(testbasepath), relpath = Some(testnewrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
-            rr2.stdout should include("ok: created API")
-            rr = apiDelete(basepathOrApiName = testbasepath, relpath = Some(testrelpath))
-            rr.stdout should include("ok: deleted " + testrelpath + " from " + testbasepath)
-            rr2 = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testnewrelpath))
-            rr2.stdout should include("ok: APIs")
-            rr2.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
-            rr2.stdout should include(testbasepath + testnewrelpath)
-        } finally {
-            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-        }
+  }
+
+  it should "verify delete single operation from existing API basepath/path/operation(s) " in {
+    val testName = "CLI_APIGWTEST12"
+    val testbasepath = "/" + testName + "_bp"
+    val testrelpath = "/path2"
+    val testnewrelpath = "/path_new"
+    val testurlop = "get"
+    val testurlop2 = "post"
+    val testapiname = testName + " API Name"
+    val actionName = testName + "_action"
+    try {
+      // Create the action for the API.  It must be a "web-action" action.
+      val file = TestUtils.getTestActionFilename(s"echo.js")
+      wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+
+      var rr = apiCreate(
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname))
+      rr.stdout should include("ok: created API")
+      rr = apiCreate(
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop2),
+        action = Some(actionName),
+        apiname = Some(testapiname))
+      rr.stdout should include("ok: created API")
+      rr = apiList(basepathOrApiName = Some(testbasepath))
+      rr.stdout should include("ok: APIs")
+      rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+      rr.stdout should include(testbasepath + testrelpath)
+      rr = apiDelete(basepathOrApiName = testbasepath, relpath = Some(testrelpath), operation = Some(testurlop2))
+      rr.stdout should include("ok: deleted " + testrelpath + " " + "POST" + " from " + testbasepath)
+      rr = apiList(basepathOrApiName = Some(testbasepath))
+      rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+    } finally {
+      wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "verify delete single operation from existing API basepath/path/operation(s) " in {
-        val testName = "CLI_APIGWTEST12"
-        val testbasepath = "/" + testName + "_bp"
-        val testrelpath = "/path2"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testurlop2 = "post"
-        val testapiname = testName + " API Name"
-        val actionName = testName + "_action"
-        try {
-            // Create the action for the API.  It must be a "web-action" action.
-            val file = TestCLIUtils.getTestActionFilename(s"echo.js")
-            wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
-
-            var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
-            rr.stdout should include("ok: created API")
-            rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop2), action = Some(actionName), apiname = Some(testapiname))
-            rr.stdout should include("ok: created API")
-            rr = apiList(basepathOrApiName = Some(testbasepath))
-            rr.stdout should include("ok: APIs")
-            rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
-            rr.stdout should include(testbasepath + testrelpath)
-            rr = apiDelete(basepathOrApiName = testbasepath, relpath = Some(testrelpath), operation = Some(testurlop2))
-            rr.stdout should include("ok: deleted " + testrelpath + " " + "POST" + " from " + testbasepath)
-            rr = apiList(basepathOrApiName = Some(testbasepath))
-            rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
-        } finally {
-            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-        }
+  }
+
+  it should "verify successful creation with complex swagger doc as input" in {
+    val testName = "CLI_APIGWTEST13"
+    val testbasepath = "/test1/v1"
+    val testrelpath = "/whisk_system/utils/echo"
+    val testrelpath2 = "/whisk_system/utils/split"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val actionName = "test1a"
+    val swaggerPath = TestUtils.getTestApiGwFilename(s"testswaggerdoc2")
+    try {
+      var rr = apiCreate(swagger = Some(swaggerPath))
+      println("api create stdout: " + rr.stdout)
+      println("api create stderror: " + rr.stderr)
+      rr.stdout should include("ok: created API")
+      rr = apiList(basepathOrApiName = Some(testbasepath))
+      rr.stdout should include("ok: APIs")
+      // Actual CLI namespace will vary from local dev to automated test environments, so don't check
+      rr.stdout should include regex (s"/[@\\w._\\-]+/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+      rr.stdout should include(testbasepath + testrelpath)
+      rr.stdout should include(testbasepath + testrelpath2)
+    } finally {
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "verify successful creation with complex swagger doc as input" in {
-        val testName = "CLI_APIGWTEST13"
-        val testbasepath = "/test1/v1"
-        val testrelpath = "/whisk_system/utils/echo"
-        val testrelpath2 = "/whisk_system/utils/split"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val actionName = "test1a"
-        val swaggerPath = TestCLIUtils.getTestApiGwFilename(s"testswaggerdoc2")
-        try {
-            var rr = apiCreate(swagger = Some(swaggerPath))
-            println("api create stdout: " + rr.stdout)
-            println("api create stderror: " + rr.stderr)
-            rr.stdout should include("ok: created API")
-            rr = apiList(basepathOrApiName = Some(testbasepath))
-            rr.stdout should include("ok: APIs")
-            // Actual CLI namespace will vary from local dev to automated test environments, so don't check
-            rr.stdout should include regex (s"/[@\\w._\\-]+/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
-            rr.stdout should include(testbasepath + testrelpath)
-            rr.stdout should include(testbasepath + testrelpath2)
-        } finally {
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-        }
+  }
+
+  it should "verify successful creation and deletion with multiple base paths" in {
+    val testName = "CLI_APIGWTEST14"
+    val testbasepath = "/" + testName + "_bp"
+    val testbasepath2 = "/" + testName + "_bp2"
+    val testrelpath = "/path"
+    val testnewrelpath = "/path_new"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val testapiname2 = testName + " API Name 2"
+    val actionName = testName + "_action"
+    try {
+      // Create the action for the API.  It must be a "web-action" action.
+      val file = TestUtils.getTestActionFilename(s"echo.js")
+      wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+
+      var rr = apiCreate(
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname))
+      rr.stdout should include("ok: created API")
+      rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
+      rr.stdout should include("ok: APIs")
+      rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+      rr.stdout should include(testbasepath + testrelpath)
+      rr = apiCreate(
+        basepath = Some(testbasepath2),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname2))
+      rr.stdout should include("ok: created API")
+      rr = apiList(basepathOrApiName = Some(testbasepath2), relpath = Some(testrelpath), operation = Some(testurlop))
+      rr.stdout should include("ok: APIs")
+      rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+      rr.stdout should include(testbasepath2 + testrelpath)
+      rr = apiDelete(basepathOrApiName = testbasepath2)
+      rr.stdout should include("ok: deleted API")
+      rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
+      rr.stdout should include("ok: APIs")
+      rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+      rr.stdout should include(testbasepath + testrelpath)
+      rr = apiDelete(basepathOrApiName = testbasepath)
+      rr.stdout should include("ok: deleted API")
+    } finally {
+      wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+      apiDelete(basepathOrApiName = testbasepath2, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "verify successful creation and deletion with multiple base paths" in {
-        val testName = "CLI_APIGWTEST14"
-        val testbasepath = "/" + testName + "_bp"
-        val testbasepath2 = "/" + testName + "_bp2"
-        val testrelpath = "/path"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val testapiname2 = testName + " API Name 2"
-        val actionName = testName + "_action"
-        try {
-            // Create the action for the API.  It must be a "web-action" action.
-            val file = TestCLIUtils.getTestActionFilename(s"echo.js")
-            wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
-
-            var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
-            rr.stdout should include("ok: created API")
-            rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
-            rr.stdout should include("ok: APIs")
-            rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
-            rr.stdout should include(testbasepath + testrelpath)
-            rr = apiCreate(basepath = Some(testbasepath2), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname2))
-            rr.stdout should include("ok: created API")
-            rr = apiList(basepathOrApiName = Some(testbasepath2), relpath = Some(testrelpath), operation = Some(testurlop))
-            rr.stdout should include("ok: APIs")
-            rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
-            rr.stdout should include(testbasepath2 + testrelpath)
-            rr = apiDelete(basepathOrApiName = testbasepath2)
-            rr.stdout should include("ok: deleted API")
-            rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
-            rr.stdout should include("ok: APIs")
-            rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
-            rr.stdout should include(testbasepath + testrelpath)
-            rr = apiDelete(basepathOrApiName = testbasepath)
-            rr.stdout should include("ok: deleted API")
-        } finally {
-            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-            apiDelete(basepathOrApiName = testbasepath2, expectedExitCode = DONTCARE_EXIT)
-        }
+  }
+
+  it should "reject an API created with a non-existent action" in {
+    val testName = "CLI_APIGWTEST15"
+    val testbasepath = "/" + testName + "_bp"
+    val testrelpath = "/path"
+    val testnewrelpath = "/path_new"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val actionName = testName + "_action"
+    try {
+      val rr = apiCreate(
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname),
+        expectedExitCode = ANY_ERROR_EXIT)
+      rr.stderr should include("does not exist")
+    } finally {
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "reject an API created with a non-existent action" in {
-        val testName = "CLI_APIGWTEST15"
-        val testbasepath = "/" + testName + "_bp"
-        val testrelpath = "/path"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val actionName = testName + "_action"
-        try {
-            val rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname), expectedExitCode = ANY_ERROR_EXIT)
-            rr.stderr should include("does not exist")
-        } finally {
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-        }
+  }
+
+  it should "reject an API created with an action that is not a web action" in {
+    val testName = "CLI_APIGWTEST16"
+    val testbasepath = "/" + testName + "_bp"
+    val testrelpath = "/path"
+    val testnewrelpath = "/path_new"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val actionName = testName + "_action"
+    try {
+      // Create the action for the API.  It must NOT be a "web-action" action for this test
+      val file = TestUtils.getTestActionFilename(s"echo.js")
+      wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT)
+
+      val rr = apiCreate(
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname),
+        expectedExitCode = ANY_ERROR_EXIT)
+      rr.stderr should include("is not a web action")
+    } finally {
+      wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "reject an API created with an action that is not a web action" in {
-        val testName = "CLI_APIGWTEST16"
-        val testbasepath = "/" + testName + "_bp"
-        val testrelpath = "/path"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val actionName = testName + "_action"
-        try {
-            // Create the action for the API.  It must NOT be a "web-action" action for this test
-            val file = TestCLIUtils.getTestActionFilename(s"echo.js")
-            wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT)
-
-            val rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname), expectedExitCode = ANY_ERROR_EXIT)
-            rr.stderr should include("is not a web action")
-        } finally {
-            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-        }
-    }
-
-    it should "verify API with http response type " in {
-        val testName = "CLI_APIGWTEST17"
-        val testbasepath = "/" + testName + "_bp"
-        val testrelpath = "/path"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val actionName = testName + "_action"
-        val responseType = "http"
-        try {
-            // Create the action for the API.  It must be a "web-action" action.
-            val file = TestCLIUtils.getTestActionFilename(s"echo.js")
-            wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
-
-            apiCreate(
-                basepath = Some(testbasepath),
-                relpath = Some(testrelpath),
-                operation = Some(testurlop),
-                action = Some(actionName),
-                apiname = Some(testapiname),
-                responsetype = Some(responseType))
-                .stdout should include("ok: created API")
-
-            val rr = apiGet(basepathOrApiName = Some(testapiname))
-            rr.stdout should include(testbasepath)
-            rr.stdout should include(s"${actionName}")
-            rr.stdout should include regex (s""""target-url":\\s+.*${actionName}.${responseType}""")
-        } finally {
-            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-        }
-    }
-
-    it should "reject API export when export type is invalid" in {
-        val testName = "CLI_APIGWTEST18"
-        val testbasepath = "/" + testName + "_bp"
-
-        val rr = apiGet(basepathOrApiName = Some(testbasepath), format = Some("BadType"), expectedExitCode = ANY_ERROR_EXIT)
-        rr.stderr should include("Invalid format type")
-    }
-
-    it should "successfully export an API in YAML format" in {
-        val testName = "CLI_APIGWTEST19"
-        val testbasepath = "/" + testName + "_bp"
-        val testrelpath = "/path"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val actionName = testName + "_action"
-        val responseType = "http"
-        try {
-            // Create the action for the API.  It must be a "web-action" action.
-            val file = TestCLIUtils.getTestActionFilename(s"echo.js")
-            wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
-
-            apiCreate(
-                basepath = Some(testbasepath),
-                relpath = Some(testrelpath),
-                operation = Some(testurlop),
-                action = Some(actionName),
-                apiname = Some(testapiname),
-                responsetype = Some(responseType))
-                .stdout should include("ok: created API")
-
-            val rr = apiGet(basepathOrApiName = Some(testapiname), format = Some("yaml"))
-            rr.stdout should include(s"basePath: ${testbasepath}")
-        } finally {
-            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-        }
+  }
+
+  it should "verify API with http response type " in {
+    val testName = "CLI_APIGWTEST17"
+    val testbasepath = "/" + testName + "_bp"
+    val testrelpath = "/path"
+    val testnewrelpath = "/path_new"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val actionName = testName + "_action"
+    val responseType = "http"
+    try {
+      // Create the action for the API.  It must be a "web-action" action.
+      val file = TestUtils.getTestActionFilename(s"echo.js")
+      wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+
+      apiCreate(
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname),
+        responsetype = Some(responseType)).stdout should include("ok: created API")
+
+      val rr = apiGet(basepathOrApiName = Some(testapiname))
+      rr.stdout should include(testbasepath)
+      rr.stdout should include(s"${actionName}")
+      rr.stdout should include regex (s""""target-url":\\s+.*${actionName}.${responseType}""")
+    } finally {
+      wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "successfully export an API when JSON format is explcitly specified" in {
-        val testName = "CLI_APIGWTEST20"
-        val testbasepath = "/" + testName + "_bp"
-        val testrelpath = "/path"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val actionName = testName + "_action"
-        val responseType = "http"
-        try {
-            // Create the action for the API.  It must be a "web-action" action.
-            val file = TestCLIUtils.getTestActionFilename(s"echo.js")
-            wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
-
-            apiCreate(
-                basepath = Some(testbasepath),
-                relpath = Some(testrelpath),
-                operation = Some(testurlop),
-                action = Some(actionName),
-                apiname = Some(testapiname),
-                responsetype = Some(responseType))
-                .stdout should include("ok: created API")
-
-            val rr = apiGet(basepathOrApiName = Some(testapiname), format = Some("json"))
-            rr.stdout should include(testbasepath)
-            rr.stdout should include(s"${actionName}")
-            rr.stdout should include regex (s""""target-url":\\s+.*${actionName}.${responseType}""")
-        } finally {
-            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-        }
+  }
+
+  it should "reject API export when export type is invalid" in {
+    val testName = "CLI_APIGWTEST18"
+    val testbasepath = "/" + testName + "_bp"
+
+    val rr = apiGet(basepathOrApiName = Some(testbasepath), format = Some("BadType"), expectedExitCode = ANY_ERROR_EXIT)
+    rr.stderr should include("Invalid format type")
+  }
+
+  it should "successfully export an API in YAML format" in {
+    val testName = "CLI_APIGWTEST19"
+    val testbasepath = "/" + testName + "_bp"
+    val testrelpath = "/path"
+    val testnewrelpath = "/path_new"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val actionName = testName + "_action"
+    val responseType = "http"
+    try {
+      // Create the action for the API.  It must be a "web-action" action.
+      val file = TestUtils.getTestActionFilename(s"echo.js")
+      wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+
+      apiCreate(
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname),
+        responsetype = Some(responseType)).stdout should include("ok: created API")
+
+      val rr = apiGet(basepathOrApiName = Some(testapiname), format = Some("yaml"))
+      rr.stdout should include(s"basePath: ${testbasepath}")
+    } finally {
+      wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "successfully create an API from a YAML formatted API configuration file" in {
-        val testName = "CLI_APIGWTEST21"
-        val testbasepath = "/bp"
-        val testrelpath = "/rp"
-        val testurlop = "get"
-        val testapiname = testbasepath
-        val actionName = "webhttpecho"
-        val swaggerPath = TestCLIUtils.getTestApiGwFilename(s"local.api.yaml")
-        try {
-            var rr = apiCreate(swagger = Some(swaggerPath))
-            println("api create stdout: " + rr.stdout)
-            println("api create stderror: " + rr.stderr)
-            rr.stdout should include("ok: created API")
-            rr = apiList(basepathOrApiName = Some(testbasepath))
-            rr.stdout should include("ok: APIs")
-            // Actual CLI namespace will vary from local dev to automated test environments, so don't check
-            rr.stdout should include regex (s"/[@\\w._\\-]+/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
-            rr.stdout should include(testbasepath + testrelpath)
-        } finally {
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-        }
+  }
+
+  it should "successfully export an API when JSON format is explcitly specified" in {
+    val testName = "CLI_APIGWTEST20"
+    val testbasepath = "/" + testName + "_bp"
+    val testrelpath = "/path"
+    val testnewrelpath = "/path_new"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val actionName = testName + "_action"
+    val responseType = "http"
+    try {
+      // Create the action for the API.  It must be a "web-action" action.
+      val file = TestUtils.getTestActionFilename(s"echo.js")
+      wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+
+      apiCreate(
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname),
+        responsetype = Some(responseType)).stdout should include("ok: created API")
+
+      val rr = apiGet(basepathOrApiName = Some(testapiname), format = Some("json"))
+      rr.stdout should include(testbasepath)
+      rr.stdout should include(s"${actionName}")
+      rr.stdout should include regex (s""""target-url":\\s+.*${actionName}.${responseType}""")
+    } finally {
+      wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "reject creation of an API from invalid YAML formatted API configuration file" in {
-        val testName = "CLI_APIGWTEST22"
-        val testbasepath = "/" + testName + "_bp"
-        val swaggerPath = TestCLIUtils.getTestApiGwFilename(s"local.api.bad.yaml")
-        try {
-            val rr = apiCreate(swagger = Some(swaggerPath), expectedExitCode = ANY_ERROR_EXIT)
-            println("api create stdout: " + rr.stdout)
-            println("api create stderror: " + rr.stderr)
-            rr.stderr should include("Unable to parse YAML configuration file")
-        } finally {
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-        }
+  }
+
+  it should "successfully create an API from a YAML formatted API configuration file" in {
+    val testName = "CLI_APIGWTEST21"
+    val testbasepath = "/bp"
+    val testrelpath = "/rp"
+    val testurlop = "get"
+    val testapiname = testbasepath
+    val actionName = "webhttpecho"
+    val swaggerPath = TestUtils.getTestApiGwFilename(s"local.api.yaml")
+    try {
+      var rr = apiCreate(swagger = Some(swaggerPath))
+      println("api create stdout: " + rr.stdout)
+      println("api create stderror: " + rr.stderr)
+      rr.stdout should include("ok: created API")
+      rr = apiList(basepathOrApiName = Some(testbasepath))
+      rr.stdout should include("ok: APIs")
+      // Actual CLI namespace will vary from local dev to automated test environments, so don't check
+      rr.stdout should include regex (s"/[@\\w._\\-]+/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+      rr.stdout should include(testbasepath + testrelpath)
+    } finally {
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "reject deletion of a non-existent api" in {
-        val nonexistentApi = "/not-there"
-
-        val rr = apiDelete(basepathOrApiName = nonexistentApi, expectedExitCode = ANY_ERROR_EXIT)
-        rr.stderr should include(s"API '${nonexistentApi}' does not exist")
+  }
+
+  it should "reject creation of an API from invalid YAML formatted API configuration file" in {
+    val testName = "CLI_APIGWTEST22"
+    val testbasepath = "/" + testName + "_bp"
+    val swaggerPath = TestUtils.getTestApiGwFilename(s"local.api.bad.yaml")
+    try {
+      val rr = apiCreate(swagger = Some(swaggerPath), expectedExitCode = ANY_ERROR_EXIT)
+      println("api create stdout: " + rr.stdout)
+      println("api create stderror: " + rr.stderr)
+      rr.stderr should include("Unable to parse YAML configuration file")
+    } finally {
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "successfully list an API whose endpoints are not mapped to actions" in {
-        val testName = "CLI_APIGWTEST23"
-        val testapiname = "A descriptive name"
-        val testbasepath = "/NoActions"
-        val testrelpath = "/"
-        val testops: Seq[String] = Seq("put", "delete", "get", "head", "options", "patch", "post")
-        val swaggerPath = TestCLIUtils.getTestApiGwFilename(s"endpoints.without.action.swagger.json")
-
-        try {
-            var rr = apiCreate(swagger = Some(swaggerPath))
-            println("api create stdout: " + rr.stdout)
-            println("api create stderror: " + rr.stderr)
-            rr.stdout should include("ok: created API")
-
-            rr = apiList(basepathOrApiName = Some(testbasepath))
-            println("api list:\n" + rr.stdout)
-            testops foreach { testurlop =>
-                rr.stdout should include regex (s"\\s+${testurlop}\\s+${testapiname}\\s+")
-            }
-            rr.stdout should include(testbasepath + testrelpath)
-
-            rr = apiList(basepathOrApiName = Some(testbasepath), full = Some(true))
-            println("api full list:\n" + rr.stdout)
-            testops foreach { testurlop =>
-                rr.stdout should include regex (s"Verb:\\s+${testurlop}")
-            }
-            rr.stdout should include(testbasepath + testrelpath)
-
-        } finally {
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-        }
+  }
+
+  it should "reject deletion of a non-existent api" in {
+    val nonexistentApi = "/not-there"
+
+    val rr = apiDelete(basepathOrApiName = nonexistentApi, expectedExitCode = ANY_ERROR_EXIT)
+    rr.stderr should include(s"API '${nonexistentApi}' does not exist")
+  }
+
+  it should "successfully list an API whose endpoints are not mapped to actions" in {
+    val testName = "CLI_APIGWTEST23"
+    val testapiname = "A descriptive name"
+    val testbasepath = "/NoActions"
+    val testrelpath = "/"
+    val testops: Seq[String] = Seq("put", "delete", "get", "head", "options", "patch", "post")
+    val swaggerPath = TestUtils.getTestApiGwFilename(s"endpoints.without.action.swagger.json")
+
+    try {
+      var rr = apiCreate(swagger = Some(swaggerPath))
+      println("api create stdout: " + rr.stdout)
+      println("api create stderror: " + rr.stderr)
+      rr.stdout should include("ok: created API")
+
+      rr = apiList(basepathOrApiName = Some(testbasepath))
+      println("api list:\n" + rr.stdout)
+      testops foreach { testurlop =>
+        rr.stdout should include regex (s"\\s+${testurlop}\\s+${testapiname}\\s+")
+      }
+      rr.stdout should include(testbasepath + testrelpath)
+
+      rr = apiList(basepathOrApiName = Some(testbasepath), full = Some(true))
+      println("api full list:\n" + rr.stdout)
+      testops foreach { testurlop =>
+        rr.stdout should include regex (s"Verb:\\s+${testurlop}")
+      }
+      rr.stdout should include(testbasepath + testrelpath)
+
+    } finally {
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "reject creation of an API with invalid auth key" in {
-        val testName = "CLI_APIGWTEST24"
-        val testbasepath = "/" + testName + "_bp"
-        val testrelpath = "/path"
-        val testurlop = "get"
-        val testapiname = testName + " API Name"
-        val actionName = testName + "_action"
-
-        try {
-            // Create the action for the API.
-            val file = TestCLIUtils.getTestActionFilename(s"echo.js")
-            wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
-
-            // Set an invalid auth key
-            val badWskProps = WskProps(authKey = "bad-auth-key")
-
-            apiCreate(
-                basepath = Some(testbasepath),
-                relpath = Some(testrelpath),
-                operation = Some(testurlop),
-                action = Some(actionName),
-                apiname = Some(testapiname),
-                expectedExitCode = ANY_ERROR_EXIT)(badWskProps)
-                .stderr should include("The supplied authentication is invalid")
-        } finally {
-            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-            apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
-        }
+  }
+
+  it should "reject creation of an API with invalid auth key" in {
+    val testName = "CLI_APIGWTEST24"
+    val testbasepath = "/" + testName + "_bp"
+    val testrelpath = "/path"
+    val testurlop = "get"
+    val testapiname = testName + " API Name"
+    val actionName = testName + "_action"
+
+    try {
+      // Create the action for the API.
+      val file = TestUtils.getTestActionFilename(s"echo.js")
+      wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+
+      // Set an invalid auth key
+      val badWskProps = WskProps(authKey = "bad-auth-key")
+
+      apiCreate(
+        basepath = Some(testbasepath),
+        relpath = Some(testrelpath),
+        operation = Some(testurlop),
+        action = Some(actionName),
+        apiname = Some(testapiname),
+        expectedExitCode = ANY_ERROR_EXIT)(badWskProps).stderr should include("The supplied authentication is invalid")
+    } finally {
+      wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
+      apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
     }
-
-    it should "list api alphabetically by Base/Rel/Verb" in {
-        val baseName = "/BaseTestPathApiList"
-        val actionName = "actionName"
-        val file = TestCLIUtils.getTestActionFilename(s"echo-web-http.js")
-        try {
-            // Create Action for apis
-            var action = wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
-            println("action creation: " + action.stdout)
-            // Create apis
-            for (i <- 1 to 3) {
-                val base = s"$baseName$i"
-                var api = apiCreate(
-                    basepath = Some(base),
-                    relpath = Some("/relPath"),
-                    operation = Some("GET"),
-                    action = Some(actionName))
-                println("api creation: " + api.stdout)
-            }
-            val original = apiList(nameSort = Some(true)).stdout
-            val originalFull = apiList(full = Some(true), nameSort = Some(true)).stdout
-            val scalaSorted = List(s"${baseName}1" + "/", s"${baseName}2" + "/", s"${baseName}3" + "/")
-            val regex = s"${baseName}[1-3]/".r
-            val list = (regex.findAllMatchIn(original)).toList
-            val listFull = (regex.findAllMatchIn(originalFull)).toList
-
-            scalaSorted.toString shouldEqual list.toString
-            scalaSorted.toString shouldEqual listFull.toString
-        } finally {
-            // Clean up Apis
-            for (i <- 1 to 3) {
-                apiDelete(basepathOrApiName = s"${baseName}$i", expectedExitCode = DONTCARE_EXIT)
-            }
-            wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
-        }
+  }
+
+  it should "list api alphabetically by Base/Rel/Verb" in {
+    val baseName = "/BaseTestPathApiList"
+    val actionName = "actionName"
+    val file = TestUtils.getTestActionFilename(s"echo-web-http.js")
+    try {
+      // Create Action for apis
+      var action =
+        wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true"))
+      println("action creation: " + action.stdout)
+      // Create apis
+      for (i <- 1 to 3) {
+        val base = s"$baseName$i"
+        var api = apiCreate(
+          basepath = Some(base),
+          relpath = Some("/relPath"),
+          operation = Some("GET"),
+          action = Some(actionName))
+        println("api creation: " + api.stdout)
+      }
+      val original = apiList(nameSort = Some(true)).stdout
+      val originalFull = apiList(full = Some(true), nameSort = Some(true)).stdout
+      val scalaSorted = List(s"${baseName}1" + "/", s"${baseName}2" + "/", s"${baseName}3" + "/")
+      val regex = s"${baseName}[1-3]/".r
+      val list = (regex.findAllMatchIn(original)).toList
+      val listFull = (regex.findAllMatchIn(originalFull)).toList
+
+      scalaSorted.toString shouldEqual list.toString
+      scalaSorted.toString shouldEqual listFull.toString
+    } finally {
+      // Clean up Apis
+      for (i <- 1 to 3) {
+        apiDelete(basepathOrApiName = s"${baseName}$i", expectedExitCode = DONTCARE_EXIT)
+      }
+      wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT)
     }
+  }
 }
diff --git a/tests/src/test/scala/whisk/core/cli/test/WskActionSequenceTests.scala b/tests/src/test/scala/whisk/core/cli/test/WskActionSequenceTests.scala
index 84d4a82..f48d0ac 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskActionSequenceTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskActionSequenceTests.scala
@@ -32,55 +32,54 @@ import whisk.core.entity.EntityPath
  * Tests creation and retrieval of a sequence action
  */
 @RunWith(classOf[JUnitRunner])
-class WskActionSequenceTests
-    extends TestHelpers
-    with WskTestHelpers {
+class WskActionSequenceTests extends TestHelpers with WskTestHelpers {
 
-    implicit val wskprops = WskProps()
-    val wsk = new Wsk
-    val defaultNamespace = EntityPath.DEFAULT.asString
-    val namespace = wsk.namespace.whois()
+  implicit val wskprops = WskProps()
+  val wsk = new Wsk
+  val defaultNamespace = EntityPath.DEFAULT.asString
+  val namespace = wsk.namespace.whois()
 
-    behavior of "Wsk Action Sequence"
+  behavior of "Wsk Action Sequence"
 
-    it should "create, and get an action sequence" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "actionSeq"
-            val packageName = "samples"
-            val helloName = "hello"
-            val catName = "cat"
-            val fullHelloActionName = s"/$defaultNamespace/$packageName/$helloName"
-            val fullCatActionName = s"/$defaultNamespace/$packageName/$catName"
+  it should "create, and get an action sequence" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "actionSeq"
+    val packageName = "samples"
+    val helloName = "hello"
+    val catName = "cat"
+    val fullHelloActionName = s"/$defaultNamespace/$packageName/$helloName"
+    val fullCatActionName = s"/$defaultNamespace/$packageName/$catName"
 
-            assetHelper.withCleaner(wsk.pkg, packageName) {
-                (pkg, _) => pkg.create(packageName, shared = Some(true))(wp)
-            }
-
-            assetHelper.withCleaner(wsk.action, fullHelloActionName) {
-                val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
-                (action, _) => action.create(fullHelloActionName, file)(wp)
-            }
+    assetHelper.withCleaner(wsk.pkg, packageName) { (pkg, _) =>
+      pkg.create(packageName, shared = Some(true))(wp)
+    }
 
-            assetHelper.withCleaner(wsk.action, fullCatActionName) {
-                val file = Some(TestCLIUtils.getTestActionFilename("cat.js"))
-                (action, _) => action.create(fullCatActionName, file)(wp)
-            }
+    assetHelper.withCleaner(wsk.action, fullHelloActionName) {
+      val file = Some(TestUtils.getTestActionFilename("hello.js"))
+      (action, _) =>
+        action.create(fullHelloActionName, file)(wp)
+    }
 
-            val artifacts = s"$fullHelloActionName,$fullCatActionName"
-            val kindValue = JsString("sequence")
-            val compValue = JsArray(
-                JsString(resolveDefaultNamespace(fullHelloActionName)),
-                JsString(resolveDefaultNamespace(fullCatActionName)))
+    assetHelper.withCleaner(wsk.action, fullCatActionName) {
+      val file = Some(TestUtils.getTestActionFilename("cat.js"))
+      (action, _) =>
+        action.create(fullCatActionName, file)(wp)
+    }
 
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(artifacts), kind = Some("sequence"))
-            }
+    val artifacts = s"$fullHelloActionName,$fullCatActionName"
+    val kindValue = JsString("sequence")
+    val compValue = JsArray(
+      JsString(resolveDefaultNamespace(fullHelloActionName)),
+      JsString(resolveDefaultNamespace(fullCatActionName)))
 
-            val stdout = wsk.action.get(name).stdout
-            assert(stdout.startsWith(s"ok: got action $name\n"))
-            wsk.parseJsonString(stdout).fields("exec").asJsObject.fields("components") shouldBe compValue
-            wsk.parseJsonString(stdout).fields("exec").asJsObject.fields("kind") shouldBe kindValue
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, Some(artifacts), kind = Some("sequence"))
     }
 
-    private def resolveDefaultNamespace(actionName: String) = actionName.replace("/_/", s"/$namespace/")
+    val stdout = wsk.action.get(name).stdout
+    assert(stdout.startsWith(s"ok: got action $name\n"))
+    wsk.parseJsonString(stdout).fields("exec").asJsObject.fields("components") shouldBe compValue
+    wsk.parseJsonString(stdout).fields("exec").asJsObject.fields("kind") shouldBe kindValue
+  }
+
+  private def resolveDefaultNamespace(actionName: String) = actionName.replace("/_/", s"/$namespace/")
 }
diff --git a/tests/src/test/scala/whisk/core/cli/test/WskBasicUsageTests.scala b/tests/src/test/scala/whisk/core/cli/test/WskBasicUsageTests.scala
index f14a092..03b4fc3 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskBasicUsageTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskBasicUsageTests.scala
@@ -53,1375 +53,354 @@ import whisk.http.Messages
  * Tests for basic CLI usage. Some of these tests require a deployed backend.
  */
 @RunWith(classOf[JUnitRunner])
-class WskBasicUsageTests
-    extends TestHelpers
-    with WskTestHelpers {
-
-    implicit val wskprops = WskProps()
-    val wsk = new Wsk
-    val defaultAction = Some(TestCLIUtils.getTestActionFilename("hello.js"))
-
-    behavior of "Wsk CLI usage"
-
-    it should "show help and usage info" in {
-        val stdout = wsk.cli(Seq()).stdout
-        stdout should include regex ("""(?i)Usage:""")
-        stdout should include regex ("""(?i)Flags""")
-        stdout should include regex ("""(?i)Available commands""")
-        stdout should include regex ("""(?i)--help""")
-    }
-
-    it should "show help and usage info using the default language" in {
-        val env = Map("LANG" -> "de_DE")
-        // Call will fail with exit code 2 if language not supported
-        wsk.cli(Seq("-h"), env = env)
-    }
-
-    it should "show cli build version" in {
-        val stdout = wsk.cli(Seq("property", "get", "--cliversion")).stdout
-        stdout should include regex ("""(?i)whisk CLI version\s+201.*""")
-    }
-
-    it should "show api version" in {
-        val stdout = wsk.cli(Seq("property", "get", "--apiversion")).stdout
-        stdout should include regex ("""(?i)whisk API version\s+v1""")
-    }
-
-    it should "reject bad command" in {
-        val result = wsk.cli(Seq("bogus"), expectedExitCode = ERROR_EXIT)
-        result.stderr should include regex ("""(?i)Run 'wsk --help' for usage""")
-    }
-
-    it should "allow a 3 part Fully Qualified Name (FQN) without a leading '/'" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val guestNamespace = wsk.namespace.whois()
-            val packageName = "packageName3ptFQN"
-            val actionName = "actionName3ptFQN"
-            val triggerName = "triggerName3ptFQN"
-            val ruleName = "ruleName3ptFQN"
-            val fullQualifiedName = s"${guestNamespace}/${packageName}/${actionName}"
-            // Used for action and rule creation below
-            assetHelper.withCleaner(wsk.pkg, packageName) {
-                (pkg, _) => pkg.create(packageName)
-            }
-            assetHelper.withCleaner(wsk.trigger, triggerName) {
-                (trigger, _) => trigger.create(triggerName)
-            }
-            // Test action and rule creation where action name is 3 part FQN w/out leading slash
-            assetHelper.withCleaner(wsk.action, fullQualifiedName) {
-                (action, _) => action.create(fullQualifiedName, defaultAction)
-            }
-            assetHelper.withCleaner(wsk.rule, ruleName) {
-                (rule, _) =>
-                    rule.create(ruleName, trigger = triggerName, action = fullQualifiedName)
-            }
-
-            wsk.action.invoke(fullQualifiedName).stdout should include(s"ok: invoked /$fullQualifiedName")
-            wsk.action.get(fullQualifiedName).stdout should include(s"ok: got action ${packageName}/${actionName}")
-    }
-
-
-    behavior of "Wsk actions"
-
-    it should "reject creating entities with invalid names" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val names = Seq(
-                ("", ERROR_EXIT),
-                (" ", BAD_REQUEST),
-                ("hi+there", BAD_REQUEST),
-                ("$hola", BAD_REQUEST),
-                ("dora?", BAD_REQUEST),
-                ("|dora|dora?", BAD_REQUEST))
-
-            names foreach {
-                case (name, ec) =>
-                    assetHelper.withCleaner(wsk.action, name, confirmDelete = false) {
-                        (action, _) => action.create(name, defaultAction, expectedExitCode = ec)
-                    }
-            }
-    }
-
-    it should "reject create with missing file" in {
-        wsk.action.create("missingFile", Some("notfound"),
-            expectedExitCode = MISUSE_EXIT).
-            stderr should include("not a valid file")
-    }
-
-    it should "reject action update when specified file is missing" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            // Create dummy action to update
-            val name = "updateMissingFile"
-            val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
-            assetHelper.withCleaner(wsk.action, name) { (action, name) => action.create(name, file) }
-            // Update it with a missing file
-            wsk.action.create(name, Some("notfound"), update = true, expectedExitCode = MISUSE_EXIT)
-    }
-
-    it should "reject action update for sequence with no components" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "updateMissingComponents"
-            val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
-            assetHelper.withCleaner(wsk.action, name) { (action, name) => action.create(name, file) }
-            wsk.action.create(name, None, update = true, kind = Some("sequence"), expectedExitCode = MISUSE_EXIT)
-    }
-
-    it should "create, and get an action to verify parameter and annotation parsing" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "actionAnnotations"
-            val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) =>
-                    action.create(name, file, annotations = getValidJSONTestArgInput,
-                        parameters = getValidJSONTestArgInput)
-            }
-
-            val stdout = wsk.action.get(name).stdout
-            assert(stdout.startsWith(s"ok: got action $name\n"))
-
-            val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
-            val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
-            val escapedJSONArr = getValidJSONTestArgOutput.convertTo[JsArray].elements
-
-            for (expectedItem <- escapedJSONArr) {
-                receivedParams should contain(expectedItem)
-                receivedAnnots should contain(expectedItem)
-            }
-    }
-
-    it should "create, and get an action to verify file parameter and annotation parsing" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "actionAnnotAndParamParsing"
-            val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
-            val argInput = Some(TestCLIUtils.getTestActionFilename("validInput1.json"))
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) =>
-                    action.create(name, file, annotationFile = argInput, parameterFile = argInput)
-            }
-
-            val stdout = wsk.action.get(name).stdout
-            assert(stdout.startsWith(s"ok: got action $name\n"))
-
-            val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
-            val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
-            val escapedJSONArr = getJSONFileOutput.convertTo[JsArray].elements
-
-            for (expectedItem <- escapedJSONArr) {
-                receivedParams should contain(expectedItem)
-                receivedAnnots should contain(expectedItem)
-            }
-    }
-
-    it should "create an action with the proper parameter and annotation escapes" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "actionEscapes"
-            val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) =>
-                    action.create(name, file, parameters = getEscapedJSONTestArgInput,
-                        annotations = getEscapedJSONTestArgInput)
-            }
-
-            val stdout = wsk.action.get(name).stdout
-            assert(stdout.startsWith(s"ok: got action $name\n"))
-
-            val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
-            val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
-            val escapedJSONArr = getEscapedJSONTestArgOutput.convertTo[JsArray].elements
-
-            for (expectedItem <- escapedJSONArr) {
-                receivedParams should contain(expectedItem)
-                receivedAnnots should contain(expectedItem)
-            }
-    }
-
-    it should "invoke an action that exits during initialization and get appropriate error" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "abort init"
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("initexit.js")))
-            }
-
-            withActivation(wsk.activation, wsk.action.invoke(name)) {
-                activation =>
-                    val response = activation.response
-                    response.result.get.fields("error") shouldBe Messages.abnormalInitialization.toJson
-                    response.status shouldBe ActivationResponse.messageForCode(ActivationResponse.ContainerError)
-            }
-    }
-
-    it should "invoke an action that hangs during initialization and get appropriate error" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "hang init"
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) =>
-                    action.create(
-                        name,
-                        Some(TestCLIUtils.getTestActionFilename("initforever.js")),
-                        timeout = Some(3 seconds))
-            }
-
-            withActivation(wsk.activation, wsk.action.invoke(name)) {
-                activation =>
-                    val response = activation.response
-                    response.result.get.fields("error") shouldBe Messages.timedoutActivation(3 seconds, true).toJson
-                    response.status shouldBe ActivationResponse.messageForCode(ActivationResponse.ApplicationError)
-            }
-    }
-
-    it should "invoke an action that exits during run and get appropriate error" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "abort run"
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("runexit.js")))
-            }
-
-            withActivation(wsk.activation, wsk.action.invoke(name)) {
-                activation =>
-                    val response = activation.response
-                    response.result.get.fields("error") shouldBe Messages.abnormalRun.toJson
-                    response.status shouldBe ActivationResponse.messageForCode(ActivationResponse.ContainerError)
-            }
-    }
-
-    it should "retrieve the last activation using --last flag" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val auth: Seq[String] = Seq("--auth", wskprops.authKey)
-            val includeStr = "hello, undefined!"
-
-            assetHelper.withCleaner(wsk.action, "lastName") {
-                (action, _) => wsk.action.create("lastName", defaultAction)
-            }
-            retry({
-                val lastInvoke = wsk.action.invoke("lastName")
-                withActivation(wsk.activation, lastInvoke) { activation =>
-                    val lastFlag = Seq(
-                        (Seq("activation", "get", "publish", "--last"), activation.activationId),
-                        (Seq("activation", "get", "--last"), activation.activationId),
-                        (Seq("activation", "logs", "--last"), includeStr),
-                        (Seq("activation", "result", "--last"), includeStr))
-
-                    retry({
-                        lastFlag foreach {
-                            case (cmd, output) =>
-                                val stdout = wsk.cli(cmd ++ wskprops.overrides ++ auth, expectedExitCode = SUCCESS_EXIT).stdout
-                                stdout should include(output)
-                        }
-                    }, waitBeforeRetry = Some(500.milliseconds))
-
-                }
-            }, waitBeforeRetry = Some(1.second), N = 5)
-    }
-
-    it should "ensure keys are not omitted from activation record" in withAssetCleaner(wskprops) {
-        val name = "activationRecordTest"
-
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("argCheck.js")))
-            }
-
-            val run = wsk.action.invoke(name)
-            withActivation(wsk.activation, run) {
-                activation =>
-                    activation.start should be > Instant.EPOCH
-                    activation.end should be > Instant.EPOCH
-                    activation.response.status shouldBe ActivationResponse.messageForCode(ActivationResponse.Success)
-                    activation.response.success shouldBe true
-                    activation.response.result shouldBe Some(JsObject())
-                    activation.logs shouldBe Some(List())
-                    activation.annotations shouldBe defined
-            }
-    }
-
-    it should "write the action-path and the limits to the annotations" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "annotations"
-            val memoryLimit = 512 MB
-            val logLimit = 1 MB
-            val timeLimit = 60 seconds
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("helloAsync.js")), memory = Some(memoryLimit), timeout = Some(timeLimit), logsize = Some(logLimit))
-            }
-
-            val run = wsk.action.invoke(name, Map("payload" -> "this is a test".toJson))
-            withActivation(wsk.activation, run) {
-                activation =>
-                    activation.response.status shouldBe "success"
-                    val annotations = activation.annotations.get
-
-                    val limitsObj = JsObject(
-                        "key" -> JsString("limits"),
-                        "value" -> ActionLimits(TimeLimit(timeLimit), MemoryLimit(memoryLimit), LogLimit(logLimit)).toJson)
-
-                    val path = annotations.find { _.fields("key").convertTo[String] == "path" }.get
-
-                    path.fields("value").convertTo[String] should fullyMatch regex (s""".*/$name""")
-                    annotations should contain(limitsObj)
-            }
-    }
-
-    it should "report error when creating an action with unknown kind" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val rr = assetHelper.withCleaner(wsk.action, "invalid kind", confirmDelete = false) {
-                (action, name) => action.create(name, Some(TestCLIUtils.getTestActionFilename("echo.js")), kind = Some("foobar"), expectedExitCode = BAD_REQUEST)
-            }
-            rr.stderr should include regex "kind 'foobar' not in Set"
-    }
-
-    it should "report error when creating an action with zip but without kind" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "zipWithNoKind"
-            val zippedPythonAction = Some(TestCLIUtils.getTestActionFilename("python.zip"))
-            val createResult = assetHelper.withCleaner(wsk.action, name, confirmDelete = false) {
-                (action, _) =>
-                    action.create(name, zippedPythonAction, expectedExitCode = ANY_ERROR_EXIT)
-            }
-
-            createResult.stderr should include regex "requires specifying the action kind"
-    }
-
-    it should "create, and invoke an action that utilizes an invalid docker container with appropriate error" in withAssetCleaner(wskprops) {
-        val name = "invalidDockerContainer"
-        val containerName = s"bogus${Random.alphanumeric.take(16).mkString.toLowerCase}"
-
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.action, name) {
-                // docker name is a randomly generate string
-                (action, _) => action.create(name, None, docker = Some(containerName))
-            }
-
-            val run = wsk.action.invoke(name)
-            withActivation(wsk.activation, run) {
-                activation =>
-                    activation.response.status shouldBe ActivationResponse.messageForCode(ActivationResponse.ApplicationError)
-                    activation.response.result.get.fields("error") shouldBe s"Failed to pull container image '$containerName'.".toJson
-                    activation.annotations shouldBe defined
-                    val limits = activation.annotations.get.filter(_.fields("key").convertTo[String] == "limits")
-                    withClue(limits) {
-                        limits.length should be > 0
-                        limits(0).fields("value") should not be JsNull
-                    }
-            }
-    }
-
-    it should "invoke an action using npm openwhisk" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "hello npm openwhisk"
-            assetHelper.withCleaner(wsk.action, name, confirmDelete = false) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("helloOpenwhiskPackage.js")))
-            }
-
-            val run = wsk.action.invoke(name, Map("ignore_certs" -> true.toJson, "name" -> name.toJson))
-            withActivation(wsk.activation, run) {
-                activation =>
-                    activation.response.status shouldBe "success"
-                    activation.response.result shouldBe Some(JsObject("delete" -> true.toJson))
-                    activation.logs.get.mkString(" ") should include("action list has this many actions")
-            }
-
-            wsk.action.delete(name, expectedExitCode = TestUtils.NOT_FOUND)
-    }
-
-    it should "invoke an action receiving context properties" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val namespace = wsk.namespace.whois()
-            val name = "context"
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("helloContext.js")))
-            }
-
-            val start = Instant.now(Clock.systemUTC()).toEpochMilli
-            val run = wsk.action.invoke(name)
-            withActivation(wsk.activation, run) {
-                activation =>
-                    activation.response.status shouldBe "success"
-                    val fields = activation.response.result.get.convertTo[Map[String, String]]
-                    fields("api_host") shouldBe WhiskProperties.getApiHostForAction
-                    fields("api_key") shouldBe wskprops.authKey
-                    fields("namespace") shouldBe namespace
-                    fields("action_name") shouldBe s"/$namespace/$name"
-                    fields("activation_id") shouldBe activation.activationId
-                    fields("deadline").toLong should be >= start
-            }
-    }
-
-    it should "invoke an action successfully with options --blocking and --result" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "invokeResult"
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("echo.js")))
-            }
-            val args = Map("hello" -> "Robert".toJson)
-            val run = wsk.action.invoke(name, args, blocking = true, result = true)
-            run.stdout.parseJson shouldBe args.toJson
-    }
-
-    it should "invoke an action that returns a result by the deadline" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "deadline"
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("helloDeadline.js")), timeout = Some(3 seconds))
-            }
-
-            val run = wsk.action.invoke(name)
-            withActivation(wsk.activation, run) {
-                activation =>
-                    activation.response.status shouldBe "success"
-                    activation.response.result shouldBe Some(JsObject("timedout" -> true.toJson))
-            }
-    }
-
-    it should "invoke an action twice, where the first times out but the second does not and should succeed" in withAssetCleaner(wskprops) {
-        // this test issues two activations: the first is forced to time out and not return a result by its deadline (ie it does not resolve
-        // its promise). The invoker should reclaim its container so that a second activation of the same action (which must happen within a
-        // short period of time (seconds, not minutes) is allocated a fresh container and hence runs as expected (vs. hitting in the container
-        // cache and reusing a bad container).
-        (wp, assetHelper) =>
-            val name = "timeout"
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("helloDeadline.js")), timeout = Some(3 seconds))
-            }
-
-            val start = Instant.now(Clock.systemUTC()).toEpochMilli
-            val hungRun = wsk.action.invoke(name, Map("forceHang" -> true.toJson))
-            withActivation(wsk.activation, hungRun) {
-                activation =>
-                    // the first action must fail with a timeout error
-                    activation.response.status shouldBe ActivationResponse.messageForCode(ActivationResponse.ApplicationError)
-                    activation.response.result shouldBe Some(JsObject("error" -> Messages.timedoutActivation(3 seconds, false).toJson))
-            }
-
-            // run the action again, this time without forcing it to timeout
-            // it should succeed because it ran in a fresh container
-            val goodRun = wsk.action.invoke(name, Map("forceHang" -> false.toJson))
-            withActivation(wsk.activation, goodRun) {
-                activation =>
-                    // the first action must fail with a timeout error
-                    activation.response.status shouldBe "success"
-                    activation.response.result shouldBe Some(JsObject("timedout" -> true.toJson))
-            }
-    }
-
-    it should "ensure --web flags set the proper annotations" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "webaction"
-            val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, file)
-            }
-
-            Seq("true", "faLse", "tRue", "nO", "yEs", "no", "raw", "NO", "Raw").
-                foreach { flag =>
-                    val webEnabled = flag.toLowerCase == "true" || flag.toLowerCase == "yes"
-                    val rawEnabled = flag.toLowerCase == "raw"
-
-                    wsk.action.create(name, file, web = Some(flag), update = true)
-
-                    val stdout = wsk.action.get(name, fieldFilter = Some("annotations")).stdout
-                    assert(stdout.startsWith(s"ok: got action $name, displaying field annotations\n"))
-                    removeCLIHeader(stdout).parseJson shouldBe JsArray(
-                        JsObject(
-                            "key" -> JsString("exec"),
-                            "value" -> JsString("nodejs:6")),
-                        JsObject(
-                            "key" -> JsString("web-export"),
-                            "value" -> JsBoolean(webEnabled || rawEnabled)),
-                        JsObject(
-                            "key" -> JsString("raw-http"),
-                            "value" -> JsBoolean(rawEnabled)),
-                        JsObject(
-                            "key" -> JsString("final"),
-                            "value" -> JsBoolean(webEnabled || rawEnabled)))
-                }
-    }
-
-    it should "ensure action update with --web flag only copies existing annotations when new annotations are not provided" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "webaction"
-            val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
-            val createKey = "createKey"
-            val createValue = JsString("createValue")
-            val updateKey = "updateKey"
-            val updateValue = JsString("updateValue")
-            val origKey = "origKey"
-            val origValue = JsString("origValue")
-            val overwrittenValue = JsString("overwrittenValue")
-            val createAnnots = Map(createKey -> createValue, origKey -> origValue)
-            val updateAnnots = Map(updateKey -> updateValue, origKey -> overwrittenValue)
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, file, annotations = createAnnots)
-            }
-
-            wsk.action.create(name, file, web = Some("true"), update = true)
-
-            val existinAnnots = wsk.action.get(name, fieldFilter = Some("annotations")).stdout
-            assert(existinAnnots.startsWith(s"ok: got action $name, displaying field annotations\n"))
-            removeCLIHeader(existinAnnots).parseJson shouldBe JsArray(
-                JsObject(
-                    "key" -> JsString("web-export"),
-                    "value" -> JsBoolean(true)),
-                JsObject(
-                    "key" -> JsString(origKey),
-                    "value" -> origValue),
-                JsObject(
-                    "key" -> JsString("raw-http"),
-                    "value" -> JsBoolean(false)),
-                JsObject(
-                    "key" -> JsString("final"),
-                    "value" -> JsBoolean(true)),
-                JsObject(
-                    "key" -> JsString(createKey),
-                    "value" -> createValue),
-                JsObject(
-                    "key" -> JsString("exec"),
-                    "value" -> JsString("nodejs:6")))
-
-            wsk.action.create(name, file, web = Some("true"), update = true, annotations = updateAnnots)
-
-            val updatedAnnots = wsk.action.get(name, fieldFilter = Some("annotations")).stdout
-            assert(updatedAnnots.startsWith(s"ok: got action $name, displaying field annotations\n"))
-            removeCLIHeader(updatedAnnots).parseJson shouldBe JsArray(
-                JsObject(
-                    "key" -> JsString("web-export"),
-                    "value" -> JsBoolean(true)),
-                JsObject(
-                    "key" -> JsString(origKey),
-                    "value" -> overwrittenValue),
-                JsObject(
-                    "key" -> JsString(updateKey),
-                    "value" -> updateValue),
-                JsObject(
-                    "key" -> JsString("raw-http"),
-                    "value" -> JsBoolean(false)),
-                JsObject(
-                    "key" -> JsString("final"),
-                    "value" -> JsBoolean(true)),
-                JsObject(
-                    "key" -> JsString("exec"),
-                    "value" -> JsString("nodejs:6")))
-    }
-
-    it should "ensure action update creates an action with --web flag" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "webaction"
-            val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, file, web = Some("true"), update = true)
-            }
-
-            val stdout = wsk.action.get(name, fieldFilter = Some("annotations")).stdout
-            assert(stdout.startsWith(s"ok: got action $name, displaying field annotations\n"))
-            removeCLIHeader(stdout).parseJson shouldBe JsArray(
-                JsObject(
-                    "key" -> JsString("web-export"),
-                    "value" -> JsBoolean(true)),
-                JsObject(
-                    "key" -> JsString("raw-http"),
-                    "value" -> JsBoolean(false)),
-                JsObject(
-                    "key" -> JsString("final"),
-                    "value" -> JsBoolean(true)),
-                JsObject(
-                    "key" -> JsString("exec"),
-                    "value" -> JsString("nodejs:6")))
-    }
-
-    it should "reject action create and update with invalid web flag input" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "webaction"
-            val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
-            val invalidInput = "bogus"
-            val errorMsg = s"Invalid argument '$invalidInput' for --web flag. Valid input consist of 'yes', 'true', 'raw', 'false', or 'no'."
-            wsk.action.create(name, file, web = Some(invalidInput), expectedExitCode = MISUSE_EXIT).stderr should include(errorMsg)
-            wsk.action.create(name, file, web = Some(invalidInput), update = true, expectedExitCode = MISUSE_EXIT).stderr should include(errorMsg)
-    }
-
-    it should "invoke action while not encoding &, <, > characters" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "nonescape"
-            val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
-            val nonescape = "&<>"
-            val input = Map("payload" -> nonescape.toJson)
-            val output = JsObject("payload" -> JsString(s"hello, $nonescape!"))
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, file)
-            }
-
-            withActivation(wsk.activation, wsk.action.invoke(name, parameters = input)) {
-                activation =>
-                    activation.response.success shouldBe true
-                    activation.response.result shouldBe Some(output)
-                    activation.logs.toList.flatten.filter(_.contains(nonescape)).length shouldBe 1
-            }
-    }
-
-    it should "get an action URL" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val actionName = "action name@_-."
-            val packageName = "package name@_-."
-            val defaultPackageName = "default"
-            val webActionName = "web action name@_-."
-            val nonExistentActionName = "non-existence action"
-            val packagedAction = s"$packageName/$actionName"
-            val packagedWebAction = s"$packageName/$webActionName"
-            val namespace = wsk.namespace.whois()
-            val encodedActionName = URLEncoder.encode(actionName, StandardCharsets.UTF_8.name).replace("+", "%20")
-            val encodedPackageName = URLEncoder.encode(packageName, StandardCharsets.UTF_8.name).replace("+", "%20")
-            val encodedWebActionName = URLEncoder.encode(webActionName, StandardCharsets.UTF_8.name).replace("+", "%20")
-            val encodedNamespace = URLEncoder.encode(namespace, StandardCharsets.UTF_8.name).replace("+", "%20")
-            val actionPath = "https://%s/api/%s/namespaces/%s/actions/%s"
-            val packagedActionPath = s"$actionPath/%s"
-            val webActionPath = "https://%s/api/%s/web/%s/%s/%s"
-
-            assetHelper.withCleaner(wsk.action, actionName) {
-                (action, _) => action.create(actionName, defaultAction)
-            }
-
-            assetHelper.withCleaner(wsk.action, webActionName) {
-                (action, _) => action.create(webActionName, defaultAction, web = Some("true"))
-            }
-
-            assetHelper.withCleaner(wsk.pkg, packageName) {
-                (pkg, _) => pkg.create(packageName)
-            }
-
-            assetHelper.withCleaner(wsk.action, packagedAction) {
-                (action, _) => action.create(packagedAction, defaultAction)
-            }
-
-            assetHelper.withCleaner(wsk.action, packagedWebAction) {
-                (action, _) => action.create(packagedWebAction, defaultAction, web = Some("true"))
-            }
-
-            wsk.action.get(actionName, url = Some(true)).
-                stdout should include(actionPath.format(wskprops.apihost, wskprops.apiversion, encodedNamespace, encodedActionName))
-
-            // Ensure url flag works when a field filter and summary flag are specified
-            wsk.action.get(actionName, url = Some(true), fieldFilter = Some("field"), summary = true).
-                stdout should include(actionPath.format(wskprops.apihost, wskprops.apiversion, encodedNamespace, encodedActionName))
-
-            wsk.action.get(webActionName, url = Some(true)).
-                stdout should include(webActionPath.format(wskprops.apihost, wskprops.apiversion, encodedNamespace, defaultPackageName, encodedWebActionName))
-
-            wsk.action.get(packagedAction, url = Some(true)).
-                stdout should include(packagedActionPath.format(wskprops.apihost, wskprops.apiversion, encodedNamespace, encodedPackageName, encodedActionName))
-
-            wsk.action.get(packagedWebAction, url = Some(true)).
-                stdout should include(webActionPath.format(wskprops.apihost, wskprops.apiversion, encodedNamespace, encodedPackageName, encodedWebActionName))
-
-            wsk.action.get(nonExistentActionName, url = Some(true), expectedExitCode = NOT_FOUND)
-    }
-    it should "limit length of HTTP request and response bodies for --verbose" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "limitVerbose"
-            val msg = "will be truncated"
-            val params = Seq("-p", "bigValue", "a" * 1000)
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, Some(TestCLIUtils.getTestActionFilename("echo.js")))
-            }
-
-            val truncated = wsk.cli(Seq("action", "invoke", name, "-b", "-v", "--auth", wskprops.authKey) ++ params ++ wskprops.overrides).stdout
-            msg.r.findAllIn(truncated).length shouldBe 2
-
-            val notTruncated = wsk.cli(Seq("action", "invoke", name, "-b", "-d", "--auth", wskprops.authKey) ++ params ++ wskprops.overrides).stdout
-            msg.r.findAllIn(notTruncated).length shouldBe 0
-    }
-
-    it should "denote bound and finalized action parameters for action summaries" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val nameBoundParams = "actionBoundParams"
-            val nameFinalParams = "actionFinalParams"
-            val paramAnnot = "paramAnnot"
-            val paramOverlap = "paramOverlap"
-            val paramBound = "paramBound"
-            val annots = Map(
-                "parameters" -> JsArray(
-                    JsObject(
-                        "name" -> JsString(paramAnnot),
-                        "description" -> JsString("Annotated")),
-                    JsObject(
-                        "name" -> JsString(paramOverlap),
-                        "description" -> JsString("Annotated And Bound"))))
-            val annotsFinal = Map(
-                "final" -> JsBoolean(true),
-                "parameters" -> JsArray(
-                    JsObject(
-                        "name" -> JsString(paramAnnot),
-                        "description" -> JsString("Annotated Parameter description")),
-                    JsObject(
-                        "name" -> JsString(paramOverlap),
-                        "description" -> JsString("Annotated And Bound"))))
-            val paramsBound = Map(
-                paramBound -> JsString("Bound"),
-                paramOverlap -> JsString("Bound And Annotated"))
-
-            assetHelper.withCleaner(wsk.action, nameBoundParams) {
-                (action, _) =>
-                    action.create(nameBoundParams, defaultAction, annotations = annots, parameters = paramsBound)
-            }
-            assetHelper.withCleaner(wsk.action, nameFinalParams) {
-                (action, _) =>
-                    action.create(nameFinalParams, defaultAction, annotations = annotsFinal, parameters = paramsBound)
-            }
-
-            val stdoutBound = wsk.action.get(nameBoundParams, summary = true).stdout
-            val stdoutFinal = wsk.action.get(nameFinalParams, summary = true).stdout
-
-            stdoutBound should include (
-                s"(parameters: $paramAnnot, *$paramBound, *$paramOverlap)")
-            stdoutFinal should include (
-                s"(parameters: $paramAnnot, **$paramBound, **$paramOverlap)")
-    }
-
-    it should "create, and get an action summary without a description and/or defined parameters" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val actNameNoParams = "actionNoParams"
-            val actNameNoDesc = "actionNoDesc"
-            val actNameNoDescOrParams = "actionNoDescOrParams"
-            val desc = "Action description"
-            val descFromParamsResp = "Returns a result based on parameters"
-            val annotsNoParams = Map(
-                "description" -> JsString(desc)
-            )
-            val annotsNoDesc = Map(
-                "parameters" -> JsArray(
-                    JsObject(
-                        "name" -> JsString("paramName1"),
-                        "description" -> JsString("Parameter description 1")),
-                    JsObject(
-                        "name" -> JsString("paramName2"),
-                        "description" -> JsString("Parameter description 2"))))
-
-            assetHelper.withCleaner(wsk.action, actNameNoDesc) {
-                (action, _) =>
-                    action.create(actNameNoDesc, defaultAction, annotations = annotsNoDesc)
-            }
-            assetHelper.withCleaner(wsk.action, actNameNoParams) {
-                (action, _) =>
-                    action.create(actNameNoParams, defaultAction, annotations = annotsNoParams)
-            }
-            assetHelper.withCleaner(wsk.action, actNameNoDescOrParams) {
-                (action, _) =>
-                    action.create(actNameNoDescOrParams, defaultAction)
-            }
-
-            val stdoutNoDesc = wsk.action.get(actNameNoDesc, summary = true).stdout
-            val stdoutNoParams = wsk.action.get(actNameNoParams, summary = true).stdout
-            val stdoutNoDescOrParams = wsk.action.get(actNameNoDescOrParams, summary = true).stdout
-            val namespace = wsk.namespace.whois()
-
-            stdoutNoDesc should include regex (
-                s"(?i)action /${namespace}/${actNameNoDesc}: ${descFromParamsResp} paramName1 and paramName2\\s*\\(parameters: paramName1, paramName2\\)")
-            stdoutNoParams should include regex (
-                s"(?i)action /${namespace}/${actNameNoParams}: ${desc}\\s*\\(parameters: none defined\\)")
-            stdoutNoDescOrParams should include regex (
-                s"(?i)action /${namespace}/${actNameNoDescOrParams}\\s*\\(parameters: none defined\\)")
-    }
-
-    behavior of "Wsk packages"
-
-    it should "create, and delete a package" in {
-        val name = "createDeletePackage"
-        wsk.pkg.create(name).stdout should include(s"ok: created package $name")
-        wsk.pkg.delete(name).stdout should include(s"ok: deleted package $name")
-    }
-
-    it should "create, and get a package to verify parameter and annotation parsing" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "packageAnnotAndParamParsing"
-
-            assetHelper.withCleaner(wsk.pkg, name) {
-                (pkg, _) =>
-                    pkg.create(name, annotations = getValidJSONTestArgInput, parameters = getValidJSONTestArgInput)
-            }
-
-            val stdout = wsk.pkg.get(name).stdout
-            assert(stdout.startsWith(s"ok: got package $name\n"))
-
-            val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
-            val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
-            val escapedJSONArr = getValidJSONTestArgOutput.convertTo[JsArray].elements
-
-            for (expectedItem <- escapedJSONArr) {
-                receivedParams should contain(expectedItem)
-                receivedAnnots should contain(expectedItem)
-            }
-    }
-
-    it should "create, and get a package to verify file parameter and annotation parsing" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "packageAnnotAndParamFileParsing"
-            val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
-            val argInput = Some(TestCLIUtils.getTestActionFilename("validInput1.json"))
-
-            assetHelper.withCleaner(wsk.pkg, name) {
-                (pkg, _) =>
-                    pkg.create(name, annotationFile = argInput, parameterFile = argInput)
-            }
-
-            val stdout = wsk.pkg.get(name).stdout
-            assert(stdout.startsWith(s"ok: got package $name\n"))
-
-            val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
-            val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
-            val escapedJSONArr = getJSONFileOutput.convertTo[JsArray].elements
-
-            for (expectedItem <- escapedJSONArr) {
-                receivedParams should contain(expectedItem)
-                receivedAnnots should contain(expectedItem)
-            }
-    }
-
-    it should "create a package with the proper parameter and annotation escapes" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "packageEscapses"
-
-            assetHelper.withCleaner(wsk.pkg, name) {
-                (pkg, _) =>
-                    pkg.create(name, parameters = getEscapedJSONTestArgInput,
-                        annotations = getEscapedJSONTestArgInput)
-            }
-
-            val stdout = wsk.pkg.get(name).stdout
-            assert(stdout.startsWith(s"ok: got package $name\n"))
-
-            val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
-            val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
-            val escapedJSONArr = getEscapedJSONTestArgOutput.convertTo[JsArray].elements
-
-            for (expectedItem <- escapedJSONArr) {
-                receivedParams should contain(expectedItem)
-                receivedAnnots should contain(expectedItem)
-            }
-    }
-
-    it should "report conformance error accessing action as package" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "aAsP"
-            val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, file)
-            }
-
-            wsk.pkg.get(name, expectedExitCode = CONFLICT).
-                stderr should include(Messages.conformanceMessage)
-
-            wsk.pkg.bind(name, "bogus", expectedExitCode = CONFLICT).
-                stderr should include(Messages.requestedBindingIsNotValid)
-
-            wsk.pkg.bind("bogus", "alsobogus", expectedExitCode = BAD_REQUEST).
-                stderr should include(Messages.bindingDoesNotExist)
-
-    }
-
-    it should "create, and get a package summary without a description and/or parameters" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val pkgNoDesc = "pkgNoDesc"
-            val pkgNoParams = "pkgNoParams"
-            val pkgNoDescOrParams = "pkgNoDescOrParams"
-            val pkgDesc = "Package description"
-            val descFromParams = "Returns a result based on parameters"
-            val namespace = wsk.namespace.whois()
-            val qualpkgNoDesc = s"/${namespace}/${pkgNoDesc}"
-            val qualpkgNoParams = s"/${namespace}/${pkgNoParams}"
-            val qualpkgNoDescOrParams = s"/${namespace}/${pkgNoDescOrParams}"
-
-            val pkgAnnotsNoParams = Map(
-                "description" -> JsString(pkgDesc)
-            )
-            val pkgAnnotsNoDesc = Map(
-                "parameters" -> JsArray(
-                    JsObject(
-                        "name" -> JsString("paramName1"),
-                        "description" -> JsString("Parameter description 1")),
-                    JsObject(
-                        "name" -> JsString("paramName2"),
-                        "description" -> JsString("Parameter description 2"))))
-
-            assetHelper.withCleaner(wsk.pkg, pkgNoDesc) {
-                (pkg, _) =>
-                    pkg.create(pkgNoDesc, annotations = pkgAnnotsNoDesc)
-            }
-            assetHelper.withCleaner(wsk.pkg, pkgNoParams) {
-                (pkg, _) =>
-                    pkg.create(pkgNoParams, annotations = pkgAnnotsNoParams)
-            }
-            assetHelper.withCleaner(wsk.pkg, pkgNoDescOrParams) {
-                (pkg, _) =>
-                    pkg.create(pkgNoDescOrParams)
-            }
-
-            val stdoutNoDescPkg = wsk.pkg.get(pkgNoDesc, summary = true).stdout
-            val stdoutNoParamsPkg = wsk.pkg.get(pkgNoParams, summary = true).stdout
-            val stdoutNoDescOrParams = wsk.pkg.get(pkgNoDescOrParams, summary = true).stdout
-
-            stdoutNoDescPkg should include regex (
-                s"(?i)package ${qualpkgNoDesc}: ${descFromParams} paramName1 and paramName2\\s*\\(parameters: paramName1, paramName2\\)")
-            stdoutNoParamsPkg should include regex (
-                s"(?i)package ${qualpkgNoParams}: ${pkgDesc}\\s*\\(parameters: none defined\\)")
-            stdoutNoDescOrParams should include regex (
-                s"(?i)package ${qualpkgNoDescOrParams}\\s*\\(parameters: none defined\\)")
-    }
-
-    it should "denote bound package parameters for package summaries" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val pkgBoundParams = "pkgBoundParams"
-            val pkgParamAnnot = "pkgParamAnnot"
-            val pkgParamOverlap = "pkgParamOverlap"
-            val pkgParamBound = "pkgParamBound"
-            val pkgAnnots = Map(
-                "parameters" -> JsArray(
-                    JsObject(
-                        "name" -> JsString(pkgParamAnnot),
-                        "description" -> JsString("Annotated")),
-                    JsObject(
-                        "name" -> JsString(pkgParamOverlap),
-                        "description" -> JsString("Annotated And Bound"))))
-            val pkgParamsBound = Map(
-                pkgParamBound -> JsString("Bound"),
-                pkgParamOverlap -> JsString("Bound And Annotated"))
-
-            assetHelper.withCleaner(wsk.pkg, pkgBoundParams) {
-                (pkg, _) =>
-                    pkg.create(pkgBoundParams, annotations = pkgAnnots, parameters = pkgParamsBound)
-            }
-
-            val pkgStdoutBound = wsk.pkg.get(pkgBoundParams, summary = true).stdout
-
-            pkgStdoutBound should include (s"(parameters: $pkgParamAnnot, *$pkgParamBound, *$pkgParamOverlap)")
-    }
-
-    behavior of "Wsk triggers"
-
-    it should "create, and get a trigger to verify parameter and annotation parsing" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "triggerAnnotAndParamParsing"
-
-            assetHelper.withCleaner(wsk.trigger, name) {
-                (trigger, _) =>
-                    trigger.create(name, annotations = getValidJSONTestArgInput, parameters = getValidJSONTestArgInput)
-            }
-
-            val stdout = wsk.trigger.get(name).stdout
-            assert(stdout.startsWith(s"ok: got trigger $name\n"))
-
-            val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
-            val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
-            val escapedJSONArr = getValidJSONTestArgOutput.convertTo[JsArray].elements
-
-            for (expectedItem <- escapedJSONArr) {
-                receivedParams should contain(expectedItem)
-                receivedAnnots should contain(expectedItem)
-            }
-    }
-
-    it should "create, and get a trigger to verify file parameter and annotation parsing" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "triggerAnnotAndParamFileParsing"
-            val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
-            val argInput = Some(TestCLIUtils.getTestActionFilename("validInput1.json"))
-
-            assetHelper.withCleaner(wsk.trigger, name) {
-                (trigger, _) =>
-                    trigger.create(name, annotationFile = argInput, parameterFile = argInput)
-            }
-
-            val stdout = wsk.trigger.get(name).stdout
-            assert(stdout.startsWith(s"ok: got trigger $name\n"))
-
-            val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
-            val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
-            val escapedJSONArr = getJSONFileOutput.convertTo[JsArray].elements
-
-            for (expectedItem <- escapedJSONArr) {
-                receivedParams should contain(expectedItem)
-                receivedAnnots should contain(expectedItem)
-            }
-    }
-
-    it should "display a trigger summary when --summary flag is used with 'wsk trigger get'" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val triggerName = "mySummaryTrigger"
-            assetHelper.withCleaner(wsk.trigger, triggerName, confirmDelete = false) {
-                (trigger, name) => trigger.create(name)
-            }
-
-            // Summary namespace should match one of the allowable namespaces (typically 'guest')
-            val ns = wsk.namespace.whois()
-            val stdout = wsk.trigger.get(triggerName, summary = true).stdout
-            stdout should include regex (s"(?i)trigger\\s+/$ns/$triggerName")
-    }
-
-    it should "create a trigger with the proper parameter and annotation escapes" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "triggerEscapes"
-
-            assetHelper.withCleaner(wsk.trigger, name) {
-                (trigger, _) =>
-                    trigger.create(name, parameters = getEscapedJSONTestArgInput,
-                        annotations = getEscapedJSONTestArgInput)
-            }
-
-            val stdout = wsk.trigger.get(name).stdout
-            assert(stdout.startsWith(s"ok: got trigger $name\n"))
-
-            val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
-            val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
-            val escapedJSONArr = getEscapedJSONTestArgOutput.convertTo[JsArray].elements
-
-            for (expectedItem <- escapedJSONArr) {
-                receivedParams should contain(expectedItem)
-                receivedAnnots should contain(expectedItem)
-            }
-    }
-
-    it should "not create a trigger when feed fails to initialize" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.trigger, "badfeed", confirmDelete = false) {
-                (trigger, name) =>
-                    trigger.create(name, feed = Some(s"bogus"), expectedExitCode = ANY_ERROR_EXIT).
-                        exitCode should equal(NOT_FOUND)
-                    trigger.get(name, expectedExitCode = NOT_FOUND)
-
-                    trigger.create(name, feed = Some(s"bogus/feed"), expectedExitCode = ANY_ERROR_EXIT).
-                        exitCode should equal(NOT_FOUND)
-                    trigger.get(name, expectedExitCode = NOT_FOUND)
-            }
-    }
-
-    it should "denote bound trigger parameters for trigger summaries" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val trgBoundParams = "trgBoundParams"
-            val trgParamAnnot = "trgParamAnnot"
-            val trgParamOverlap = "trgParamOverlap"
-            val trgParamBound = "trgParamBound"
-            val trgAnnots = Map(
-                "parameters" -> JsArray(
-                    JsObject(
-                        "name" -> JsString(trgParamAnnot),
-                        "description" -> JsString("Annotated")),
-                    JsObject(
-                        "name" -> JsString(trgParamOverlap),
-                        "description" -> JsString("Annotated And Bound"))))
-            val trgParamsBound = Map(
-                trgParamBound -> JsString("Bound"),
-                trgParamOverlap -> JsString("Bound And Annotated"))
-
-            assetHelper.withCleaner(wsk.trigger, trgBoundParams) {
-                (trigger, _) =>
-                    trigger.create(trgBoundParams, annotations = trgAnnots, parameters = trgParamsBound)
-            }
-
-            val trgStdoutBound = wsk.trigger.get(trgBoundParams, summary = true).stdout
-
-            trgStdoutBound should include (s"(parameters: $trgParamAnnot, *$trgParamBound, *$trgParamOverlap)")
-    }
-
-    it should "create, and get a trigger summary without a description and/or parameters" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val trgNoDesc = "trgNoDesc"
-            val trgNoParams = "trgNoParams"
-            val trgNoDescOrParams = "trgNoDescOrParams"
-            val trgDesc = "Package description"
-            val descFromParams = "Returns a result based on parameters"
-            val namespace = wsk.namespace.whois()
-            val qualtrgNoDesc = s"/${namespace}/${trgNoDesc}"
-            val qualtrgNoParams = s"/${namespace}/${trgNoParams}"
-            val qualtrgNoDescOrParams = s"/${namespace}/${trgNoDescOrParams}"
-
-            val trgAnnotsNoParams = Map(
-                "description" -> JsString(trgDesc)
-            )
-            val trgAnnotsNoDesc = Map(
-                "parameters" -> JsArray(
-                    JsObject(
-                        "name" -> JsString("paramName1"),
-                        "description" -> JsString("Parameter description 1")),
-                    JsObject(
-                        "name" -> JsString("paramName2"),
-                        "description" -> JsString("Parameter description 2"))))
-
-            assetHelper.withCleaner(wsk.trigger, trgNoDesc) {
-                (trigger, _) =>
-                    trigger.create(trgNoDesc, annotations = trgAnnotsNoDesc)
-            }
-            assetHelper.withCleaner(wsk.trigger, trgNoParams) {
-                (trigger, _) =>
-                    trigger.create(trgNoParams, annotations = trgAnnotsNoParams)
-            }
-            assetHelper.withCleaner(wsk.trigger, trgNoDescOrParams) {
-                (trigger, _) =>
-                    trigger.create(trgNoDescOrParams)
-            }
-
-            val stdoutNoDescPkg = wsk.trigger.get(trgNoDesc, summary = true).stdout
-            val stdoutNoParamsPkg = wsk.trigger.get(trgNoParams, summary = true).stdout
-            val stdoutNoDescOrParams = wsk.trigger.get(trgNoDescOrParams, summary = true).stdout
-
-            stdoutNoDescPkg should include regex (
-                s"(?i)trigger ${qualtrgNoDesc}: ${descFromParams} paramName1 and paramName2\\s*\\(parameters: paramName1, paramName2\\)")
-            stdoutNoParamsPkg should include regex (
-                s"(?i)trigger ${qualtrgNoParams}: ${trgDesc}\\s*\\(parameters: none defined\\)")
-            stdoutNoDescOrParams should include regex (
-                s"(?i)trigger ${qualtrgNoDescOrParams}\\s*\\(parameters: none defined\\)")
-    }
-
-    behavior of "Wsk entity list formatting"
-
-    it should "create, and list a package with a long name" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "x" * 70
-            assetHelper.withCleaner(wsk.pkg, name) {
-                (pkg, _) =>
-                    pkg.create(name)
-            }
-            retry({
-                wsk.pkg.list().stdout should include(s"$name private")
-            }, 5, Some(1 second))
-    }
-
-    it should "create, and list an action with a long name" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "x" * 70
-            val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) =>
-                    action.create(name, file)
-            }
-            retry({
-                wsk.action.list().stdout should include(s"$name private nodejs")
-            }, 5, Some(1 second))
-    }
-
-    it should "create, and list a trigger with a long name" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "x" * 70
-            assetHelper.withCleaner(wsk.trigger, name) {
-                (trigger, _) =>
-                    trigger.create(name)
-            }
-            retry({
-                wsk.trigger.list().stdout should include(s"$name private")
-            }, 5, Some(1 second))
-    }
-
-    it should "create, and list a rule with a long name" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val ruleName = "x" * 70
-            val triggerName = "listRulesTrigger"
-            val actionName = "listRulesAction";
-            assetHelper.withCleaner(wsk.trigger, triggerName) {
-                (trigger, name) => trigger.create(name)
-            }
-            assetHelper.withCleaner(wsk.action, actionName) {
-                (action, name) => action.create(name, defaultAction)
-            }
-            assetHelper.withCleaner(wsk.rule, ruleName) {
-                (rule, name) =>
-                    rule.create(name, trigger = triggerName, action = actionName)
-            }
-            retry({
-                wsk.rule.list().stdout should include(s"$ruleName private")
-            }, 5, Some(1 second))
-    }
-
-    it should "return a list of alphabetized actions" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            // Declare 4 actions, create them out of alphabetical order
-            val actionName = "actionAlphaTest"
-            for (i <- 1 to 3) {
-                val name = s"$actionName$i"
-                assetHelper.withCleaner(wsk.action, name) {
-                    (action, name) =>
-                        action.create(name, defaultAction)
-                }
-            }
-            retry({
-                val original = wsk.action.list(nameSort = Some(true)).stdout
-                // Create list with action names in correct order
-                val scalaSorted = List(s"${actionName}1", s"${actionName}2", s"${actionName}3")
-                // Filter out everything not previously created
-                val regex = s"${actionName}[1-3]".r
-                // Retrieve action names into list as found in original
-                val list  = (regex.findAllMatchIn(original)).toList
-                scalaSorted.toString shouldEqual list.toString
-            }, 5, Some(1 second))
-    }
-
-    it should "return an alphabetized list with default package actions on top" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            // Declare 4 actions, create them out of alphabetical order
-            val actionName = "actionPackageAlphaTest"
-            val packageName = "packageAlphaTest"
-            assetHelper.withCleaner(wsk.action, actionName) {
-                (action, actionName) =>
-                    action.create(actionName, defaultAction)
-            }
-            assetHelper.withCleaner(wsk.pkg, packageName) {
-                (pkg, packageName) =>
-                    pkg.create(packageName)
-            }
-            for (i <- 1 to 3) {
-                val name = s"${packageName}/${actionName}$i"
-                assetHelper.withCleaner(wsk.action, name) {
-                    (action, name) =>
-                        action.create(name, defaultAction)
-                }
-            }
-            retry({
-                val original = wsk.action.list(nameSort = Some(true)).stdout
-                // Create list with action names in correct order
-                val scalaSorted = List(s"$actionName", s"${packageName}/${actionName}1", s"${packageName}/${actionName}2", s"${packageName}/${actionName}3")
-                // Filter out everything not previously created
-                val regexNoPackage = s"$actionName".r
-                val regexWithPackage = s"${packageName}/${actionName}[1-3]".r
-                // Retrieve action names into list as found in original
-                val list = regexNoPackage.findFirstIn(original).get :: (regexWithPackage.findAllMatchIn(original)).toList
-                scalaSorted.toString shouldEqual list.toString
-            }, 5, Some(1 second))
-    }
-
-    it should "return a list of alphabetized packages" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            // Declare 3 packages, create them out of alphabetical order
-            val packageName = "pkgAlphaTest"
-            for (i <- 1 to 3) {
-                val name = s"$packageName$i"
-                assetHelper.withCleaner(wsk.pkg, name) {
-                    (pkg, name) =>
-                        pkg.create(name)
-                }
-            }
-            retry({
-                val original = wsk.pkg.list(nameSort = Some(true)).stdout
-                // Create list with package names in correct order
-                val scalaSorted = List(s"${packageName}1", s"${packageName}2", s"${packageName}3")
-                // Filter out everything not previously created
-                val regex = s"${packageName}[1-3]".r
-                // Retrieve package names into list as found in original
-                val list  = (regex.findAllMatchIn(original)).toList
-                scalaSorted.toString shouldEqual list.toString
-            }, 5, Some(1 second))
+class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
+
+  implicit val wskprops = WskProps()
+  val wsk = new Wsk
+  val defaultAction = Some(TestUtils.getTestActionFilename("hello.js"))
+
+  behavior of "Wsk CLI usage"
+
+  it should "show help and usage info" in {
+    val stdout = wsk.cli(Seq()).stdout
+    stdout should include regex ("""(?i)Usage:""")
+    stdout should include regex ("""(?i)Flags""")
+    stdout should include regex ("""(?i)Available commands""")
+    stdout should include regex ("""(?i)--help""")
+  }
+
+  it should "show help and usage info using the default language" in {
+    val env = Map("LANG" -> "de_DE")
+    // Call will fail with exit code 2 if language not supported
+    wsk.cli(Seq("-h"), env = env)
+  }
+
+  it should "show cli build version" in {
+    val stdout = wsk.cli(Seq("property", "get", "--cliversion")).stdout
+    stdout should include regex ("""(?i)whisk CLI version\s+201.*""")
+  }
+
+  it should "show api version" in {
+    val stdout = wsk.cli(Seq("property", "get", "--apiversion")).stdout
+    stdout should include regex ("""(?i)whisk API version\s+v1""")
+  }
+
+  it should "reject bad command" in {
+    val result = wsk.cli(Seq("bogus"), expectedExitCode = ERROR_EXIT)
+    result.stderr should include regex ("""(?i)Run 'wsk --help' for usage""")
+  }
+
+  it should "allow a 3 part Fully Qualified Name (FQN) without a leading '/'" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val guestNamespace = wsk.namespace.whois()
+      val packageName = "packageName3ptFQN"
+      val actionName = "actionName3ptFQN"
+      val triggerName = "triggerName3ptFQN"
+      val ruleName = "ruleName3ptFQN"
+      val fullQualifiedName = s"${guestNamespace}/${packageName}/${actionName}"
+      // Used for action and rule creation below
+      assetHelper.withCleaner(wsk.pkg, packageName) { (pkg, _) =>
+        pkg.create(packageName)
+      }
+      assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, _) =>
+        trigger.create(triggerName)
+      }
+      // Test action and rule creation where action name is 3 part FQN w/out leading slash
+      assetHelper.withCleaner(wsk.action, fullQualifiedName) { (action, _) =>
+        action.create(fullQualifiedName, defaultAction)
+      }
+      assetHelper.withCleaner(wsk.rule, ruleName) { (rule, _) =>
+        rule.create(ruleName, trigger = triggerName, action = fullQualifiedName)
+      }
+
+      wsk.action.invoke(fullQualifiedName).stdout should include(s"ok: invoked /$fullQualifiedName")
+      wsk.action.get(fullQualifiedName).stdout should include(s"ok: got action ${packageName}/${actionName}")
+  }
+
+  behavior of "Wsk actions"
+
+  it should "reject creating entities with invalid names" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val names = Seq(
+      ("", ERROR_EXIT),
+      (" ", BAD_REQUEST),
+      ("hi+there", BAD_REQUEST),
+      ("$hola", BAD_REQUEST),
+      ("dora?", BAD_REQUEST),
+      ("|dora|dora?", BAD_REQUEST))
+
+    names foreach {
+      case (name, ec) =>
+        assetHelper.withCleaner(wsk.action, name, confirmDelete = false) { (action, _) =>
+          action.create(name, defaultAction, expectedExitCode = ec)
+        }
     }
+  }
+
+  it should "reject create with missing file" in {
+    wsk.action.create("missingFile", Some("notfound"), expectedExitCode = MISUSE_EXIT).stderr should include(
+      "not a valid file")
+  }
+
+  it should "reject action update when specified file is missing" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    // Create dummy action to update
+    val name = "updateMissingFile"
+    val file = Some(TestUtils.getTestActionFilename("hello.js"))
+    assetHelper.withCleaner(wsk.action, name) { (action, name) =>
+      action.create(name, file)
+    }
+    // Update it with a missing file
+    wsk.action.create(name, Some("notfound"), update = true, expectedExitCode = MISUSE_EXIT)
+  }
+
+  it should "reject action update for sequence with no components" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "updateMissingComponents"
+    val file = Some(TestUtils.getTestActionFilename("hello.js"))
+    assetHelper.withCleaner(wsk.action, name) { (action, name) =>
+      action.create(name, file)
+    }
+    wsk.action.create(name, None, update = true, kind = Some("sequence"), expectedExitCode = MISUSE_EXIT)
+  }
+
+  it should "create, and get an action to verify parameter and annotation parsing" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "actionAnnotations"
+      val file = Some(TestUtils.getTestActionFilename("hello.js"))
+
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, file, annotations = getValidJSONTestArgInput, parameters = getValidJSONTestArgInput)
+      }
+
+      val stdout = wsk.action.get(name).stdout
+      assert(stdout.startsWith(s"ok: got action $name\n"))
+
+      val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
+      val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
+      val escapedJSONArr = getValidJSONTestArgOutput.convertTo[JsArray].elements
+
+      for (expectedItem <- escapedJSONArr) {
+        receivedParams should contain(expectedItem)
+        receivedAnnots should contain(expectedItem)
+      }
+  }
+
+  it should "create, and get an action to verify file parameter and annotation parsing" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "actionAnnotAndParamParsing"
+      val file = Some(TestUtils.getTestActionFilename("hello.js"))
+      val argInput = Some(TestUtils.getTestActionFilename("validInput1.json"))
+
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, file, annotationFile = argInput, parameterFile = argInput)
+      }
+
+      val stdout = wsk.action.get(name).stdout
+      assert(stdout.startsWith(s"ok: got action $name\n"))
+
+      val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
+      val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
+      val escapedJSONArr = getJSONFileOutput.convertTo[JsArray].elements
+
+      for (expectedItem <- escapedJSONArr) {
+        receivedParams should contain(expectedItem)
+        receivedAnnots should contain(expectedItem)
+      }
+  }
+
+  it should "create an action with the proper parameter and annotation escapes" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "actionEscapes"
+      val file = Some(TestUtils.getTestActionFilename("hello.js"))
+
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, file, parameters = getEscapedJSONTestArgInput, annotations = getEscapedJSONTestArgInput)
+      }
+
+      val stdout = wsk.action.get(name).stdout
+      assert(stdout.startsWith(s"ok: got action $name\n"))
+
+      val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
+      val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
+      val escapedJSONArr = getEscapedJSONTestArgOutput.convertTo[JsArray].elements
+
+      for (expectedItem <- escapedJSONArr) {
+        receivedParams should contain(expectedItem)
+        receivedAnnots should contain(expectedItem)
+      }
+  }
+
+  it should "invoke an action that exits during initialization and get appropriate error" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "abort init"
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, Some(TestUtils.getTestActionFilename("initexit.js")))
+      }
+
+      withActivation(wsk.activation, wsk.action.invoke(name)) { activation =>
+        val response = activation.response
+        response.result.get.fields("error") shouldBe Messages.abnormalInitialization.toJson
+        response.status shouldBe ActivationResponse.messageForCode(ActivationResponse.ContainerError)
+      }
+  }
+
+  it should "invoke an action that hangs during initialization and get appropriate error" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "hang init"
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, Some(TestUtils.getTestActionFilename("initforever.js")), timeout = Some(3 seconds))
+      }
+
+      withActivation(wsk.activation, wsk.action.invoke(name)) { activation =>
+        val response = activation.response
+        response.result.get.fields("error") shouldBe Messages.timedoutActivation(3 seconds, true).toJson
+        response.status shouldBe ActivationResponse.messageForCode(ActivationResponse.ApplicationError)
+      }
+  }
+
+  it should "invoke an action that exits during run and get appropriate error" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "abort run"
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, Some(TestUtils.getTestActionFilename("runexit.js")))
+      }
+
+      withActivation(wsk.activation, wsk.action.invoke(name)) { activation =>
+        val response = activation.response
+        response.result.get.fields("error") shouldBe Messages.abnormalRun.toJson
+        response.status shouldBe ActivationResponse.messageForCode(ActivationResponse.ContainerError)
+      }
+  }
+
+  it should "retrieve the last activation using --last flag" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val auth: Seq[String] = Seq("--auth", wskprops.authKey)
+    val includeStr = "hello, undefined!"
+
+    assetHelper.withCleaner(wsk.action, "lastName") { (action, _) =>
+      wsk.action.create("lastName", defaultAction)
+    }
+    retry(
+      {
+        val lastInvoke = wsk.action.invoke("lastName")
+        withActivation(wsk.activation, lastInvoke) {
+          activation =>
+            val lastFlag = Seq(
+              (Seq("activation", "get", "publish", "--last"), activation.activationId),
+              (Seq("activation", "get", "--last"), activation.activationId),
+              (Seq("activation", "logs", "--last"), includeStr),
+              (Seq("activation", "result", "--last"), includeStr))
 
-    it should "return a list of alphabetized triggers" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            // Declare 4 triggers, create them out of alphabetical order
-            val triggerName = "triggerAlphaTest"
-            for (i <- 1 to 3) {
-                val name = s"$triggerName$i"
-                assetHelper.withCleaner(wsk.trigger, name) {
-                    (trigger, name) =>
-                        trigger.create(name)
-                }
-            }
             retry({
-                val original = wsk.trigger.list(nameSort = Some(true)).stdout
-                // Create list with trigger names in correct order
-                val scalaSorted = List(s"${triggerName}1", s"${triggerName}2", s"${triggerName}3")
-                // Filter out everything not previously created
-                val regex = s"${triggerName}[1-3]".r
-                // Retrieve trigger names into list as found in original
-                val list  = (regex.findAllMatchIn(original)).toList
-                scalaSorted.toString shouldEqual list.toString
-            }, 5, Some(1 second))
-    }
+              lastFlag foreach {
+                case (cmd, output) =>
+                  val stdout = wsk.cli(cmd ++ wskprops.overrides ++ auth, expectedExitCode = SUCCESS_EXIT).stdout
+                  stdout should include(output)
+              }
+            }, waitBeforeRetry = Some(500.milliseconds))
 
-    it should "return a list of alphabetized rules" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            // Declare a trigger and an action for the purposes of creating rules
-            val triggerName = "listRulesTrigger"
-            val actionName = "listRulesAction"
-
-            assetHelper.withCleaner(wsk.trigger, triggerName) {
-                (trigger, name) => trigger.create(name)
-            }
-            assetHelper.withCleaner(wsk.action, actionName) {
-                (action, name) => action.create(name, defaultAction)
-            }
-            // Declare 3 rules, create them out of alphabetical order
-            val ruleName = "ruleAlphaTest"
-            for (i <- 1 to 3) {
-                val name = s"$ruleName$i"
-                assetHelper.withCleaner(wsk.rule, name) {
-                    (rule, name) =>
-                        rule.create(name, trigger = triggerName, action = actionName)
-                }
-            }
-            retry({
-                val original = wsk.rule.list(nameSort = Some(true)).stdout
-                // Create list with rule names in correct order
-                val scalaSorted = List(s"${ruleName}1", s"${ruleName}2", s"${ruleName}3")
-                // Filter out everything not previously created
-                val regex = s"${ruleName}[1-3]".r
-                // Retrieve rule names into list as found in original
-                val list  = (regex.findAllMatchIn(original)).toList
-                scalaSorted.toString shouldEqual list.toString
-            })
-    }
-
-    behavior of "Wsk params and annotations"
-
-    it should "reject commands that are executed with invalid JSON for annotations and parameters" in {
-        val invalidJSONInputs = getInvalidJSONInput
-        val invalidJSONFiles = Seq(
-            TestCLIUtils.getTestActionFilename("malformed.js"),
-            TestCLIUtils.getTestActionFilename("invalidInput1.json"),
-            TestCLIUtils.getTestActionFilename("invalidInput2.json"),
-            TestCLIUtils.getTestActionFilename("invalidInput3.json"),
-            TestCLIUtils.getTestActionFilename("invalidInput4.json"))
-        val paramCmds = Seq(
-            Seq("action", "create", "actionName", TestCLIUtils.getTestActionFilename("hello.js")),
-            Seq("action", "update", "actionName", TestCLIUtils.getTestActionFilename("hello.js")),
-            Seq("action", "invoke", "actionName"),
-            Seq("package", "create", "packageName"),
-            Seq("package", "update", "packageName"),
-            Seq("package", "bind", "packageName", "boundPackageName"),
-            Seq("trigger", "create", "triggerName"),
-            Seq("trigger", "update", "triggerName"),
-            Seq("trigger", "fire", "triggerName"))
-        val annotCmds = Seq(
-            Seq("action", "create", "actionName", TestCLIUtils.getTestActionFilename("hello.js")),
-            Seq("action", "update", "actionName", TestCLIUtils.getTestActionFilename("hello.js")),
-            Seq("package", "create", "packageName"),
-            Seq("package", "update", "packageName"),
-            Seq("package", "bind", "packageName", "boundPackageName"),
-            Seq("trigger", "create", "triggerName"),
-            Seq("trigger", "update", "triggerName"))
-
-        for (cmd <- paramCmds) {
-            for (invalid <- invalidJSONInputs) {
-                wsk.cli(cmd ++ Seq("-p", "key", invalid) ++ wskprops.overrides, expectedExitCode = ERROR_EXIT)
-                    .stderr should include("Invalid parameter argument")
-            }
-
-            for (invalid <- invalidJSONFiles) {
-                wsk.cli(cmd ++ Seq("-P", invalid) ++ wskprops.overrides, expectedExitCode = ERROR_EXIT)
-                    .stderr should include("Invalid parameter argument")
-
-            }
         }
-
-        for (cmd <- annotCmds) {
-            for (invalid <- invalidJSONInputs) {
-                wsk.cli(cmd ++ Seq("-a", "key", invalid) ++ wskprops.overrides, expectedExitCode = ERROR_EXIT)
-                    .stderr should include("Invalid annotation argument")
-            }
-
-            for (invalid <- invalidJSONFiles) {
-                wsk.cli(cmd ++ Seq("-A", invalid) ++ wskprops.overrides, expectedExitCode = ERROR_EXIT)
-                    .stderr should include("Invalid annotation argument")
-            }
+      },
+      waitBeforeRetry = Some(1.second),
+      N = 5)
+  }
+
+  it should "ensure keys are not omitted from activation record" in withAssetCleaner(wskprops) {
+    val name = "activationRecordTest"
+
+    (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, Some(TestUtils.getTestActionFilename("argCheck.js")))
+      }
+
+      val run = wsk.action.invoke(name)
+      withActivation(wsk.activation, run) { activation =>
+        activation.start should be > Instant.EPOCH
+        activation.end should be > Instant.EPOCH
+        activation.response.status shouldBe ActivationResponse.messageForCode(ActivationResponse.Success)
+        activation.response.success shouldBe true
+        activation.response.result shouldBe Some(JsObject())
+        activation.logs shouldBe Some(List())
+        activation.annotations shouldBe defined
+      }
+  }
+
+  it should "write the action-path and the limits to the annotations" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "annotations"
+      val memoryLimit = 512 MB
+      val logLimit = 1 MB
+      val timeLimit = 60 seconds
+
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(
+          name,
+          Some(TestUtils.getTestActionFilename("helloAsync.js")),
+          memory = Some(memoryLimit),
+          timeout = Some(timeLimit),
+          logsize = Some(logLimit))
+      }
+
+      val run = wsk.action.invoke(name, Map("payload" -> "this is a test".toJson))
+      withActivation(wsk.activation, run) { activation =>
+        activation.response.status shouldBe "success"
+        val annotations = activation.annotations.get
+
+        val limitsObj = JsObject(
+          "key" -> JsString("limits"),
+          "value" -> ActionLimits(TimeLimit(timeLimit), MemoryLimit(memoryLimit), LogLimit(logLimit)).toJson)
+
+        val path = annotations.find { _.fields("key").convertTo[String] == "path" }.get
+
+        path.fields("value").convertTo[String] should fullyMatch regex (s""".*/$name""")
+        annotations should contain(limitsObj)
+      }
+  }
+
+  it should "report error when creating an action with unknown kind" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val rr = assetHelper.withCleaner(wsk.action, "invalid kind", confirmDelete = false) { (action, name) =>
+        action.create(
+          name,
+          Some(TestUtils.getTestActionFilename("echo.js")),
+          kind = Some("foobar"),
+          expectedExitCode = BAD_REQUEST)
+      }
+      rr.stderr should include regex "kind 'foobar' not in Set"
+  }
+
+  it should "report error when creating an action with zip but without kind" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "zipWithNoKind"
+      val zippedPythonAction = Some(TestUtils.getTestActionFilename("python.zip"))
+      val createResult = assetHelper.withCleaner(wsk.action, name, confirmDelete = false) { (action, _) =>
+        action.create(name, zippedPythonAction, expectedExitCode = ANY_ERROR_EXIT)
+      }
+
+      createResult.stderr should include regex "requires specifying the action kind"
+  }
+
+  it should "create, and invoke an action that utilizes an invalid docker container with appropriate error" in withAssetCleaner(
+    wskprops) {
+    val name = "invalidDockerContainer"
+    val containerName = s"bogus${Random.alphanumeric.take(16).mkString.toLowerCase}"
+
+    (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.action, name) {
+        // docker name is a randomly generate string
+        (action, _) =>
+          action.create(name, None, docker = Some(containerName))
+      }
+
+      val run = wsk.action.invoke(name)
+      withActivation(wsk.activation, run) { activation =>
+        activation.response.status shouldBe ActivationResponse.messageForCode(ActivationResponse.ApplicationError)
+        activation.response.result.get
+          .fields("error") shouldBe s"Failed to pull container image '$containerName'.".toJson
+        activation.annotations shouldBe defined
+        val limits = activation.annotations.get.filter(_.fields("key").convertTo[String] == "limits")
+        withClue(limits) {
+          limits.length should be > 0
+          limits(0).fields("value") should not be JsNull
         }
+<<<<<<< HEAD
     }
 
     it should "reject commands that are executed with a missing or invalid parameter or annotation file" in {
@@ -1476,246 +455,1207 @@ class WskBasicUsageTests
                 val stderr = wsk.cli(cmd, expectedExitCode = MISUSE_EXIT).stderr
                 stderr should include(err)
                 stderr should include("Run 'wsk --help' for usage.")
+=======
+      }
+  }
+
+  it should "invoke an action using npm openwhisk" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "hello npm openwhisk"
+    assetHelper.withCleaner(wsk.action, name, confirmDelete = false) { (action, _) =>
+      action.create(name, Some(TestUtils.getTestActionFilename("helloOpenwhiskPackage.js")))
+    }
+
+    val run = wsk.action.invoke(name, Map("ignore_certs" -> true.toJson, "name" -> name.toJson))
+    withActivation(wsk.activation, run) { activation =>
+      activation.response.status shouldBe "success"
+      activation.response.result shouldBe Some(JsObject("delete" -> true.toJson))
+      activation.logs.get.mkString(" ") should include("action list has this many actions")
+    }
+
+    wsk.action.delete(name, expectedExitCode = TestUtils.NOT_FOUND)
+  }
+
+  it should "invoke an action receiving context properties" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val namespace = wsk.namespace.whois()
+    val name = "context"
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, Some(TestUtils.getTestActionFilename("helloContext.js")))
+    }
+
+    val start = Instant.now(Clock.systemUTC()).toEpochMilli
+    val run = wsk.action.invoke(name)
+    withActivation(wsk.activation, run) { activation =>
+      activation.response.status shouldBe "success"
+      val fields = activation.response.result.get.convertTo[Map[String, String]]
+      fields("api_host") shouldBe WhiskProperties.getApiHostForAction
+      fields("api_key") shouldBe wskprops.authKey
+      fields("namespace") shouldBe namespace
+      fields("action_name") shouldBe s"/$namespace/$name"
+      fields("activation_id") shouldBe activation.activationId
+      fields("deadline").toLong should be >= start
+    }
+  }
+
+  it should "invoke an action successfully with options --blocking and --result" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "invokeResult"
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, Some(TestUtils.getTestActionFilename("echo.js")))
+      }
+      val args = Map("hello" -> "Robert".toJson)
+      val run = wsk.action.invoke(name, args, blocking = true, result = true)
+      run.stdout.parseJson shouldBe args.toJson
+  }
+
+  it should "invoke an action that returns a result by the deadline" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "deadline"
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, Some(TestUtils.getTestActionFilename("helloDeadline.js")), timeout = Some(3 seconds))
+      }
+
+      val run = wsk.action.invoke(name)
+      withActivation(wsk.activation, run) { activation =>
+        activation.response.status shouldBe "success"
+        activation.response.result shouldBe Some(JsObject("timedout" -> true.toJson))
+      }
+  }
+
+  it should "invoke an action twice, where the first times out but the second does not and should succeed" in withAssetCleaner(
+    wskprops) {
+    // this test issues two activations: the first is forced to time out and not return a result by its deadline (ie it does not resolve
+    // its promise). The invoker should reclaim its container so that a second activation of the same action (which must happen within a
+    // short period of time (seconds, not minutes) is allocated a fresh container and hence runs as expected (vs. hitting in the container
+    // cache and reusing a bad container).
+    (wp, assetHelper) =>
+      val name = "timeout"
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, Some(TestUtils.getTestActionFilename("helloDeadline.js")), timeout = Some(3 seconds))
+      }
+
+      val start = Instant.now(Clock.systemUTC()).toEpochMilli
+      val hungRun = wsk.action.invoke(name, Map("forceHang" -> true.toJson))
+      withActivation(wsk.activation, hungRun) { activation =>
+        // the first action must fail with a timeout error
+        activation.response.status shouldBe ActivationResponse.messageForCode(ActivationResponse.ApplicationError)
+        activation.response.result shouldBe Some(
+          JsObject("error" -> Messages.timedoutActivation(3 seconds, false).toJson))
+      }
+
+      // run the action again, this time without forcing it to timeout
+      // it should succeed because it ran in a fresh container
+      val goodRun = wsk.action.invoke(name, Map("forceHang" -> false.toJson))
+      withActivation(wsk.activation, goodRun) { activation =>
+        // the first action must fail with a timeout error
+        activation.response.status shouldBe "success"
+        activation.response.result shouldBe Some(JsObject("timedout" -> true.toJson))
+      }
+  }
+
+  it should "ensure --web flags set the proper annotations" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "webaction"
+    val file = Some(TestUtils.getTestActionFilename("echo.js"))
+
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, file)
+    }
+
+    Seq("true", "faLse", "tRue", "nO", "yEs", "no", "raw", "NO", "Raw").foreach { flag =>
+      val webEnabled = flag.toLowerCase == "true" || flag.toLowerCase == "yes"
+      val rawEnabled = flag.toLowerCase == "raw"
+
+      wsk.action.create(name, file, web = Some(flag), update = true)
+
+      val stdout = wsk.action.get(name, fieldFilter = Some("annotations")).stdout
+      assert(stdout.startsWith(s"ok: got action $name, displaying field annotations\n"))
+      removeCLIHeader(stdout).parseJson shouldBe JsArray(
+        JsObject("key" -> JsString("exec"), "value" -> JsString("nodejs:6")),
+        JsObject("key" -> JsString("web-export"), "value" -> JsBoolean(webEnabled || rawEnabled)),
+        JsObject("key" -> JsString("raw-http"), "value" -> JsBoolean(rawEnabled)),
+        JsObject("key" -> JsString("final"), "value" -> JsBoolean(webEnabled || rawEnabled)))
+    }
+  }
+
+  it should "ensure action update with --web flag only copies existing annotations when new annotations are not provided" in withAssetCleaner(
+    wskprops) { (wp, assetHelper) =>
+    val name = "webaction"
+    val file = Some(TestUtils.getTestActionFilename("echo.js"))
+    val createKey = "createKey"
+    val createValue = JsString("createValue")
+    val updateKey = "updateKey"
+    val updateValue = JsString("updateValue")
+    val origKey = "origKey"
+    val origValue = JsString("origValue")
+    val overwrittenValue = JsString("overwrittenValue")
+    val createAnnots = Map(createKey -> createValue, origKey -> origValue)
+    val updateAnnots = Map(updateKey -> updateValue, origKey -> overwrittenValue)
+
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, file, annotations = createAnnots)
+    }
+
+    wsk.action.create(name, file, web = Some("true"), update = true)
+
+    val existinAnnots = wsk.action.get(name, fieldFilter = Some("annotations")).stdout
+    assert(existinAnnots.startsWith(s"ok: got action $name, displaying field annotations\n"))
+    removeCLIHeader(existinAnnots).parseJson shouldBe JsArray(
+      JsObject("key" -> JsString("web-export"), "value" -> JsBoolean(true)),
+      JsObject("key" -> JsString(origKey), "value" -> origValue),
+      JsObject("key" -> JsString("raw-http"), "value" -> JsBoolean(false)),
+      JsObject("key" -> JsString("final"), "value" -> JsBoolean(true)),
+      JsObject("key" -> JsString(createKey), "value" -> createValue),
+      JsObject("key" -> JsString("exec"), "value" -> JsString("nodejs:6")))
+
+    wsk.action.create(name, file, web = Some("true"), update = true, annotations = updateAnnots)
+
+    val updatedAnnots = wsk.action.get(name, fieldFilter = Some("annotations")).stdout
+    assert(updatedAnnots.startsWith(s"ok: got action $name, displaying field annotations\n"))
+    removeCLIHeader(updatedAnnots).parseJson shouldBe JsArray(
+      JsObject("key" -> JsString("web-export"), "value" -> JsBoolean(true)),
+      JsObject("key" -> JsString(origKey), "value" -> overwrittenValue),
+      JsObject("key" -> JsString(updateKey), "value" -> updateValue),
+      JsObject("key" -> JsString("raw-http"), "value" -> JsBoolean(false)),
+      JsObject("key" -> JsString("final"), "value" -> JsBoolean(true)),
+      JsObject("key" -> JsString("exec"), "value" -> JsString("nodejs:6")))
+  }
+
+  it should "ensure action update creates an action with --web flag" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "webaction"
+      val file = Some(TestUtils.getTestActionFilename("echo.js"))
+
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, file, web = Some("true"), update = true)
+      }
+
+      val stdout = wsk.action.get(name, fieldFilter = Some("annotations")).stdout
+      assert(stdout.startsWith(s"ok: got action $name, displaying field annotations\n"))
+      removeCLIHeader(stdout).parseJson shouldBe JsArray(
+        JsObject("key" -> JsString("web-export"), "value" -> JsBoolean(true)),
+        JsObject("key" -> JsString("raw-http"), "value" -> JsBoolean(false)),
+        JsObject("key" -> JsString("final"), "value" -> JsBoolean(true)),
+        JsObject("key" -> JsString("exec"), "value" -> JsString("nodejs:6")))
+  }
+
+  it should "reject action create and update with invalid web flag input" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "webaction"
+      val file = Some(TestUtils.getTestActionFilename("echo.js"))
+      val invalidInput = "bogus"
+      val errorMsg =
+        s"Invalid argument '$invalidInput' for --web flag. Valid input consist of 'yes', 'true', 'raw', 'false', or 'no'."
+      wsk.action.create(name, file, web = Some(invalidInput), expectedExitCode = MISUSE_EXIT).stderr should include(
+        errorMsg)
+      wsk.action
+        .create(name, file, web = Some(invalidInput), update = true, expectedExitCode = MISUSE_EXIT)
+        .stderr should include(errorMsg)
+  }
+
+  it should "invoke action while not encoding &, <, > characters" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "nonescape"
+    val file = Some(TestUtils.getTestActionFilename("hello.js"))
+    val nonescape = "&<>"
+    val input = Map("payload" -> nonescape.toJson)
+    val output = JsObject("payload" -> JsString(s"hello, $nonescape!"))
+
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, file)
+    }
+
+    withActivation(wsk.activation, wsk.action.invoke(name, parameters = input)) { activation =>
+      activation.response.success shouldBe true
+      activation.response.result shouldBe Some(output)
+      activation.logs.toList.flatten.filter(_.contains(nonescape)).length shouldBe 1
+    }
+  }
+
+  it should "get an action URL" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val actionName = "action name@_-."
+    val packageName = "package name@_-."
+    val defaultPackageName = "default"
+    val webActionName = "web action name@_-."
+    val nonExistentActionName = "non-existence action"
+    val packagedAction = s"$packageName/$actionName"
+    val packagedWebAction = s"$packageName/$webActionName"
+    val namespace = wsk.namespace.whois()
+    val encodedActionName = URLEncoder.encode(actionName, StandardCharsets.UTF_8.name).replace("+", "%20")
+    val encodedPackageName = URLEncoder.encode(packageName, StandardCharsets.UTF_8.name).replace("+", "%20")
+    val encodedWebActionName = URLEncoder.encode(webActionName, StandardCharsets.UTF_8.name).replace("+", "%20")
+    val encodedNamespace = URLEncoder.encode(namespace, StandardCharsets.UTF_8.name).replace("+", "%20")
+    val actionPath = "https://%s/api/%s/namespaces/%s/actions/%s"
+    val packagedActionPath = s"$actionPath/%s"
+    val webActionPath = "https://%s/api/%s/web/%s/%s/%s"
+
+    assetHelper.withCleaner(wsk.action, actionName) { (action, _) =>
+      action.create(actionName, defaultAction)
+    }
+
+    assetHelper.withCleaner(wsk.action, webActionName) { (action, _) =>
+      action.create(webActionName, defaultAction, web = Some("true"))
+    }
+
+    assetHelper.withCleaner(wsk.pkg, packageName) { (pkg, _) =>
+      pkg.create(packageName)
+    }
+
+    assetHelper.withCleaner(wsk.action, packagedAction) { (action, _) =>
+      action.create(packagedAction, defaultAction)
+    }
+
+    assetHelper.withCleaner(wsk.action, packagedWebAction) { (action, _) =>
+      action.create(packagedWebAction, defaultAction, web = Some("true"))
+    }
+
+    wsk.action.get(actionName, url = Some(true)).stdout should include(
+      actionPath.format(wskprops.apihost, wskprops.apiversion, encodedNamespace, encodedActionName))
+
+    // Ensure url flag works when a field filter and summary flag are specified
+    wsk.action.get(actionName, url = Some(true), fieldFilter = Some("field"), summary = true).stdout should include(
+      actionPath.format(wskprops.apihost, wskprops.apiversion, encodedNamespace, encodedActionName))
+
+    wsk.action.get(webActionName, url = Some(true)).stdout should include(
+      webActionPath
+        .format(wskprops.apihost, wskprops.apiversion, encodedNamespace, defaultPackageName, encodedWebActionName))
+
+    wsk.action.get(packagedAction, url = Some(true)).stdout should include(
+      packagedActionPath
+        .format(wskprops.apihost, wskprops.apiversion, encodedNamespace, encodedPackageName, encodedActionName))
+
+    wsk.action.get(packagedWebAction, url = Some(true)).stdout should include(
+      webActionPath
+        .format(wskprops.apihost, wskprops.apiversion, encodedNamespace, encodedPackageName, encodedWebActionName))
+
+    wsk.action.get(nonExistentActionName, url = Some(true), expectedExitCode = NOT_FOUND)
+  }
+  it should "limit length of HTTP request and response bodies for --verbose" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "limitVerbose"
+      val msg = "will be truncated"
+      val params = Seq("-p", "bigValue", "a" * 1000)
+
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, Some(TestUtils.getTestActionFilename("echo.js")))
+      }
+
+      val truncated = wsk
+        .cli(Seq("action", "invoke", name, "-b", "-v", "--auth", wskprops.authKey) ++ params ++ wskprops.overrides)
+        .stdout
+      msg.r.findAllIn(truncated).length shouldBe 2
+
+      val notTruncated = wsk
+        .cli(Seq("action", "invoke", name, "-b", "-d", "--auth", wskprops.authKey) ++ params ++ wskprops.overrides)
+        .stdout
+      msg.r.findAllIn(notTruncated).length shouldBe 0
+  }
+
+  it should "denote bound and finalized action parameters for action summaries" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val nameBoundParams = "actionBoundParams"
+      val nameFinalParams = "actionFinalParams"
+      val paramAnnot = "paramAnnot"
+      val paramOverlap = "paramOverlap"
+      val paramBound = "paramBound"
+      val annots = Map(
+        "parameters" -> JsArray(
+          JsObject("name" -> JsString(paramAnnot), "description" -> JsString("Annotated")),
+          JsObject("name" -> JsString(paramOverlap), "description" -> JsString("Annotated And Bound"))))
+      val annotsFinal = Map(
+        "final" -> JsBoolean(true),
+        "parameters" -> JsArray(
+          JsObject("name" -> JsString(paramAnnot), "description" -> JsString("Annotated Parameter description")),
+          JsObject("name" -> JsString(paramOverlap), "description" -> JsString("Annotated And Bound"))))
+      val paramsBound = Map(paramBound -> JsString("Bound"), paramOverlap -> JsString("Bound And Annotated"))
+
+      assetHelper.withCleaner(wsk.action, nameBoundParams) { (action, _) =>
+        action.create(nameBoundParams, defaultAction, annotations = annots, parameters = paramsBound)
+      }
+      assetHelper.withCleaner(wsk.action, nameFinalParams) { (action, _) =>
+        action.create(nameFinalParams, defaultAction, annotations = annotsFinal, parameters = paramsBound)
+      }
+
+      val stdoutBound = wsk.action.get(nameBoundParams, summary = true).stdout
+      val stdoutFinal = wsk.action.get(nameFinalParams, summary = true).stdout
+
+      stdoutBound should include(s"(parameters: $paramAnnot, *$paramBound, *$paramOverlap)")
+      stdoutFinal should include(s"(parameters: $paramAnnot, **$paramBound, **$paramOverlap)")
+  }
+
+  it should "create, and get an action summary without a description and/or defined parameters" in withAssetCleaner(
+    wskprops) { (wp, assetHelper) =>
+    val actNameNoParams = "actionNoParams"
+    val actNameNoDesc = "actionNoDesc"
+    val actNameNoDescOrParams = "actionNoDescOrParams"
+    val desc = "Action description"
+    val descFromParamsResp = "Returns a result based on parameters"
+    val annotsNoParams = Map("description" -> JsString(desc))
+    val annotsNoDesc = Map(
+      "parameters" -> JsArray(
+        JsObject("name" -> JsString("paramName1"), "description" -> JsString("Parameter description 1")),
+        JsObject("name" -> JsString("paramName2"), "description" -> JsString("Parameter description 2"))))
+
+    assetHelper.withCleaner(wsk.action, actNameNoDesc) { (action, _) =>
+      action.create(actNameNoDesc, defaultAction, annotations = annotsNoDesc)
+    }
+    assetHelper.withCleaner(wsk.action, actNameNoParams) { (action, _) =>
+      action.create(actNameNoParams, defaultAction, annotations = annotsNoParams)
+    }
+    assetHelper.withCleaner(wsk.action, actNameNoDescOrParams) { (action, _) =>
+      action.create(actNameNoDescOrParams, defaultAction)
+    }
+
+    val stdoutNoDesc = wsk.action.get(actNameNoDesc, summary = true).stdout
+    val stdoutNoParams = wsk.action.get(actNameNoParams, summary = true).stdout
+    val stdoutNoDescOrParams = wsk.action.get(actNameNoDescOrParams, summary = true).stdout
+    val namespace = wsk.namespace.whois()
+
+    stdoutNoDesc should include regex (s"(?i)action /${namespace}/${actNameNoDesc}: ${descFromParamsResp} paramName1 and paramName2\\s*\\(parameters: paramName1, paramName2\\)")
+    stdoutNoParams should include regex (s"(?i)action /${namespace}/${actNameNoParams}: ${desc}\\s*\\(parameters: none defined\\)")
+    stdoutNoDescOrParams should include regex (s"(?i)action /${namespace}/${actNameNoDescOrParams}\\s*\\(parameters: none defined\\)")
+  }
+
+  behavior of "Wsk packages"
+
+  it should "create, and delete a package" in {
+    val name = "createDeletePackage"
+    wsk.pkg.create(name).stdout should include(s"ok: created package $name")
+    wsk.pkg.delete(name).stdout should include(s"ok: deleted package $name")
+  }
+
+  it should "create, and get a package to verify parameter and annotation parsing" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "packageAnnotAndParamParsing"
+
+      assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
+        pkg.create(name, annotations = getValidJSONTestArgInput, parameters = getValidJSONTestArgInput)
+      }
+
+      val stdout = wsk.pkg.get(name).stdout
+      assert(stdout.startsWith(s"ok: got package $name\n"))
+
+      val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
+      val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
+      val escapedJSONArr = getValidJSONTestArgOutput.convertTo[JsArray].elements
+
+      for (expectedItem <- escapedJSONArr) {
+        receivedParams should contain(expectedItem)
+        receivedAnnots should contain(expectedItem)
+      }
+  }
+
+  it should "create, and get a package to verify file parameter and annotation parsing" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "packageAnnotAndParamFileParsing"
+      val file = Some(TestUtils.getTestActionFilename("hello.js"))
+      val argInput = Some(TestUtils.getTestActionFilename("validInput1.json"))
+
+      assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
+        pkg.create(name, annotationFile = argInput, parameterFile = argInput)
+      }
+
+      val stdout = wsk.pkg.get(name).stdout
+      assert(stdout.startsWith(s"ok: got package $name\n"))
+
+      val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
+      val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
+      val escapedJSONArr = getJSONFileOutput.convertTo[JsArray].elements
+
+      for (expectedItem <- escapedJSONArr) {
+        receivedParams should contain(expectedItem)
+        receivedAnnots should contain(expectedItem)
+      }
+  }
+
+  it should "create a package with the proper parameter and annotation escapes" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "packageEscapses"
+
+      assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
+        pkg.create(name, parameters = getEscapedJSONTestArgInput, annotations = getEscapedJSONTestArgInput)
+      }
+
+      val stdout = wsk.pkg.get(name).stdout
+      assert(stdout.startsWith(s"ok: got package $name\n"))
+
+      val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
+      val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
+      val escapedJSONArr = getEscapedJSONTestArgOutput.convertTo[JsArray].elements
+
+      for (expectedItem <- escapedJSONArr) {
+        receivedParams should contain(expectedItem)
+        receivedAnnots should contain(expectedItem)
+      }
+  }
+
+  it should "report conformance error accessing action as package" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "aAsP"
+    val file = Some(TestUtils.getTestActionFilename("hello.js"))
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, file)
+    }
+
+    wsk.pkg.get(name, expectedExitCode = CONFLICT).stderr should include(Messages.conformanceMessage)
+
+    wsk.pkg.bind(name, "bogus", expectedExitCode = CONFLICT).stderr should include(Messages.requestedBindingIsNotValid)
+
+    wsk.pkg.bind("bogus", "alsobogus", expectedExitCode = BAD_REQUEST).stderr should include(
+      Messages.bindingDoesNotExist)
+
+  }
+
+  it should "create, and get a package summary without a description and/or parameters" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val pkgNoDesc = "pkgNoDesc"
+      val pkgNoParams = "pkgNoParams"
+      val pkgNoDescOrParams = "pkgNoDescOrParams"
+      val pkgDesc = "Package description"
+      val descFromParams = "Returns a result based on parameters"
+      val namespace = wsk.namespace.whois()
+      val qualpkgNoDesc = s"/${namespace}/${pkgNoDesc}"
+      val qualpkgNoParams = s"/${namespace}/${pkgNoParams}"
+      val qualpkgNoDescOrParams = s"/${namespace}/${pkgNoDescOrParams}"
+
+      val pkgAnnotsNoParams = Map("description" -> JsString(pkgDesc))
+      val pkgAnnotsNoDesc = Map(
+        "parameters" -> JsArray(
+          JsObject("name" -> JsString("paramName1"), "description" -> JsString("Parameter description 1")),
+          JsObject("name" -> JsString("paramName2"), "description" -> JsString("Parameter description 2"))))
+
+      assetHelper.withCleaner(wsk.pkg, pkgNoDesc) { (pkg, _) =>
+        pkg.create(pkgNoDesc, annotations = pkgAnnotsNoDesc)
+      }
+      assetHelper.withCleaner(wsk.pkg, pkgNoParams) { (pkg, _) =>
+        pkg.create(pkgNoParams, annotations = pkgAnnotsNoParams)
+      }
+      assetHelper.withCleaner(wsk.pkg, pkgNoDescOrParams) { (pkg, _) =>
+        pkg.create(pkgNoDescOrParams)
+      }
+
+      val stdoutNoDescPkg = wsk.pkg.get(pkgNoDesc, summary = true).stdout
+      val stdoutNoParamsPkg = wsk.pkg.get(pkgNoParams, summary = true).stdout
+      val stdoutNoDescOrParams = wsk.pkg.get(pkgNoDescOrParams, summary = true).stdout
+
+      stdoutNoDescPkg should include regex (s"(?i)package ${qualpkgNoDesc}: ${descFromParams} paramName1 and paramName2\\s*\\(parameters: paramName1, paramName2\\)")
+      stdoutNoParamsPkg should include regex (s"(?i)package ${qualpkgNoParams}: ${pkgDesc}\\s*\\(parameters: none defined\\)")
+      stdoutNoDescOrParams should include regex (s"(?i)package ${qualpkgNoDescOrParams}\\s*\\(parameters: none defined\\)")
+  }
+
+  it should "denote bound package parameters for package summaries" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val pkgBoundParams = "pkgBoundParams"
+    val pkgParamAnnot = "pkgParamAnnot"
+    val pkgParamOverlap = "pkgParamOverlap"
+    val pkgParamBound = "pkgParamBound"
+    val pkgAnnots = Map(
+      "parameters" -> JsArray(
+        JsObject("name" -> JsString(pkgParamAnnot), "description" -> JsString("Annotated")),
+        JsObject("name" -> JsString(pkgParamOverlap), "description" -> JsString("Annotated And Bound"))))
+    val pkgParamsBound = Map(pkgParamBound -> JsString("Bound"), pkgParamOverlap -> JsString("Bound And Annotated"))
+
+    assetHelper.withCleaner(wsk.pkg, pkgBoundParams) { (pkg, _) =>
+      pkg.create(pkgBoundParams, annotations = pkgAnnots, parameters = pkgParamsBound)
+    }
+
+    val pkgStdoutBound = wsk.pkg.get(pkgBoundParams, summary = true).stdout
+
+    pkgStdoutBound should include(s"(parameters: $pkgParamAnnot, *$pkgParamBound, *$pkgParamOverlap)")
+  }
+
+  behavior of "Wsk triggers"
+
+  it should "create, and get a trigger to verify parameter and annotation parsing" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "triggerAnnotAndParamParsing"
+
+      assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
+        trigger.create(name, annotations = getValidJSONTestArgInput, parameters = getValidJSONTestArgInput)
+      }
+
+      val stdout = wsk.trigger.get(name).stdout
+      assert(stdout.startsWith(s"ok: got trigger $name\n"))
+
+      val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
+      val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
+      val escapedJSONArr = getValidJSONTestArgOutput.convertTo[JsArray].elements
+
+      for (expectedItem <- escapedJSONArr) {
+        receivedParams should contain(expectedItem)
+        receivedAnnots should contain(expectedItem)
+      }
+  }
+
+  it should "create, and get a trigger to verify file parameter and annotation parsing" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "triggerAnnotAndParamFileParsing"
+      val file = Some(TestUtils.getTestActionFilename("hello.js"))
+      val argInput = Some(TestUtils.getTestActionFilename("validInput1.json"))
+
+      assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
+        trigger.create(name, annotationFile = argInput, parameterFile = argInput)
+      }
+
+      val stdout = wsk.trigger.get(name).stdout
+      assert(stdout.startsWith(s"ok: got trigger $name\n"))
+
+      val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
+      val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
+      val escapedJSONArr = getJSONFileOutput.convertTo[JsArray].elements
+
+      for (expectedItem <- escapedJSONArr) {
+        receivedParams should contain(expectedItem)
+        receivedAnnots should contain(expectedItem)
+      }
+  }
+
+  it should "display a trigger summary when --summary flag is used with 'wsk trigger get'" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val triggerName = "mySummaryTrigger"
+      assetHelper.withCleaner(wsk.trigger, triggerName, confirmDelete = false) { (trigger, name) =>
+        trigger.create(name)
+      }
+
+      // Summary namespace should match one of the allowable namespaces (typically 'guest')
+      val ns = wsk.namespace.whois()
+      val stdout = wsk.trigger.get(triggerName, summary = true).stdout
+      stdout should include regex (s"(?i)trigger\\s+/$ns/$triggerName")
+  }
+
+  it should "create a trigger with the proper parameter and annotation escapes" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "triggerEscapes"
+
+      assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
+        trigger.create(name, parameters = getEscapedJSONTestArgInput, annotations = getEscapedJSONTestArgInput)
+      }
+
+      val stdout = wsk.trigger.get(name).stdout
+      assert(stdout.startsWith(s"ok: got trigger $name\n"))
+
+      val receivedParams = wsk.parseJsonString(stdout).fields("parameters").convertTo[JsArray].elements
+      val receivedAnnots = wsk.parseJsonString(stdout).fields("annotations").convertTo[JsArray].elements
+      val escapedJSONArr = getEscapedJSONTestArgOutput.convertTo[JsArray].elements
+
+      for (expectedItem <- escapedJSONArr) {
+        receivedParams should contain(expectedItem)
+        receivedAnnots should contain(expectedItem)
+      }
+  }
+
+  it should "not create a trigger when feed fails to initialize" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    assetHelper.withCleaner(wsk.trigger, "badfeed", confirmDelete = false) { (trigger, name) =>
+      trigger.create(name, feed = Some(s"bogus"), expectedExitCode = ANY_ERROR_EXIT).exitCode should equal(NOT_FOUND)
+      trigger.get(name, expectedExitCode = NOT_FOUND)
+
+      trigger.create(name, feed = Some(s"bogus/feed"), expectedExitCode = ANY_ERROR_EXIT).exitCode should equal(
+        NOT_FOUND)
+      trigger.get(name, expectedExitCode = NOT_FOUND)
+    }
+  }
+
+  it should "denote bound trigger parameters for trigger summaries" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val trgBoundParams = "trgBoundParams"
+    val trgParamAnnot = "trgParamAnnot"
+    val trgParamOverlap = "trgParamOverlap"
+    val trgParamBound = "trgParamBound"
+    val trgAnnots = Map(
+      "parameters" -> JsArray(
+        JsObject("name" -> JsString(trgParamAnnot), "description" -> JsString("Annotated")),
+        JsObject("name" -> JsString(trgParamOverlap), "description" -> JsString("Annotated And Bound"))))
+    val trgParamsBound = Map(trgParamBound -> JsString("Bound"), trgParamOverlap -> JsString("Bound And Annotated"))
+
+    assetHelper.withCleaner(wsk.trigger, trgBoundParams) { (trigger, _) =>
+      trigger.create(trgBoundParams, annotations = trgAnnots, parameters = trgParamsBound)
+    }
+
+    val trgStdoutBound = wsk.trigger.get(trgBoundParams, summary = true).stdout
+
+    trgStdoutBound should include(s"(parameters: $trgParamAnnot, *$trgParamBound, *$trgParamOverlap)")
+  }
+
+  it should "create, and get a trigger summary without a description and/or parameters" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val trgNoDesc = "trgNoDesc"
+      val trgNoParams = "trgNoParams"
+      val trgNoDescOrParams = "trgNoDescOrParams"
+      val trgDesc = "Package description"
+      val descFromParams = "Returns a result based on parameters"
+      val namespace = wsk.namespace.whois()
+      val qualtrgNoDesc = s"/${namespace}/${trgNoDesc}"
+      val qualtrgNoParams = s"/${namespace}/${trgNoParams}"
+      val qualtrgNoDescOrParams = s"/${namespace}/${trgNoDescOrParams}"
+
+      val trgAnnotsNoParams = Map("description" -> JsString(trgDesc))
+      val trgAnnotsNoDesc = Map(
+        "parameters" -> JsArray(
+          JsObject("name" -> JsString("paramName1"), "description" -> JsString("Parameter description 1")),
+          JsObject("name" -> JsString("paramName2"), "description" -> JsString("Parameter description 2"))))
+
+      assetHelper.withCleaner(wsk.trigger, trgNoDesc) { (trigger, _) =>
+        trigger.create(trgNoDesc, annotations = trgAnnotsNoDesc)
+      }
+      assetHelper.withCleaner(wsk.trigger, trgNoParams) { (trigger, _) =>
+        trigger.create(trgNoParams, annotations = trgAnnotsNoParams)
+      }
+      assetHelper.withCleaner(wsk.trigger, trgNoDescOrParams) { (trigger, _) =>
+        trigger.create(trgNoDescOrParams)
+      }
+
+      val stdoutNoDescPkg = wsk.trigger.get(trgNoDesc, summary = true).stdout
+      val stdoutNoParamsPkg = wsk.trigger.get(trgNoParams, summary = true).stdout
+      val stdoutNoDescOrParams = wsk.trigger.get(trgNoDescOrParams, summary = true).stdout
+
+      stdoutNoDescPkg should include regex (s"(?i)trigger ${qualtrgNoDesc}: ${descFromParams} paramName1 and paramName2\\s*\\(parameters: paramName1, paramName2\\)")
+      stdoutNoParamsPkg should include regex (s"(?i)trigger ${qualtrgNoParams}: ${trgDesc}\\s*\\(parameters: none defined\\)")
+      stdoutNoDescOrParams should include regex (s"(?i)trigger ${qualtrgNoDescOrParams}\\s*\\(parameters: none defined\\)")
+  }
+
+  behavior of "Wsk entity list formatting"
+
+  it should "create, and list a package with a long name" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "x" * 70
+    assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
+      pkg.create(name)
+    }
+    retry({
+      wsk.pkg.list().stdout should include(s"$name private")
+    }, 5, Some(1 second))
+  }
+
+  it should "create, and list an action with a long name" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "x" * 70
+    val file = Some(TestUtils.getTestActionFilename("hello.js"))
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, file)
+    }
+    retry({
+      wsk.action.list().stdout should include(s"$name private nodejs")
+    }, 5, Some(1 second))
+  }
+
+  it should "create, and list a trigger with a long name" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "x" * 70
+    assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
+      trigger.create(name)
+    }
+    retry({
+      wsk.trigger.list().stdout should include(s"$name private")
+    }, 5, Some(1 second))
+  }
+
+  it should "create, and list a rule with a long name" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val ruleName = "x" * 70
+    val triggerName = "listRulesTrigger"
+    val actionName = "listRulesAction";
+    assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, name) =>
+      trigger.create(name)
+    }
+    assetHelper.withCleaner(wsk.action, actionName) { (action, name) =>
+      action.create(name, defaultAction)
+    }
+    assetHelper.withCleaner(wsk.rule, ruleName) { (rule, name) =>
+      rule.create(name, trigger = triggerName, action = actionName)
+    }
+    retry({
+      wsk.rule.list().stdout should include(s"$ruleName private")
+    }, 5, Some(1 second))
+  }
+
+  it should "return a list of alphabetized actions" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    // Declare 4 actions, create them out of alphabetical order
+    val actionName = "actionAlphaTest"
+    for (i <- 1 to 3) {
+      val name = s"$actionName$i"
+      assetHelper.withCleaner(wsk.action, name) { (action, name) =>
+        action.create(name, defaultAction)
+      }
+    }
+    retry({
+      val original = wsk.action.list(nameSort = Some(true)).stdout
+      // Create list with action names in correct order
+      val scalaSorted = List(s"${actionName}1", s"${actionName}2", s"${actionName}3")
+      // Filter out everything not previously created
+      val regex = s"${actionName}[1-3]".r
+      // Retrieve action names into list as found in original
+      val list = (regex.findAllMatchIn(original)).toList
+      scalaSorted.toString shouldEqual list.toString
+    }, 5, Some(1 second))
+  }
+
+  it should "return an alphabetized list with default package actions on top" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      // Declare 4 actions, create them out of alphabetical order
+      val actionName = "actionPackageAlphaTest"
+      val packageName = "packageAlphaTest"
+      assetHelper.withCleaner(wsk.action, actionName) { (action, actionName) =>
+        action.create(actionName, defaultAction)
+      }
+      assetHelper.withCleaner(wsk.pkg, packageName) { (pkg, packageName) =>
+        pkg.create(packageName)
+      }
+      for (i <- 1 to 3) {
+        val name = s"${packageName}/${actionName}$i"
+        assetHelper.withCleaner(wsk.action, name) { (action, name) =>
+          action.create(name, defaultAction)
+>>>>>>> c10e681... Apply standard scala formatting. (#2650)
         }
-    }
-
-    it should "reject commands that are executed with not enough param or annot arguments" in {
-        val invalidParamMsg = "Arguments for '-p' must be a key/value pair"
-        val invalidAnnotMsg = "Arguments for '-a' must be a key/value pair"
-        val invalidParamFileMsg = "An argument must be provided for '-P'"
-        val invalidAnnotFileMsg = "An argument must be provided for '-A'"
-        val invalidArgs = Seq(
-            (Seq("action", "create", "actionName", "-p"), invalidParamMsg),
-            (Seq("action", "create", "actionName", "-p", "key"), invalidParamMsg),
-            (Seq("action", "create", "actionName", "-P"), invalidParamFileMsg),
-            (Seq("action", "update", "actionName", "-p"), invalidParamMsg),
-            (Seq("action", "update", "actionName", "-p", "key"), invalidParamMsg),
-            (Seq("action", "update", "actionName", "-P"), invalidParamFileMsg),
-            (Seq("action", "invoke", "actionName", "-p"), invalidParamMsg),
-            (Seq("action", "invoke", "actionName", "-p", "key"), invalidParamMsg),
-            (Seq("action", "invoke", "actionName", "-P"), invalidParamFileMsg),
-            (Seq("action", "create", "actionName", "-a"), invalidAnnotMsg),
-            (Seq("action", "create", "actionName", "-a", "key"), invalidAnnotMsg),
-            (Seq("action", "create", "actionName", "-A"), invalidAnnotFileMsg),
-            (Seq("action", "update", "actionName", "-a"), invalidAnnotMsg),
-            (Seq("action", "update", "actionName", "-a", "key"), invalidAnnotMsg),
-            (Seq("action", "update", "actionName", "-A"), invalidAnnotFileMsg),
-            (Seq("action", "invoke", "actionName", "-a"), invalidAnnotMsg),
-            (Seq("action", "invoke", "actionName", "-a", "key"), invalidAnnotMsg),
-            (Seq("action", "invoke", "actionName", "-A"), invalidAnnotFileMsg),
-            (Seq("package", "create", "packageName", "-p"), invalidParamMsg),
-            (Seq("package", "create", "packageName", "-p", "key"), invalidParamMsg),
-            (Seq("package", "create", "packageName", "-P"), invalidParamFileMsg),
-            (Seq("package", "update", "packageName", "-p"), invalidParamMsg),
-            (Seq("package", "update", "packageName", "-p", "key"), invalidParamMsg),
-            (Seq("package", "update", "packageName", "-P"), invalidParamFileMsg),
-            (Seq("package", "bind", "packageName", "boundPackageName", "-p"), invalidParamMsg),
-            (Seq("package", "bind", "packageName", "boundPackageName", "-p", "key"), invalidParamMsg),
-            (Seq("package", "bind", "packageName", "boundPackageName", "-P"), invalidParamFileMsg),
-            (Seq("package", "create", "packageName", "-a"), invalidAnnotMsg),
-            (Seq("package", "create", "packageName", "-a", "key"), invalidAnnotMsg),
-            (Seq("package", "create", "packageName", "-A"), invalidAnnotFileMsg),
-            (Seq("package", "update", "packageName", "-a"), invalidAnnotMsg),
-            (Seq("package", "update", "packageName", "-a", "key"), invalidAnnotMsg),
-            (Seq("package", "update", "packageName", "-A"), invalidAnnotFileMsg),
-            (Seq("package", "bind", "packageName", "boundPackageName", "-a"), invalidAnnotMsg),
-            (Seq("package", "bind", "packageName", "boundPackageName", "-a", "key"), invalidAnnotMsg),
-            (Seq("package", "bind", "packageName", "boundPackageName", "-A"), invalidAnnotFileMsg),
-            (Seq("trigger", "create", "triggerName", "-p"), invalidParamMsg),
-            (Seq("trigger", "create", "triggerName", "-p", "key"), invalidParamMsg),
-            (Seq("trigger", "create", "triggerName", "-P"), invalidParamFileMsg),
-            (Seq("trigger", "update", "triggerName", "-p"), invalidParamMsg),
-            (Seq("trigger", "update", "triggerName", "-p", "key"), invalidParamMsg),
-            (Seq("trigger", "update", "triggerName", "-P"), invalidParamFileMsg),
-            (Seq("trigger", "fire", "triggerName", "-p"), invalidParamMsg),
-            (Seq("trigger", "fire", "triggerName", "-p", "key"), invalidParamMsg),
-            (Seq("trigger", "fire", "triggerName", "-P"), invalidParamFileMsg),
-            (Seq("trigger", "create", "triggerName", "-a"), invalidAnnotMsg),
-            (Seq("trigger", "create", "triggerName", "-a", "key"), invalidAnnotMsg),
-            (Seq("trigger", "create", "triggerName", "-A"), invalidAnnotFileMsg),
-            (Seq("trigger", "update", "triggerName", "-a"), invalidAnnotMsg),
-            (Seq("trigger", "update", "triggerName", "-a", "key"), invalidAnnotMsg),
-            (Seq("trigger", "update", "triggerName", "-A"), invalidAnnotFileMsg),
-            (Seq("trigger", "fire", "triggerName", "-a"), invalidAnnotMsg),
-            (Seq("trigger", "fire", "triggerName", "-a", "key"), invalidAnnotMsg),
-            (Seq("trigger", "fire", "triggerName", "-A"), invalidAnnotFileMsg))
-
-        invalidArgs foreach {
-            case (cmd, err) =>
-                val stderr = wsk.cli(cmd, expectedExitCode = ERROR_EXIT).stderr
-                stderr should include(err)
-                stderr should include("Run 'wsk --help' for usage.")
+      }
+      retry(
+        {
+          val original = wsk.action.list(nameSort = Some(true)).stdout
+          // Create list with action names in correct order
+          val scalaSorted = List(
+            s"$actionName",
+            s"${packageName}/${actionName}1",
+            s"${packageName}/${actionName}2",
+            s"${packageName}/${actionName}3")
+          // Filter out everything not previously created
+          val regexNoPackage = s"$actionName".r
+          val regexWithPackage = s"${packageName}/${actionName}[1-3]".r
+          // Retrieve action names into list as found in original
+          val list = regexNoPackage.findFirstIn(original).get :: (regexWithPackage.findAllMatchIn(original)).toList
+          scalaSorted.toString shouldEqual list.toString
+        },
+        5,
+        Some(1 second))
+  }
+
+  it should "return a list of alphabetized packages" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    // Declare 3 packages, create them out of alphabetical order
+    val packageName = "pkgAlphaTest"
+    for (i <- 1 to 3) {
+      val name = s"$packageName$i"
+      assetHelper.withCleaner(wsk.pkg, name) { (pkg, name) =>
+        pkg.create(name)
+      }
+    }
+    retry({
+      val original = wsk.pkg.list(nameSort = Some(true)).stdout
+      // Create list with package names in correct order
+      val scalaSorted = List(s"${packageName}1", s"${packageName}2", s"${packageName}3")
+      // Filter out everything not previously created
+      val regex = s"${packageName}[1-3]".r
+      // Retrieve package names into list as found in original
+      val list = (regex.findAllMatchIn(original)).toList
+      scalaSorted.toString shouldEqual list.toString
+    }, 5, Some(1 second))
+  }
+
+  it should "return a list of alphabetized triggers" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    // Declare 4 triggers, create them out of alphabetical order
+    val triggerName = "triggerAlphaTest"
+    for (i <- 1 to 3) {
+      val name = s"$triggerName$i"
+      assetHelper.withCleaner(wsk.trigger, name) { (trigger, name) =>
+        trigger.create(name)
+      }
+    }
+    retry({
+      val original = wsk.trigger.list(nameSort = Some(true)).stdout
+      // Create list with trigger names in correct order
+      val scalaSorted = List(s"${triggerName}1", s"${triggerName}2", s"${triggerName}3")
+      // Filter out everything not previously created
+      val regex = s"${triggerName}[1-3]".r
+      // Retrieve trigger names into list as found in original
+      val list = (regex.findAllMatchIn(original)).toList
+      scalaSorted.toString shouldEqual list.toString
+    }, 5, Some(1 second))
+  }
+
+  it should "return a list of alphabetized rules" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    // Declare a trigger and an action for the purposes of creating rules
+    val triggerName = "listRulesTrigger"
+    val actionName = "listRulesAction"
+
+    assetHelper.withCleaner(wsk.trigger, triggerName) { (trigger, name) =>
+      trigger.create(name)
+    }
+    assetHelper.withCleaner(wsk.action, actionName) { (action, name) =>
+      action.create(name, defaultAction)
+    }
+    // Declare 3 rules, create them out of alphabetical order
+    val ruleName = "ruleAlphaTest"
+    for (i <- 1 to 3) {
+      val name = s"$ruleName$i"
+      assetHelper.withCleaner(wsk.rule, name) { (rule, name) =>
+        rule.create(name, trigger = triggerName, action = actionName)
+      }
+    }
+    retry({
+      val original = wsk.rule.list(nameSort = Some(true)).stdout
+      // Create list with rule names in correct order
+      val scalaSorted = List(s"${ruleName}1", s"${ruleName}2", s"${ruleName}3")
+      // Filter out everything not previously created
+      val regex = s"${ruleName}[1-3]".r
+      // Retrieve rule names into list as found in original
+      val list = (regex.findAllMatchIn(original)).toList
+      scalaSorted.toString shouldEqual list.toString
+    })
+  }
+
+  behavior of "Wsk params and annotations"
+
+  it should "reject commands that are executed with invalid JSON for annotations and parameters" in {
+    val invalidJSONInputs = getInvalidJSONInput
+    val invalidJSONFiles = Seq(
+      TestUtils.getTestActionFilename("malformed.js"),
+      TestUtils.getTestActionFilename("invalidInput1.json"),
+      TestUtils.getTestActionFilename("invalidInput2.json"),
+      TestUtils.getTestActionFilename("invalidInput3.json"),
+      TestUtils.getTestActionFilename("invalidInput4.json"))
+    val paramCmds = Seq(
+      Seq("action", "create", "actionName", TestUtils.getTestActionFilename("hello.js")),
+      Seq("action", "update", "actionName", TestUtils.getTestActionFilename("hello.js")),
+      Seq("action", "invoke", "actionName"),
+      Seq("package", "create", "packageName"),
+      Seq("package", "update", "packageName"),
+      Seq("package", "bind", "packageName", "boundPackageName"),
+      Seq("trigger", "create", "triggerName"),
+      Seq("trigger", "update", "triggerName"),
+      Seq("trigger", "fire", "triggerName"))
+    val annotCmds = Seq(
+      Seq("action", "create", "actionName", TestUtils.getTestActionFilename("hello.js")),
+      Seq("action", "update", "actionName", TestUtils.getTestActionFilename("hello.js")),
+      Seq("package", "create", "packageName"),
+      Seq("package", "update", "packageName"),
+      Seq("package", "bind", "packageName", "boundPackageName"),
+      Seq("trigger", "create", "triggerName"),
+      Seq("trigger", "update", "triggerName"))
+
+    for (cmd <- paramCmds) {
+      for (invalid <- invalidJSONInputs) {
+        wsk
+          .cli(cmd ++ Seq("-p", "key", invalid) ++ wskprops.overrides, expectedExitCode = ERROR_EXIT)
+          .stderr should include("Invalid parameter argument")
+      }
+
+      for (invalid <- invalidJSONFiles) {
+        wsk.cli(cmd ++ Seq("-P", invalid) ++ wskprops.overrides, expectedExitCode = ERROR_EXIT).stderr should include(
+          "Invalid parameter argument")
+
+      }
+    }
+
+    for (cmd <- annotCmds) {
+      for (invalid <- invalidJSONInputs) {
+        wsk
+          .cli(cmd ++ Seq("-a", "key", invalid) ++ wskprops.overrides, expectedExitCode = ERROR_EXIT)
+          .stderr should include("Invalid annotation argument")
+      }
+
+      for (invalid <- invalidJSONFiles) {
+        wsk.cli(cmd ++ Seq("-A", invalid) ++ wskprops.overrides, expectedExitCode = ERROR_EXIT).stderr should include(
+          "Invalid annotation argument")
+      }
+    }
+  }
+
+  it should "reject commands that are executed with a missing or invalid parameter or annotation file" in {
+    val emptyFile = TestUtils.getTestActionFilename("emtpy.js")
+    val missingFile = "notafile"
+    val emptyFileMsg = s"File '$emptyFile' is not a valid file or it does not exist"
+    val missingFileMsg = s"File '$missingFile' is not a valid file or it does not exist"
+    val invalidArgs = Seq(
+      (
+        Seq("action", "create", "actionName", TestUtils.getTestActionFilename("hello.js"), "-P", emptyFile),
+        emptyFileMsg),
+      (
+        Seq("action", "update", "actionName", TestUtils.getTestActionFilename("hello.js"), "-P", emptyFile),
+        emptyFileMsg),
+      (Seq("action", "invoke", "actionName", "-P", emptyFile), emptyFileMsg),
+      (Seq("action", "create", "actionName", "-P", emptyFile), emptyFileMsg),
+      (Seq("action", "update", "actionName", "-P", emptyFile), emptyFileMsg),
+      (Seq("action", "invoke", "actionName", "-P", emptyFile), emptyFileMsg),
+      (Seq("package", "create", "packageName", "-P", emptyFile), emptyFileMsg),
+      (Seq("package", "update", "packageName", "-P", emptyFile), emptyFileMsg),
+      (Seq("package", "bind", "packageName", "boundPackageName", "-P", emptyFile), emptyFileMsg),
+      (Seq("package", "create", "packageName", "-P", emptyFile), emptyFileMsg),
+      (Seq("package", "update", "packageName", "-P", emptyFile), emptyFileMsg),
+      (Seq("package", "bind", "packageName", "boundPackageName", "-P", emptyFile), emptyFileMsg),
+      (Seq("trigger", "create", "triggerName", "-P", emptyFile), emptyFileMsg),
+      (Seq("trigger", "update", "triggerName", "-P", emptyFile), emptyFileMsg),
+      (Seq("trigger", "fire", "triggerName", "-P", emptyFile), emptyFileMsg),
+      (Seq("trigger", "create", "triggerName", "-P", emptyFile), emptyFileMsg),
+      (Seq("trigger", "update", "triggerName", "-P", emptyFile), emptyFileMsg),
+      (Seq("trigger", "fire", "triggerName", "-P", emptyFile), emptyFileMsg),
+      (
+        Seq("action", "create", "actionName", TestUtils.getTestActionFilename("hello.js"), "-A", missingFile),
+        missingFileMsg),
+      (
+        Seq("action", "update", "actionName", TestUtils.getTestActionFilename("hello.js"), "-A", missingFile),
+        missingFileMsg),
+      (Seq("action", "invoke", "actionName", "-A", missingFile), missingFileMsg),
+      (Seq("action", "create", "actionName", "-A", missingFile), missingFileMsg),
+      (Seq("action", "update", "actionName", "-A", missingFile), missingFileMsg),
+      (Seq("action", "invoke", "actionName", "-A", missingFile), missingFileMsg),
+      (Seq("package", "create", "packageName", "-A", missingFile), missingFileMsg),
+      (Seq("package", "update", "packageName", "-A", missingFile), missingFileMsg),
+      (Seq("package", "bind", "packageName", "boundPackageName", "-A", missingFile), missingFileMsg),
+      (Seq("package", "create", "packageName", "-A", missingFile), missingFileMsg),
+      (Seq("package", "update", "packageName", "-A", missingFile), missingFileMsg),
+      (Seq("package", "bind", "packageName", "boundPackageName", "-A", missingFile), missingFileMsg),
+      (Seq("trigger", "create", "triggerName", "-A", missingFile), missingFileMsg),
+      (Seq("trigger", "update", "triggerName", "-A", missingFile), missingFileMsg),
+      (Seq("trigger", "fire", "triggerName", "-A", missingFile), missingFileMsg),
+      (Seq("trigger", "create", "triggerName", "-A", missingFile), missingFileMsg),
+      (Seq("trigger", "update", "triggerName", "-A", missingFile), missingFileMsg),
+      (Seq("trigger", "fire", "triggerName", "-A", missingFile), missingFileMsg))
+
+    invalidArgs foreach {
+      case (cmd, err) =>
+        val stderr = wsk.cli(cmd, expectedExitCode = MISUSE_EXIT).stderr
+        stderr should include(err)
+        stderr should include("Run 'wsk --help' for usage.")
+    }
+  }
+
+  it should "reject commands that are executed with not enough param or annot arguments" in {
+    val invalidParamMsg = "Arguments for '-p' must be a key/value pair"
+    val invalidAnnotMsg = "Arguments for '-a' must be a key/value pair"
+    val invalidParamFileMsg = "An argument must be provided for '-P'"
+    val invalidAnnotFileMsg = "An argument must be provided for '-A'"
+    val invalidArgs = Seq(
+      (Seq("action", "create", "actionName", "-p"), invalidParamMsg),
+      (Seq("action", "create", "actionName", "-p", "key"), invalidParamMsg),
+      (Seq("action", "create", "actionName", "-P"), invalidParamFileMsg),
+      (Seq("action", "update", "actionName", "-p"), invalidParamMsg),
+      (Seq("action", "update", "actionName", "-p", "key"), invalidParamMsg),
+      (Seq("action", "update", "actionName", "-P"), invalidParamFileMsg),
+      (Seq("action", "invoke", "actionName", "-p"), invalidParamMsg),
+      (Seq("action", "invoke", "actionName", "-p", "key"), invalidParamMsg),
+      (Seq("action", "invoke", "actionName", "-P"), invalidParamFileMsg),
+      (Seq("action", "create", "actionName", "-a"), invalidAnnotMsg),
+      (Seq("action", "create", "actionName", "-a", "key"), invalidAnnotMsg),
+      (Seq("action", "create", "actionName", "-A"), invalidAnnotFileMsg),
+      (Seq("action", "update", "actionName", "-a"), invalidAnnotMsg),
+      (Seq("action", "update", "actionName", "-a", "key"), invalidAnnotMsg),
+      (Seq("action", "update", "actionName", "-A"), invalidAnnotFileMsg),
+      (Seq("action", "invoke", "actionName", "-a"), invalidAnnotMsg),
+      (Seq("action", "invoke", "actionName", "-a", "key"), invalidAnnotMsg),
+      (Seq("action", "invoke", "actionName", "-A"), invalidAnnotFileMsg),
+      (Seq("package", "create", "packageName", "-p"), invalidParamMsg),
+      (Seq("package", "create", "packageName", "-p", "key"), invalidParamMsg),
+      (Seq("package", "create", "packageName", "-P"), invalidParamFileMsg),
+      (Seq("package", "update", "packageName", "-p"), invalidParamMsg),
+      (Seq("package", "update", "packageName", "-p", "key"), invalidParamMsg),
+      (Seq("package", "update", "packageName", "-P"), invalidParamFileMsg),
+      (Seq("package", "bind", "packageName", "boundPackageName", "-p"), invalidParamMsg),
+      (Seq("package", "bind", "packageName", "boundPackageName", "-p", "key"), invalidParamMsg),
+      (Seq("package", "bind", "packageName", "boundPackageName", "-P"), invalidParamFileMsg),
+      (Seq("package", "create", "packageName", "-a"), invalidAnnotMsg),
+      (Seq("package", "create", "packageName", "-a", "key"), invalidAnnotMsg),
+      (Seq("package", "create", "packageName", "-A"), invalidAnnotFileMsg),
+      (Seq("package", "update", "packageName", "-a"), invalidAnnotMsg),
+      (Seq("package", "update", "packageName", "-a", "key"), invalidAnnotMsg),
+      (Seq("package", "update", "packageName", "-A"), invalidAnnotFileMsg),
+      (Seq("package", "bind", "packageName", "boundPackageName", "-a"), invalidAnnotMsg),
+      (Seq("package", "bind", "packageName", "boundPackageName", "-a", "key"), invalidAnnotMsg),
+      (Seq("package", "bind", "packageName", "boundPackageName", "-A"), invalidAnnotFileMsg),
+      (Seq("trigger", "create", "triggerName", "-p"), invalidParamMsg),
+      (Seq("trigger", "create", "triggerName", "-p", "key"), invalidParamMsg),
+      (Seq("trigger", "create", "triggerName", "-P"), invalidParamFileMsg),
+      (Seq("trigger", "update", "triggerName", "-p"), invalidParamMsg),
+      (Seq("trigger", "update", "triggerName", "-p", "key"), invalidParamMsg),
+      (Seq("trigger", "update", "triggerName", "-P"), invalidParamFileMsg),
+      (Seq("trigger", "fire", "triggerName", "-p"), invalidParamMsg),
+      (Seq("trigger", "fire", "triggerName", "-p", "key"), invalidParamMsg),
+      (Seq("trigger", "fire", "triggerName", "-P"), invalidParamFileMsg),
+      (Seq("trigger", "create", "triggerName", "-a"), invalidAnnotMsg),
+      (Seq("trigger", "create", "triggerName", "-a", "key"), invalidAnnotMsg),
+      (Seq("trigger", "create", "triggerName", "-A"), invalidAnnotFileMsg),
+      (Seq("trigger", "update", "triggerName", "-a"), invalidAnnotMsg),
+      (Seq("trigger", "update", "triggerName", "-a", "key"), invalidAnnotMsg),
+      (Seq("trigger", "update", "triggerName", "-A"), invalidAnnotFileMsg),
+      (Seq("trigger", "fire", "triggerName", "-a"), invalidAnnotMsg),
+      (Seq("trigger", "fire", "triggerName", "-a", "key"), invalidAnnotMsg),
+      (Seq("trigger", "fire", "triggerName", "-A"), invalidAnnotFileMsg))
+
+    invalidArgs foreach {
+      case (cmd, err) =>
+        val stderr = wsk.cli(cmd, expectedExitCode = ERROR_EXIT).stderr
+        stderr should include(err)
+        stderr should include("Run 'wsk --help' for usage.")
+    }
+  }
+
+  behavior of "Wsk invalid argument handling"
+
+  it should "reject commands that are executed with invalid arguments" in {
+    val invalidArgsMsg = "error: Invalid argument(s)"
+    val tooFewArgsMsg = invalidArgsMsg + "."
+    val tooManyArgsMsg = invalidArgsMsg + ": "
+    val actionNameActionReqMsg = "An action name and code artifact are required."
+    val actionNameReqMsg = "An action name is required."
+    val actionOptMsg = "A code artifact is optional."
+    val packageNameReqMsg = "A package name is required."
+    val packageNameBindingReqMsg = "A package name and binding name are required."
+    val ruleNameReqMsg = "A rule name is required."
+    val ruleTriggerActionReqMsg = "A rule, trigger and action name are required."
+    val activationIdReq = "An activation ID is required."
+    val triggerNameReqMsg = "A trigger name is required."
+    val optNamespaceMsg = "An optional namespace is the only valid argument."
+    val optPayloadMsg = "A payload is optional."
+    val noArgsReqMsg = "No arguments are required."
+    val invalidArg = "invalidArg"
+    val apiCreateReqMsg =
+      "Specify a swagger file or specify an API base path with an API path, an API verb, and an action name."
+    val apiGetReqMsg = "An API base path or API name is required."
+    val apiDeleteReqMsg =
+      "An API base path or API name is required.  An optional API relative path and operation may also be provided."
+    val apiListReqMsg = "Optional parameters are: API base path (or API name), API relative path and operation."
+    val invalidShared = s"Cannot use value '$invalidArg' for shared"
+    val entityNameMsg =
+      s"An entity name, '$invalidArg', was provided instead of a namespace. Valid namespaces are of the following format: /NAMESPACE."
+    val invalidArgs = Seq(
+      (Seq("api", "create"), s"${tooFewArgsMsg} ${apiCreateReqMsg}"),
+      (
+        Seq("api", "create", "/basepath", "/path", "GET", "action", invalidArg),
+        s"${tooManyArgsMsg}${invalidArg}. ${apiCreateReqMsg}"),
+      (Seq("api", "get"), s"${tooFewArgsMsg} ${apiGetReqMsg}"),
+      (Seq("api", "get", "/basepath", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${apiGetReqMsg}"),
+      (Seq("api", "delete"), s"${tooFewArgsMsg} ${apiDeleteReqMsg}"),
+      (
+        Seq("api", "delete", "/basepath", "/path", "GET", invalidArg),
+        s"${tooManyArgsMsg}${invalidArg}. ${apiDeleteReqMsg}"),
+      (
+        Seq("api", "list", "/basepath", "/path", "GET", invalidArg),
+        s"${tooManyArgsMsg}${invalidArg}. ${apiListReqMsg}"),
+      (Seq("action", "create"), s"${tooFewArgsMsg} ${actionNameActionReqMsg}"),
+      (Seq("action", "create", "someAction"), s"${tooFewArgsMsg} ${actionNameActionReqMsg}"),
+      (Seq("action", "create", "actionName", "artifactName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("action", "update"), s"${tooFewArgsMsg} ${actionNameReqMsg} ${actionOptMsg}"),
+      (
+        Seq("action", "update", "actionName", "artifactName", invalidArg),
+        s"${tooManyArgsMsg}${invalidArg}. ${actionNameReqMsg} ${actionOptMsg}"),
+      (Seq("action", "delete"), s"${tooFewArgsMsg} ${actionNameReqMsg}"),
+      (Seq("action", "delete", "actionName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("action", "get"), s"${tooFewArgsMsg} ${actionNameReqMsg}"),
+      (Seq("action", "get", "actionName", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("action", "list", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
+      (Seq("action", "invoke"), s"${tooFewArgsMsg} ${actionNameReqMsg}"),
+      (Seq("action", "invoke", "actionName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("activation", "list", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
+      (Seq("activation", "get"), s"${tooFewArgsMsg} ${activationIdReq}"),
+      (Seq("activation", "get", "activationID", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("activation", "logs"), s"${tooFewArgsMsg} ${activationIdReq}"),
+      (Seq("activation", "logs", "activationID", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("activation", "result"), s"${tooFewArgsMsg} ${activationIdReq}"),
+      (Seq("activation", "result", "activationID", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("activation", "poll", "activationID", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
+      (Seq("namespace", "list", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${noArgsReqMsg}"),
+      (Seq("namespace", "get", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
+      (Seq("package", "create"), s"${tooFewArgsMsg} ${packageNameReqMsg}"),
+      (Seq("package", "create", "packageName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("package", "create", "packageName", "--shared", invalidArg), invalidShared),
+      (Seq("package", "update"), s"${tooFewArgsMsg} ${packageNameReqMsg}"),
+      (Seq("package", "update", "packageName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("package", "update", "packageName", "--shared", invalidArg), invalidShared),
+      (Seq("package", "get"), s"${tooFewArgsMsg} ${packageNameReqMsg}"),
+      (Seq("package", "get", "packageName", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("package", "bind"), s"${tooFewArgsMsg} ${packageNameBindingReqMsg}"),
+      (Seq("package", "bind", "packageName"), s"${tooFewArgsMsg} ${packageNameBindingReqMsg}"),
+      (Seq("package", "bind", "packageName", "bindingName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("package", "list", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
+      (Seq("package", "list", invalidArg), entityNameMsg),
+      (Seq("package", "delete"), s"${tooFewArgsMsg} ${packageNameReqMsg}"),
+      (Seq("package", "delete", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("package", "refresh", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
+      (Seq("package", "refresh", invalidArg), entityNameMsg),
+      (Seq("rule", "enable"), s"${tooFewArgsMsg} ${ruleNameReqMsg}"),
+      (Seq("rule", "enable", "ruleName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("rule", "disable"), s"${tooFewArgsMsg} ${ruleNameReqMsg}"),
+      (Seq("rule", "disable", "ruleName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("rule", "status"), s"${tooFewArgsMsg} ${ruleNameReqMsg}"),
+      (Seq("rule", "status", "ruleName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("rule", "create"), s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
+      (Seq("rule", "create", "ruleName"), s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
+      (Seq("rule", "create", "ruleName", "triggerName"), s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
+      (Seq("rule", "create", "ruleName", "triggerName", "actionName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("rule", "update"), s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
+      (Seq("rule", "update", "ruleName"), s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
+      (Seq("rule", "update", "ruleName", "triggerName"), s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
+      (Seq("rule", "update", "ruleName", "triggerName", "actionName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("rule", "get"), s"${tooFewArgsMsg} ${ruleNameReqMsg}"),
+      (Seq("rule", "get", "ruleName", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("rule", "delete"), s"${tooFewArgsMsg} ${ruleNameReqMsg}"),
+      (Seq("rule", "delete", "ruleName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("rule", "list", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
+      (Seq("rule", "list", invalidArg), entityNameMsg),
+      (Seq("trigger", "fire"), s"${tooFewArgsMsg} ${triggerNameReqMsg} ${optPayloadMsg}"),
+      (
+        Seq("trigger", "fire", "triggerName", "triggerPayload", invalidArg),
+        s"${tooManyArgsMsg}${invalidArg}. ${triggerNameReqMsg} ${optPayloadMsg}"),
+      (Seq("trigger", "create"), s"${tooFewArgsMsg} ${triggerNameReqMsg}"),
+      (Seq("trigger", "create", "triggerName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("trigger", "update"), s"${tooFewArgsMsg} ${triggerNameReqMsg}"),
+      (Seq("trigger", "update", "triggerName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("trigger", "get"), s"${tooFewArgsMsg} ${triggerNameReqMsg}"),
+      (Seq("trigger", "get", "triggerName", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("trigger", "delete"), s"${tooFewArgsMsg} ${triggerNameReqMsg}"),
+      (Seq("trigger", "delete", "triggerName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
+      (Seq("trigger", "list", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
+      (Seq("trigger", "list", invalidArg), entityNameMsg))
+
+    invalidArgs foreach {
+      case (cmd, err) =>
+        withClue(cmd) {
+          val rr = wsk.cli(cmd ++ wskprops.overrides, expectedExitCode = ANY_ERROR_EXIT)
+          rr.exitCode should (be(ERROR_EXIT) or be(MISUSE_EXIT))
+          rr.stderr should include(err)
+          rr.stderr should include("Run 'wsk --help' for usage.")
         }
     }
-
-    behavior of "Wsk invalid argument handling"
-
-    it should "reject commands that are executed with invalid arguments" in {
-        val invalidArgsMsg = "error: Invalid argument(s)"
-        val tooFewArgsMsg = invalidArgsMsg + "."
-        val tooManyArgsMsg = invalidArgsMsg + ": "
-        val actionNameActionReqMsg = "An action name and code artifact are required."
-        val actionNameReqMsg = "An action name is required."
-        val actionOptMsg = "A code artifact is optional."
-        val packageNameReqMsg = "A package name is required."
-        val packageNameBindingReqMsg = "A package name and binding name are required."
-        val ruleNameReqMsg = "A rule name is required."
-        val ruleTriggerActionReqMsg = "A rule, trigger and action name are required."
-        val activationIdReq = "An activation ID is required."
-        val triggerNameReqMsg = "A trigger name is required."
-        val optNamespaceMsg = "An optional namespace is the only valid argument."
-        val optPayloadMsg = "A payload is optional."
-        val noArgsReqMsg = "No arguments are required."
-        val invalidArg = "invalidArg"
-        val apiCreateReqMsg = "Specify a swagger file or specify an API base path with an API path, an API verb, and an action name."
-        val apiGetReqMsg = "An API base path or API name is required."
-        val apiDeleteReqMsg = "An API base path or API name is required.  An optional API relative path and operation may also be provided."
-        val apiListReqMsg = "Optional parameters are: API base path (or API name), API relative path and operation."
-        val invalidShared = s"Cannot use value '$invalidArg' for shared"
-        val entityNameMsg = s"An entity name, '$invalidArg', was provided instead of a namespace. Valid namespaces are of the following format: /NAMESPACE."
-        val invalidArgs = Seq(
-            (Seq("api", "create"), s"${tooFewArgsMsg} ${apiCreateReqMsg}"),
-            (Seq("api", "create", "/basepath", "/path", "GET", "action", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${apiCreateReqMsg}"),
-            (Seq("api", "get"), s"${tooFewArgsMsg} ${apiGetReqMsg}"),
-            (Seq("api", "get", "/basepath", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${apiGetReqMsg}"),
-            (Seq("api", "delete"), s"${tooFewArgsMsg} ${apiDeleteReqMsg}"),
-            (Seq("api", "delete", "/basepath", "/path", "GET", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${apiDeleteReqMsg}"),
-            (Seq("api", "list", "/basepath", "/path", "GET", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${apiListReqMsg}"),
-            (Seq("action", "create"), s"${tooFewArgsMsg} ${actionNameActionReqMsg}"),
-            (Seq("action", "create", "someAction"), s"${tooFewArgsMsg} ${actionNameActionReqMsg}"),
-            (Seq("action", "create", "actionName", "artifactName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("action", "update"), s"${tooFewArgsMsg} ${actionNameReqMsg} ${actionOptMsg}"),
-            (Seq("action", "update", "actionName", "artifactName", invalidArg),
-                s"${tooManyArgsMsg}${invalidArg}. ${actionNameReqMsg} ${actionOptMsg}"),
-            (Seq("action", "delete"), s"${tooFewArgsMsg} ${actionNameReqMsg}"),
-            (Seq("action", "delete", "actionName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("action", "get"), s"${tooFewArgsMsg} ${actionNameReqMsg}"),
-            (Seq("action", "get", "actionName", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("action", "list", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
-            (Seq("action", "invoke"), s"${tooFewArgsMsg} ${actionNameReqMsg}"),
-            (Seq("action", "invoke", "actionName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("activation", "list", "namespace", invalidArg),
-                s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
-            (Seq("activation", "get"), s"${tooFewArgsMsg} ${activationIdReq}"),
-            (Seq("activation", "get", "activationID", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("activation", "logs"), s"${tooFewArgsMsg} ${activationIdReq}"),
-            (Seq("activation", "logs", "activationID", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("activation", "result"), s"${tooFewArgsMsg} ${activationIdReq}"),
-            (Seq("activation", "result", "activationID", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("activation", "poll", "activationID", invalidArg),
-                s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
-            (Seq("namespace", "list", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${noArgsReqMsg}"),
-            (Seq("namespace", "get", "namespace", invalidArg),
-                s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
-            (Seq("package", "create"), s"${tooFewArgsMsg} ${packageNameReqMsg}"),
-            (Seq("package", "create", "packageName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("package", "create", "packageName", "--shared", invalidArg), invalidShared),
-            (Seq("package", "update"), s"${tooFewArgsMsg} ${packageNameReqMsg}"),
-            (Seq("package", "update", "packageName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("package", "update", "packageName", "--shared", invalidArg), invalidShared),
-            (Seq("package", "get"), s"${tooFewArgsMsg} ${packageNameReqMsg}"),
-            (Seq("package", "get", "packageName", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("package", "bind"), s"${tooFewArgsMsg} ${packageNameBindingReqMsg}"),
-            (Seq("package", "bind", "packageName"), s"${tooFewArgsMsg} ${packageNameBindingReqMsg}"),
-            (Seq("package", "bind", "packageName", "bindingName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("package", "list", "namespace", invalidArg),
-                s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
-            (Seq("package", "list", invalidArg), entityNameMsg),
-            (Seq("package", "delete"), s"${tooFewArgsMsg} ${packageNameReqMsg}"),
-            (Seq("package", "delete", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("package", "refresh", "namespace", invalidArg),
-                s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
-            (Seq("package", "refresh", invalidArg), entityNameMsg),
-            (Seq("rule", "enable"), s"${tooFewArgsMsg} ${ruleNameReqMsg}"),
-            (Seq("rule", "enable", "ruleName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("rule", "disable"), s"${tooFewArgsMsg} ${ruleNameReqMsg}"),
-            (Seq("rule", "disable", "ruleName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("rule", "status"), s"${tooFewArgsMsg} ${ruleNameReqMsg}"),
-            (Seq("rule", "status", "ruleName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("rule", "create"), s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
-            (Seq("rule", "create", "ruleName"), s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
-            (Seq("rule", "create", "ruleName", "triggerName"), s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
-            (Seq("rule", "create", "ruleName", "triggerName", "actionName", invalidArg),
-                s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("rule", "update"), s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
-            (Seq("rule", "update", "ruleName"), s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
-            (Seq("rule", "update", "ruleName", "triggerName"), s"${tooFewArgsMsg} ${ruleTriggerActionReqMsg}"),
-            (Seq("rule", "update", "ruleName", "triggerName", "actionName", invalidArg),
-                s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("rule", "get"), s"${tooFewArgsMsg} ${ruleNameReqMsg}"),
-            (Seq("rule", "get", "ruleName", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("rule", "delete"), s"${tooFewArgsMsg} ${ruleNameReqMsg}"),
-            (Seq("rule", "delete", "ruleName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("rule", "list", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
-            (Seq("rule", "list", invalidArg), entityNameMsg),
-            (Seq("trigger", "fire"), s"${tooFewArgsMsg} ${triggerNameReqMsg} ${optPayloadMsg}"),
-            (Seq("trigger", "fire", "triggerName", "triggerPayload", invalidArg),
-                s"${tooManyArgsMsg}${invalidArg}. ${triggerNameReqMsg} ${optPayloadMsg}"),
-            (Seq("trigger", "create"), s"${tooFewArgsMsg} ${triggerNameReqMsg}"),
-            (Seq("trigger", "create", "triggerName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("trigger", "update"), s"${tooFewArgsMsg} ${triggerNameReqMsg}"),
-            (Seq("trigger", "update", "triggerName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("trigger", "get"), s"${tooFewArgsMsg} ${triggerNameReqMsg}"),
-            (Seq("trigger", "get", "triggerName", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("trigger", "delete"), s"${tooFewArgsMsg} ${triggerNameReqMsg}"),
-            (Seq("trigger", "delete", "triggerName", invalidArg), s"${tooManyArgsMsg}${invalidArg}."),
-            (Seq("trigger", "list", "namespace", invalidArg), s"${tooManyArgsMsg}${invalidArg}. ${optNamespaceMsg}"),
-            (Seq("trigger", "list", invalidArg), entityNameMsg))
-
-        invalidArgs foreach {
-            case (cmd, err) =>
-                withClue(cmd) {
-                    val rr = wsk.cli(cmd ++ wskprops.overrides, expectedExitCode = ANY_ERROR_EXIT)
-                    rr.exitCode should (be(ERROR_EXIT) or be(MISUSE_EXIT))
-                    rr.stderr should include(err)
-                    rr.stderr should include("Run 'wsk --help' for usage.")
-                }
+  }
+
+  behavior of "Wsk action parameters"
+
+  it should "create an action with different permutations of limits" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val file = Some(TestUtils.getTestActionFilename("hello.js"))
+
+      def testLimit(timeout: Option[Duration] = None,
+                    memory: Option[ByteSize] = None,
+                    logs: Option[ByteSize] = None,
+                    ec: Int = SUCCESS_EXIT) = {
+        // Limits to assert, standard values if CLI omits certain values
+        val limits = JsObject(
+          "timeout" -> timeout.getOrElse(STD_DURATION).toMillis.toJson,
+          "memory" -> memory.getOrElse(STD_MEMORY).toMB.toInt.toJson,
+          "logs" -> logs.getOrElse(STD_LOGSIZE).toMB.toInt.toJson)
+
+        val name = "ActionLimitTests" + Instant.now.toEpochMilli
+        val createResult = assetHelper.withCleaner(wsk.action, name, confirmDelete = (ec == SUCCESS_EXIT)) {
+          (action, _) =>
+            val result = action.create(
+              name,
+              file,
+              logsize = logs,
+              memory = memory,
+              timeout = timeout,
+              expectedExitCode = DONTCARE_EXIT)
+            withClue(s"create failed for parameters: timeout = $timeout, memory = $memory, logsize = $logs:") {
+              result.exitCode should be(ec)
+            }
+            result
         }
-    }
-
-    behavior of "Wsk action parameters"
-
-    it should "create an action with different permutations of limits" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
-
-            def testLimit(timeout: Option[Duration] = None, memory: Option[ByteSize] = None, logs: Option[ByteSize] = None, ec: Int = SUCCESS_EXIT) = {
-                // Limits to assert, standard values if CLI omits certain values
-                val limits = JsObject(
-                    "timeout" -> timeout.getOrElse(STD_DURATION).toMillis.toJson,
-                    "memory" -> memory.getOrElse(STD_MEMORY).toMB.toInt.toJson,
-                    "logs" -> logs.getOrElse(STD_LOGSIZE).toMB.toInt.toJson)
-
-                val name = "ActionLimitTests" + Instant.now.toEpochMilli
-                val createResult = assetHelper.withCleaner(wsk.action, name, confirmDelete = (ec == SUCCESS_EXIT)) {
-                    (action, _) =>
-                        val result = action.create(name, file, logsize = logs, memory = memory, timeout = timeout, expectedExitCode = DONTCARE_EXIT)
-                        withClue(s"create failed for parameters: timeout = $timeout, memory = $memory, logsize = $logs:") {
-                            result.exitCode should be(ec)
-                        }
-                        result
-                }
-
-                if (ec == SUCCESS_EXIT) {
-                    val JsObject(parsedAction) = wsk.action.get(name).stdout.split("\n").tail.mkString.parseJson.asJsObject
-                    parsedAction("limits") shouldBe limits
-                } else {
-                    createResult.stderr should include("allowed threshold")
-                }
-            }
 
-            // Assert for valid permutations that the values are set correctly
-            for {
-                time <- Seq(None, Some(MIN_DURATION), Some(MAX_DURATION))
-                mem <- Seq(None, Some(MIN_MEMORY), Some(MAX_MEMORY))
-                log <- Seq(None, Some(MIN_LOGSIZE), Some(MAX_LOGSIZE))
-            } testLimit(time, mem, log)
-
-            // Assert that invalid permutation are rejected
-            testLimit(Some(0.milliseconds), None, None, BAD_REQUEST)
-            testLimit(Some(100.minutes), None, None, BAD_REQUEST)
-            testLimit(None, Some(0.MB), None, BAD_REQUEST)
-            testLimit(None, Some(32768.MB), None, BAD_REQUEST)
-            testLimit(None, None, Some(32768.MB), BAD_REQUEST)
-    }
+        if (ec == SUCCESS_EXIT) {
+          val JsObject(parsedAction) = wsk.action.get(name).stdout.split("\n").tail.mkString.parseJson.asJsObject
+          parsedAction("limits") shouldBe limits
+        } else {
+          createResult.stderr should include("allowed threshold")
+        }
+      }
+
+      // Assert for valid permutations that the values are set correctly
+      for {
+        time <- Seq(None, Some(MIN_DURATION), Some(MAX_DURATION))
+        mem <- Seq(None, Some(MIN_MEMORY), Some(MAX_MEMORY))
+        log <- Seq(None, Some(MIN_LOGSIZE), Some(MAX_LOGSIZE))
+      } testLimit(time, mem, log)
+
+      // Assert that invalid permutation are rejected
+      testLimit(Some(0.milliseconds), None, None, BAD_REQUEST)
+      testLimit(Some(100.minutes), None, None, BAD_REQUEST)
+      testLimit(None, Some(0.MB), None, BAD_REQUEST)
+      testLimit(None, Some(32768.MB), None, BAD_REQUEST)
+      testLimit(None, None, Some(32768.MB), BAD_REQUEST)
+  }
 }
diff --git a/tests/src/test/scala/whisk/core/cli/test/WskConfigTests.scala b/tests/src/test/scala/whisk/core/cli/test/WskConfigTests.scala
index fbe1631..90b014d 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskConfigTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskConfigTests.scala
@@ -33,229 +33,287 @@ import common.WskProps
 import common.WskTestHelpers
 
 @RunWith(classOf[JUnitRunner])
-class WskConfigTests
-    extends TestHelpers
-    with WskTestHelpers {
+class WskConfigTests extends TestHelpers with WskTestHelpers {
 
-    implicit val wskprops = WskProps()
-    val wsk = new Wsk
+  implicit val wskprops = WskProps()
+  val wsk = new Wsk
 
-    behavior of "Wsk CLI config"
+  behavior of "Wsk CLI config"
 
-    it should "fail to show api build when setting apihost to bogus value" in {
-        val tmpwskprops = File.createTempFile("wskprops", ".tmp")
-        try {
-            val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
-            wsk.cli(Seq("property", "set", "-i", "--apihost", "xxxx.yyyy"), env = env)
-            val rr = wsk.cli(Seq("property", "get", "--apibuild", "-i"), env = env, expectedExitCode = ANY_ERROR_EXIT)
-            rr.stdout should include regex ("""whisk API build\s*Unknown""")
-            rr.stderr should include regex ("Unable to obtain API build information")
-        } finally {
-            tmpwskprops.delete()
-        }
+  it should "fail to show api build when setting apihost to bogus value" in {
+    val tmpwskprops = File.createTempFile("wskprops", ".tmp")
+    try {
+      val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
+      wsk.cli(Seq("property", "set", "-i", "--apihost", "xxxx.yyyy"), env = env)
+      val rr = wsk.cli(Seq("property", "get", "--apibuild", "-i"), env = env, expectedExitCode = ANY_ERROR_EXIT)
+      rr.stdout should include regex ("""whisk API build\s*Unknown""")
+      rr.stderr should include regex ("Unable to obtain API build information")
+    } finally {
+      tmpwskprops.delete()
     }
+  }
 
-    it should "validate default property values" in {
-        val tmpwskprops = File.createTempFile("wskprops", ".tmp")
-        val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
-        val stdout = wsk.cli(Seq("property", "unset", "--auth", "--cert", "--key", "--apihost", "--apiversion", "--namespace"), env = env).stdout
-        try {
-            stdout should include regex ("ok: whisk auth unset")
-            stdout should include regex ("ok: client cert unset")
-            stdout should include regex ("ok: client key unset")
-            stdout should include regex ("ok: whisk API host unset")
-            stdout should include regex ("ok: whisk API version unset")
-            stdout should include regex ("ok: whisk namespace unset")
+  it should "validate default property values" in {
+    val tmpwskprops = File.createTempFile("wskprops", ".tmp")
+    val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
+    val stdout = wsk
+      .cli(Seq("property", "unset", "--auth", "--cert", "--key", "--apihost", "--apiversion", "--namespace"), env = env)
+      .stdout
+    try {
+      stdout should include regex ("ok: whisk auth unset")
+      stdout should include regex ("ok: client cert unset")
+      stdout should include regex ("ok: client key unset")
+      stdout should include regex ("ok: whisk API host unset")
+      stdout should include regex ("ok: whisk API version unset")
+      stdout should include regex ("ok: whisk namespace unset")
 
-            wsk.cli(Seq("property", "get", "--auth"), env = env).
-                    stdout should include regex ("""(?i)whisk auth\s*$""") // default = empty string
-            wsk.cli(Seq("property", "get", "--cert"), env = env).
-                    stdout should include regex ("""(?i)client cert\s*$""") // default = empty string
-            wsk.cli(Seq("property", "get", "--key"), env = env).
-                    stdout should include regex ("""(?i)client key\s*$""") // default = empty string
-            wsk.cli(Seq("property", "get", "--apihost"), env = env).
-                    stdout should include regex ("""(?i)whisk API host\s*$""") // default = empty string
-            wsk.cli(Seq("property", "get", "--namespace"), env = env).
-                    stdout should include regex ("""(?i)whisk namespace\s*_$""") // default = _
-        } finally {
-            tmpwskprops.delete()
-        }
+      wsk
+        .cli(Seq("property", "get", "--auth"), env = env)
+        .stdout should include regex ("""(?i)whisk auth\s*$""") // default = empty string
+      wsk
+        .cli(Seq("property", "get", "--cert"), env = env)
+        .stdout should include regex ("""(?i)client cert\s*$""") // default = empty string
+      wsk
+        .cli(Seq("property", "get", "--key"), env = env)
+        .stdout should include regex ("""(?i)client key\s*$""") // default = empty string
+      wsk
+        .cli(Seq("property", "get", "--apihost"), env = env)
+        .stdout should include regex ("""(?i)whisk API host\s*$""") // default = empty string
+      wsk
+        .cli(Seq("property", "get", "--namespace"), env = env)
+        .stdout should include regex ("""(?i)whisk namespace\s*_$""") // default = _
+    } finally {
+      tmpwskprops.delete()
     }
+  }
 
-    it should "reject authenticated command when no auth key is given" in {
-        // override wsk props file in case it exists
-        val tmpwskprops = File.createTempFile("wskprops", ".tmp")
-        val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
-        val stderr = wsk.cli(Seq("list") ++ wskprops.overrides, env = env, expectedExitCode = MISUSE_EXIT).stderr
-        try {
-            stderr should include regex (s"usage[:.]")
-            stderr should include("--auth is required")
-        } finally {
-            tmpwskprops.delete()
-        }
+  it should "reject authenticated command when no auth key is given" in {
+    // override wsk props file in case it exists
+    val tmpwskprops = File.createTempFile("wskprops", ".tmp")
+    val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
+    val stderr = wsk.cli(Seq("list") ++ wskprops.overrides, env = env, expectedExitCode = MISUSE_EXIT).stderr
+    try {
+      stderr should include regex (s"usage[:.]")
+      stderr should include("--auth is required")
+    } finally {
+      tmpwskprops.delete()
     }
+  }
 
-    it should "reject a command when the API host is not set" in {
-        val tmpwskprops = File.createTempFile("wskprops", ".tmp")
-        try {
-            val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
-            val stderr = wsk.cli(Seq("property", "get", "-i"), env = env, expectedExitCode = ERROR_EXIT).stderr
-            stderr should include("The API host is not valid: An API host must be provided.")
-        } finally {
-            tmpwskprops.delete()
-        }
+  it should "reject a command when the API host is not set" in {
+    val tmpwskprops = File.createTempFile("wskprops", ".tmp")
+    try {
+      val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
+      val stderr = wsk.cli(Seq("property", "get", "-i"), env = env, expectedExitCode = ERROR_EXIT).stderr
+      stderr should include("The API host is not valid: An API host must be provided.")
+    } finally {
+      tmpwskprops.delete()
     }
+  }
 
-    it should "show api build details" in {
-        val tmpProps = File.createTempFile("wskprops", ".tmp")
-        try {
-            val env = Map("WSK_CONFIG_FILE" -> tmpProps.getAbsolutePath())
-            wsk.cli(Seq("property", "set", "-i") ++ wskprops.overrides, env = env)
-            val rr = wsk.cli(Seq("property", "get", "--apibuild", "--apibuildno", "-i"), env = env)
-            rr.stderr should not include ("https:///api/v1: http: no Host in request URL")
-            rr.stdout should not include regex("Cannot determine API build")
-            rr.stdout should include regex ("""(?i)whisk API build\s+201.*""")
-            rr.stdout should include regex ("""(?i)whisk API build number\s+.*""")
-        } finally {
-            tmpProps.delete()
-        }
+  it should "show api build details" in {
+    val tmpProps = File.createTempFile("wskprops", ".tmp")
+    try {
+      val env = Map("WSK_CONFIG_FILE" -> tmpProps.getAbsolutePath())
+      wsk.cli(Seq("property", "set", "-i") ++ wskprops.overrides, env = env)
+      val rr = wsk.cli(Seq("property", "get", "--apibuild", "--apibuildno", "-i"), env = env)
+      rr.stderr should not include ("https:///api/v1: http: no Host in request URL")
+      rr.stdout should not include regex("Cannot determine API build")
+      rr.stdout should include regex ("""(?i)whisk API build\s+201.*""")
+      rr.stdout should include regex ("""(?i)whisk API build number\s+.*""")
+    } finally {
+      tmpProps.delete()
     }
+  }
 
-    it should "set apihost, auth, and namespace" in {
-        val tmpwskprops = File.createTempFile("wskprops", ".tmp")
-        try {
-            val namespace = wsk.namespace.whois()
-            val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
-            val stdout = wsk.cli(Seq("property", "set", "-i",
-                "--apihost", wskprops.apihost,
-                "--auth", wskprops.authKey,
-                "--namespace", namespace),
-                env = env).stdout
-            stdout should include(s"ok: whisk auth set")
-            stdout should include(s"ok: whisk API host set to ${wskprops.apihost}")
-            stdout should include(s"ok: whisk namespace set to ${namespace}")
-        } finally {
-            tmpwskprops.delete()
-        }
+  it should "set apihost, auth, and namespace" in {
+    val tmpwskprops = File.createTempFile("wskprops", ".tmp")
+    try {
+      val namespace = wsk.namespace.whois()
+      val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
+      val stdout = wsk
+        .cli(
+          Seq(
+            "property",
+            "set",
+            "-i",
+            "--apihost",
+            wskprops.apihost,
+            "--auth",
+            wskprops.authKey,
+            "--namespace",
+            namespace),
+          env = env)
+        .stdout
+      stdout should include(s"ok: whisk auth set")
+      stdout should include(s"ok: whisk API host set to ${wskprops.apihost}")
+      stdout should include(s"ok: whisk namespace set to ${namespace}")
+    } finally {
+      tmpwskprops.delete()
     }
+  }
 
-    // If client certificate verification is off, should ingore run below tests.
-    if (!WhiskProperties.getProperty("whisk.ssl.client.verification").equals("off")) {
-        it should "set valid cert key to get expected success result for client certificate verification" in {
-            val tmpwskprops = File.createTempFile("wskprops", ".tmp")
-            try {
-                val namespace = wsk.namespace.list().stdout.trim.split("\n").last
-                val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
-                // Send request to https://<apihost>/api/v1/namespaces, wsk client passes client certificate to nginx, nginx will
-                // verify it by client ca's openwhisk-client-ca-cert.pem
-                val stdout = wsk.cli(Seq("property", "set", "-i", "--apihost", wskprops.apihost, "--auth", wskprops.authKey,
-                    "--cert", wskprops.cert, "--key", wskprops.key, "--namespace", namespace), env = env).stdout
-                stdout should include(s"ok: client cert set")
-                stdout should include(s"ok: client key set")
-                stdout should include(s"ok: whisk auth set")
-                stdout should include(s"ok: whisk API host set to ${wskprops.apihost}")
-                stdout should include(s"ok: whisk namespace set to ${namespace}")
-            } finally {
-                tmpwskprops.delete()
-            }
-        }
+  // If client certificate verification is off, should ingore run below tests.
+  if (!WhiskProperties.getProperty("whisk.ssl.client.verification").equals("off")) {
+    it should "set valid cert key to get expected success result for client certificate verification" in {
+      val tmpwskprops = File.createTempFile("wskprops", ".tmp")
+      try {
+        val namespace = wsk.namespace.list().stdout.trim.split("\n").last
+        val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
+        // Send request to https://<apihost>/api/v1/namespaces, wsk client passes client certificate to nginx, nginx will
+        // verify it by client ca's openwhisk-client-ca-cert.pem
+        val stdout = wsk
+          .cli(
+            Seq(
+              "property",
+              "set",
+              "-i",
+              "--apihost",
+              wskprops.apihost,
+              "--auth",
+              wskprops.authKey,
+              "--cert",
+              wskprops.cert,
+              "--key",
+              wskprops.key,
+              "--namespace",
+              namespace),
+            env = env)
+          .stdout
+        stdout should include(s"ok: client cert set")
+        stdout should include(s"ok: client key set")
+        stdout should include(s"ok: whisk auth set")
+        stdout should include(s"ok: whisk API host set to ${wskprops.apihost}")
+        stdout should include(s"ok: whisk namespace set to ${namespace}")
+      } finally {
+        tmpwskprops.delete()
+      }
+    }
 
-        it should "set invalid cert key to get expected exception result for client certificate verification" in {
-            val tmpwskprops = File.createTempFile("wskprops", ".tmp")
-            try {
-                val namespace = wsk.namespace.list().stdout.trim.split("\n").last
-                val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
-                val thrown = the[Exception] thrownBy wsk.cli(Seq("property", "set", "-i", "--apihost", wskprops.apihost, "--auth", wskprops.authKey,
-                    "--cert", "invalid-cert.pem", "--key", "invalid-key.pem", "--namespace", namespace), env = env)
-                thrown.getMessage should include("cannot validate certificate")
-            } finally {
-                tmpwskprops.delete()
-            }
-        }
+    it should "set invalid cert key to get expected exception result for client certificate verification" in {
+      val tmpwskprops = File.createTempFile("wskprops", ".tmp")
+      try {
+        val namespace = wsk.namespace.list().stdout.trim.split("\n").last
+        val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
+        val thrown = the[Exception] thrownBy wsk.cli(
+          Seq(
+            "property",
+            "set",
+            "-i",
+            "--apihost",
+            wskprops.apihost,
+            "--auth",
+            wskprops.authKey,
+            "--cert",
+            "invalid-cert.pem",
+            "--key",
+            "invalid-key.pem",
+            "--namespace",
+            namespace),
+          env = env)
+        thrown.getMessage should include("cannot validate certificate")
+      } finally {
+        tmpwskprops.delete()
+      }
     }
+  }
 
-    it should "ensure default namespace is used when a blank namespace is set" in {
-        val tmpwskprops = File.createTempFile("wskprops", ".tmp")
-        try {
-            val writer = new BufferedWriter(new FileWriter(tmpwskprops))
-            writer.write(s"NAMESPACE=")
-            writer.close()
-            val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
-            val stdout = wsk.cli(Seq("property", "get", "-i", "--namespace"), env = env).stdout
-            stdout should include regex ("whisk namespace\\s+_")
-        } finally {
-            tmpwskprops.delete()
-        }
+  it should "ensure default namespace is used when a blank namespace is set" in {
+    val tmpwskprops = File.createTempFile("wskprops", ".tmp")
+    try {
+      val writer = new BufferedWriter(new FileWriter(tmpwskprops))
+      writer.write(s"NAMESPACE=")
+      writer.close()
+      val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
+      val stdout = wsk.cli(Seq("property", "get", "-i", "--namespace"), env = env).stdout
+      stdout should include regex ("whisk namespace\\s+_")
+    } finally {
+      tmpwskprops.delete()
     }
+  }
 
-    it should "show api build version using property file" in {
-        val tmpwskprops = File.createTempFile("wskprops", ".tmp")
-        try {
-            val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
-            wsk.cli(Seq("property", "set", "-i") ++ wskprops.overrides, env = env)
-            val stdout = wsk.cli(Seq("property", "get", "--apibuild", "-i"), env = env).stdout
-            stdout should include regex ("""(?i)whisk API build\s+201.*""")
-        } finally {
-            tmpwskprops.delete()
-        }
+  it should "show api build version using property file" in {
+    val tmpwskprops = File.createTempFile("wskprops", ".tmp")
+    try {
+      val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
+      wsk.cli(Seq("property", "set", "-i") ++ wskprops.overrides, env = env)
+      val stdout = wsk.cli(Seq("property", "get", "--apibuild", "-i"), env = env).stdout
+      stdout should include regex ("""(?i)whisk API build\s+201.*""")
+    } finally {
+      tmpwskprops.delete()
     }
+  }
 
-    it should "show api build using http apihost" in {
-        val tmpwskprops = File.createTempFile("wskprops", ".tmp")
-        try {
-            val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
-            val apihost = s"http://${WhiskProperties.getBaseControllerAddress()}"
-            wsk.cli(Seq("property", "set", "--apihost", apihost), env = env)
-            val rr = wsk.cli(Seq("property", "get", "--apibuild", "-i"), env = env)
-            rr.stdout should not include regex("""whisk API build\s*Unknown""")
-            rr.stderr should not include regex("Unable to obtain API build information")
-            rr.stdout should include regex ("""(?i)whisk API build\s+201.*""")
-        } finally {
-            tmpwskprops.delete()
-        }
+  it should "show api build using http apihost" in {
+    val tmpwskprops = File.createTempFile("wskprops", ".tmp")
+    try {
+      val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
+      val apihost = s"http://${WhiskProperties.getBaseControllerAddress()}"
+      wsk.cli(Seq("property", "set", "--apihost", apihost), env = env)
+      val rr = wsk.cli(Seq("property", "get", "--apibuild", "-i"), env = env)
+      rr.stdout should not include regex("""whisk API build\s*Unknown""")
+      rr.stderr should not include regex("Unable to obtain API build information")
+      rr.stdout should include regex ("""(?i)whisk API build\s+201.*""")
+    } finally {
+      tmpwskprops.delete()
     }
+  }
 
-    it should "set auth in property file" in {
-        val tmpwskprops = File.createTempFile("wskprops", ".tmp")
-        val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
-        wsk.cli(Seq("property", "set", "--auth", "testKey"), env = env)
-        try {
-            val fileContent = FileUtils.readFileToString(tmpwskprops)
-            fileContent should include("AUTH=testKey")
-        } finally {
-            tmpwskprops.delete()
-        }
+  it should "set auth in property file" in {
+    val tmpwskprops = File.createTempFile("wskprops", ".tmp")
+    val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
+    wsk.cli(Seq("property", "set", "--auth", "testKey"), env = env)
+    try {
+      val fileContent = FileUtils.readFileToString(tmpwskprops)
+      fileContent should include("AUTH=testKey")
+    } finally {
+      tmpwskprops.delete()
     }
+  }
 
-    it should "set multiple property values with single command" in {
-        val tmpwskprops = File.createTempFile("wskprops", ".tmp")
-        val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
-        val stdout = wsk.cli(Seq("property", "set", "--auth", "testKey", "--cert", "cert.pem", "--key", "key.pem", "--apihost", "openwhisk.ng.bluemix.net", "--apiversion", "v1"), env = env).stdout
-        try {
-            stdout should include regex ("ok: whisk auth set")
-            stdout should include regex ("ok: client cert set")
-            stdout should include regex ("ok: client key set")
-            stdout should include regex ("ok: whisk API host set")
-            stdout should include regex ("ok: whisk API version set")
-            val fileContent = FileUtils.readFileToString(tmpwskprops)
-            fileContent should include("AUTH=testKey")
-            fileContent should include("APIHOST=openwhisk.ng.bluemix.net")
-            fileContent should include("APIVERSION=v1")
-        } finally {
-            tmpwskprops.delete()
-        }
+  it should "set multiple property values with single command" in {
+    val tmpwskprops = File.createTempFile("wskprops", ".tmp")
+    val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
+    val stdout = wsk
+      .cli(
+        Seq(
+          "property",
+          "set",
+          "--auth",
+          "testKey",
+          "--cert",
+          "cert.pem",
+          "--key",
+          "key.pem",
+          "--apihost",
+          "openwhisk.ng.bluemix.net",
+          "--apiversion",
+          "v1"),
+        env = env)
+      .stdout
+    try {
+      stdout should include regex ("ok: whisk auth set")
+      stdout should include regex ("ok: client cert set")
+      stdout should include regex ("ok: client key set")
+      stdout should include regex ("ok: whisk API host set")
+      stdout should include regex ("ok: whisk API version set")
+      val fileContent = FileUtils.readFileToString(tmpwskprops)
+      fileContent should include("AUTH=testKey")
+      fileContent should include("APIHOST=openwhisk.ng.bluemix.net")
+      fileContent should include("APIVERSION=v1")
+    } finally {
+      tmpwskprops.delete()
     }
+  }
 
-    it should "create a trigger using property file" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "listTriggers"
-            val tmpProps = File.createTempFile("wskprops", ".tmp")
-            val env = Map("WSK_CONFIG_FILE" -> tmpProps.getAbsolutePath())
-            wsk.cli(Seq("property", "set", "--auth", wp.authKey) ++ wskprops.overrides, env = env)
-            assetHelper.withCleaner(wsk.trigger, name) {
-                (trigger, _) =>
-                    wsk.cli(Seq("-i", "trigger", "create", name), env = env)
-            }
-            tmpProps.delete()
+  it should "create a trigger using property file" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "listTriggers"
+    val tmpProps = File.createTempFile("wskprops", ".tmp")
+    val env = Map("WSK_CONFIG_FILE" -> tmpProps.getAbsolutePath())
+    wsk.cli(Seq("property", "set", "--auth", wp.authKey) ++ wskprops.overrides, env = env)
+    assetHelper.withCleaner(wsk.trigger, name) { (trigger, _) =>
+      wsk.cli(Seq("-i", "trigger", "create", name), env = env)
     }
+    tmpProps.delete()
+  }
 }
diff --git a/tests/src/test/scala/whisk/core/cli/test/WskEntitlementTests.scala b/tests/src/test/scala/whisk/core/cli/test/WskEntitlementTests.scala
index 7f83762..8140cb4 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskEntitlementTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskEntitlementTests.scala
@@ -35,326 +35,315 @@ import whisk.core.entity.Subject
 import whisk.core.entity.WhiskPackage
 
 @RunWith(classOf[JUnitRunner])
-class WskEntitlementTests
-    extends TestHelpers
-    with WskTestHelpers
-    with BeforeAndAfterAll {
-
-    val wsk = new Wsk
-    lazy val defaultWskProps = WskProps()
-    lazy val guestWskProps = getAdditionalTestSubject(Subject().asString)
-
-    override def afterAll() = {
-        disposeAdditionalTestSubject(guestWskProps.namespace)
+class WskEntitlementTests extends TestHelpers with WskTestHelpers with BeforeAndAfterAll {
+
+  val wsk = new Wsk
+  lazy val defaultWskProps = WskProps()
+  lazy val guestWskProps = getAdditionalTestSubject(Subject().asString)
+
+  override def afterAll() = {
+    disposeAdditionalTestSubject(guestWskProps.namespace)
+  }
+
+  val samplePackage = "samplePackage"
+  val sampleAction = "sampleAction"
+  val fullSampleActionName = s"$samplePackage/$sampleAction"
+  val guestNamespace = guestWskProps.namespace
+
+  behavior of "Wsk Package Entitlement"
+
+  it should "not allow unauthorized subject to operate on private action" in withAssetCleaner(guestWskProps) {
+    (wp, assetHelper) =>
+      val privateAction = "privateAction"
+
+      assetHelper.withCleaner(wsk.action, privateAction) { (action, name) =>
+        action.create(name, Some(TestUtils.getTestActionFilename("hello.js")))(wp)
+      }
+
+      val fullyQualifiedActionName = s"/$guestNamespace/$privateAction"
+      wsk.action.get(fullyQualifiedActionName, expectedExitCode = FORBIDDEN)(defaultWskProps).stderr should include(
+        "not authorized")
+
+      withAssetCleaner(defaultWskProps) { (wp, assetHelper) =>
+        assetHelper.withCleaner(wsk.action, fullyQualifiedActionName, confirmDelete = false) { (action, name) =>
+          val rr = action.create(name, None, update = true, expectedExitCode = FORBIDDEN)(wp)
+          rr.stderr should include("not authorized")
+          rr
+        }
+        assetHelper.withCleaner(wsk.action, "unauthorized sequence", confirmDelete = false) { (action, name) =>
+          val rr = action.create(
+            name,
+            Some(fullyQualifiedActionName),
+            kind = Some("sequence"),
+            update = true,
+            expectedExitCode = FORBIDDEN)(wp)
+          rr.stderr should include("not authorized")
+          rr
+        }
+      }
+
+      wsk.action.delete(fullyQualifiedActionName, expectedExitCode = FORBIDDEN)(defaultWskProps).stderr should include(
+        "not authorized")
+
+      wsk.action.invoke(fullyQualifiedActionName, expectedExitCode = FORBIDDEN)(defaultWskProps).stderr should include(
+        "not authorized")
+  }
+
+  it should "reject deleting action in shared package not owned by authkey" in withAssetCleaner(guestWskProps) {
+    (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.pkg, samplePackage) { (pkg, _) =>
+        pkg.create(samplePackage, shared = Some(true))(wp)
+      }
+
+      assetHelper.withCleaner(wsk.action, fullSampleActionName) {
+        val file = Some(TestUtils.getTestActionFilename("empty.js"))
+        (action, _) =>
+          action.create(fullSampleActionName, file)(wp)
+      }
+
+      val fullyQualifiedActionName = s"/$guestNamespace/$fullSampleActionName"
+      wsk.action.get(fullyQualifiedActionName)(defaultWskProps)
+      wsk.action.delete(fullyQualifiedActionName, expectedExitCode = FORBIDDEN)(defaultWskProps)
+  }
+
+  it should "reject create action in shared package not owned by authkey" in withAssetCleaner(guestWskProps) {
+    (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.pkg, samplePackage) { (pkg, name) =>
+        pkg.create(name, shared = Some(true))(wp)
+      }
+
+      val fullyQualifiedActionName = s"/$guestNamespace/notallowed"
+      val file = Some(TestUtils.getTestActionFilename("empty.js"))
+
+      withAssetCleaner(defaultWskProps) { (wp, assetHelper) =>
+        assetHelper.withCleaner(wsk.action, fullyQualifiedActionName, confirmDelete = false) { (action, name) =>
+          action.create(name, file, expectedExitCode = FORBIDDEN)(wp)
+        }
+      }
+  }
+
+  it should "reject update action in shared package not owned by authkey" in withAssetCleaner(guestWskProps) {
+    (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.pkg, samplePackage) { (pkg, _) =>
+        pkg.create(samplePackage, shared = Some(true))(wp)
+      }
+
+      assetHelper.withCleaner(wsk.action, fullSampleActionName) {
+        val file = Some(TestUtils.getTestActionFilename("empty.js"))
+        (action, _) =>
+          action.create(fullSampleActionName, file)(wp)
+      }
+
+      val fullyQualifiedActionName = s"/$guestNamespace/$fullSampleActionName"
+      wsk.action.create(fullyQualifiedActionName, None, update = true, expectedExitCode = FORBIDDEN)(defaultWskProps)
+  }
+
+  behavior of "Wsk Package Listing"
+
+  it should "list shared packages" in withAssetCleaner(guestWskProps) { (wp, assetHelper) =>
+    assetHelper.withCleaner(wsk.pkg, samplePackage) { (pkg, _) =>
+      pkg.create(samplePackage, shared = Some(true))(wp)
     }
 
-    val samplePackage = "samplePackage"
-    val sampleAction = "sampleAction"
-    val fullSampleActionName = s"$samplePackage/$sampleAction"
-    val guestNamespace = guestWskProps.namespace
-
-    behavior of "Wsk Package Entitlement"
-
-    it should "not allow unauthorized subject to operate on private action" in withAssetCleaner(guestWskProps) {
-        (wp, assetHelper) =>
-            val privateAction = "privateAction"
-
-            assetHelper.withCleaner(wsk.action, privateAction) {
-                (action, name) => action.create(name, Some(TestCLIUtils.getTestActionFilename("hello.js")))(wp)
-            }
-
-            val fullyQualifiedActionName = s"/$guestNamespace/$privateAction"
-            wsk.action.get(fullyQualifiedActionName, expectedExitCode = FORBIDDEN)(defaultWskProps).
-                stderr should include("not authorized")
-
-            withAssetCleaner(defaultWskProps) {
-                (wp, assetHelper) =>
-                    assetHelper.withCleaner(wsk.action, fullyQualifiedActionName, confirmDelete = false) {
-                        (action, name) =>
-                            val rr = action.create(name, None, update = true, expectedExitCode = FORBIDDEN)(wp)
-                            rr.stderr should include("not authorized")
-                            rr
-                    }
-                    assetHelper.withCleaner(wsk.action, "unauthorized sequence", confirmDelete = false) {
-                        (action, name) =>
-                            val rr = action.create(name, Some(fullyQualifiedActionName), kind = Some("sequence"), update = true, expectedExitCode = FORBIDDEN)(wp)
-                            rr.stderr should include("not authorized")
-                            rr
-                    }
-            }
-
-            wsk.action.delete(fullyQualifiedActionName, expectedExitCode = FORBIDDEN)(defaultWskProps).
-                stderr should include("not authorized")
-
-            wsk.action.invoke(fullyQualifiedActionName, expectedExitCode = FORBIDDEN)(defaultWskProps).
-                stderr should include("not authorized")
-    }
+    val fullyQualifiedPackageName = s"/$guestNamespace/$samplePackage"
+    val result = wsk.pkg.list(Some(s"/$guestNamespace"))(defaultWskProps).stdout
+    result should include regex (fullyQualifiedPackageName + """\s+shared""")
+  }
 
-    it should "reject deleting action in shared package not owned by authkey" in withAssetCleaner(guestWskProps) {
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.pkg, samplePackage) {
-                (pkg, _) => pkg.create(samplePackage, shared = Some(true))(wp)
-            }
+  it should "not list private packages" in withAssetCleaner(guestWskProps) { (wp, assetHelper) =>
+    assetHelper.withCleaner(wsk.pkg, samplePackage) { (pkg, _) =>
+      pkg.create(samplePackage)(wp)
+    }
 
-            assetHelper.withCleaner(wsk.action, fullSampleActionName) {
-                val file = Some(TestCLIUtils.getTestActionFilename("empty.js"))
-                (action, _) => action.create(fullSampleActionName, file)(wp)
-            }
+    val fullyQualifiedPackageName = s"/$guestNamespace/$samplePackage"
+    val result = wsk.pkg.list(Some(s"/$guestNamespace"))(defaultWskProps).stdout
+    result should not include regex(fullyQualifiedPackageName)
+  }
 
-            val fullyQualifiedActionName = s"/$guestNamespace/$fullSampleActionName"
-            wsk.action.get(fullyQualifiedActionName)(defaultWskProps)
-            wsk.action.delete(fullyQualifiedActionName, expectedExitCode = FORBIDDEN)(defaultWskProps)
+  it should "list shared package actions" in withAssetCleaner(guestWskProps) { (wp, assetHelper) =>
+    assetHelper.withCleaner(wsk.pkg, samplePackage) { (pkg, _) =>
+      pkg.create(samplePackage, shared = Some(true))(wp)
     }
 
-    it should "reject create action in shared package not owned by authkey" in withAssetCleaner(guestWskProps) {
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.pkg, samplePackage) {
-                (pkg, name) => pkg.create(name, shared = Some(true))(wp)
-            }
-
-            val fullyQualifiedActionName = s"/$guestNamespace/notallowed"
-            val file = Some(TestCLIUtils.getTestActionFilename("empty.js"))
-
-            withAssetCleaner(defaultWskProps) {
-                (wp, assetHelper) =>
-                    assetHelper.withCleaner(wsk.action, fullyQualifiedActionName, confirmDelete = false) {
-                        (action, name) => action.create(name, file, expectedExitCode = FORBIDDEN)(wp)
-                    }
-            }
+    assetHelper.withCleaner(wsk.action, fullSampleActionName) {
+      val file = Some(TestUtils.getTestActionFilename("empty.js"))
+      (action, _) =>
+        action.create(fullSampleActionName, file, kind = Some("nodejs:default"))(wp)
     }
 
-    it should "reject update action in shared package not owned by authkey" in withAssetCleaner(guestWskProps) {
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.pkg, samplePackage) {
-                (pkg, _) => pkg.create(samplePackage, shared = Some(true))(wp)
-            }
+    val fullyQualifiedPackageName = s"/$guestNamespace/$samplePackage"
+    val fullyQualifiedActionName = s"/$guestNamespace/$fullSampleActionName"
+    val result = wsk.action.list(Some(fullyQualifiedPackageName))(defaultWskProps).stdout
+    result should include regex (fullyQualifiedActionName)
+  }
 
-            assetHelper.withCleaner(wsk.action, fullSampleActionName) {
-                val file = Some(TestCLIUtils.getTestActionFilename("empty.js"))
-                (action, _) => action.create(fullSampleActionName, file)(wp)
-            }
+  behavior of "Wsk Package Binding"
 
-            val fullyQualifiedActionName = s"/$guestNamespace/$fullSampleActionName"
-            wsk.action.create(fullyQualifiedActionName, None, update = true, expectedExitCode = FORBIDDEN)(defaultWskProps)
+  it should "create a package binding" in withAssetCleaner(guestWskProps) { (wp, assetHelper) =>
+    assetHelper.withCleaner(wsk.pkg, samplePackage) { (pkg, _) =>
+      pkg.create(samplePackage, shared = Some(true))(wp)
     }
 
-    behavior of "Wsk Package Listing"
-
-    it should "list shared packages" in withAssetCleaner(guestWskProps) {
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.pkg, samplePackage) {
-                (pkg, _) => pkg.create(samplePackage, shared = Some(true))(wp)
-            }
-
-            val fullyQualifiedPackageName = s"/$guestNamespace/$samplePackage"
-            val result = wsk.pkg.list(Some(s"/$guestNamespace"))(defaultWskProps).stdout
-            result should include regex (fullyQualifiedPackageName + """\s+shared""")
+    val name = "bindPackage"
+    val annotations = Map("a" -> "A".toJson, WhiskPackage.bindingFieldName -> "xxx".toJson)
+    val provider = s"/$guestNamespace/$samplePackage"
+    withAssetCleaner(defaultWskProps) { (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.pkg, name) { (pkg, _) =>
+        pkg.bind(provider, name, annotations = annotations)(wp)
+      }
+
+      val stdout = wsk.pkg.get(name)(defaultWskProps).stdout
+      val annotationString = wsk.parseJsonString(stdout).fields("annotations").toString
+      annotationString should include regex (""""key":"a"""")
+      annotationString should include regex (""""value":"A"""")
+      annotationString should include regex (s""""key":"${WhiskPackage.bindingFieldName}"""")
+      annotationString should not include regex(""""key":"xxx"""")
+      annotationString should include regex (s""""name":"${samplePackage}"""")
     }
+  }
 
-    it should "not list private packages" in withAssetCleaner(guestWskProps) {
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.pkg, samplePackage) {
-                (pkg, _) => pkg.create(samplePackage)(wp)
-            }
-
-            val fullyQualifiedPackageName = s"/$guestNamespace/$samplePackage"
-            val result = wsk.pkg.list(Some(s"/$guestNamespace"))(defaultWskProps).stdout
-            result should not include regex(fullyQualifiedPackageName)
+  it should "not create a package binding for private package" in withAssetCleaner(guestWskProps) { (wp, assetHelper) =>
+    assetHelper.withCleaner(wsk.pkg, samplePackage) { (pkg, _) =>
+      pkg.create(samplePackage, shared = Some(false))(wp)
     }
 
-    it should "list shared package actions" in withAssetCleaner(guestWskProps) {
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.pkg, samplePackage) {
-                (pkg, _) => pkg.create(samplePackage, shared = Some(true))(wp)
-            }
-
-            assetHelper.withCleaner(wsk.action, fullSampleActionName) {
-                val file = Some(TestCLIUtils.getTestActionFilename("empty.js"))
-                (action, _) => action.create(fullSampleActionName, file, kind = Some("nodejs:default"))(wp)
-            }
-
-            val fullyQualifiedPackageName = s"/$guestNamespace/$samplePackage"
-            val fullyQualifiedActionName = s"/$guestNamespace/$fullSampleActionName"
-            val result = wsk.action.list(Some(fullyQualifiedPackageName))(defaultWskProps).stdout
-            result should include regex (fullyQualifiedActionName)
+    val name = "bindPackage"
+    val provider = s"/$guestNamespace/$samplePackage"
+    withAssetCleaner(defaultWskProps) { (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.pkg, name, confirmDelete = false) { (pkg, _) =>
+        pkg.bind(provider, name, expectedExitCode = FORBIDDEN)(wp)
+      }
     }
+  }
+
+  behavior of "Wsk Package Action"
 
-    behavior of "Wsk Package Binding"
-
-    it should "create a package binding" in withAssetCleaner(guestWskProps) {
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.pkg, samplePackage) {
-                (pkg, _) => pkg.create(samplePackage, shared = Some(true))(wp)
-            }
-
-            val name = "bindPackage"
-            val annotations = Map("a" -> "A".toJson, WhiskPackage.bindingFieldName -> "xxx".toJson)
-            val provider = s"/$guestNamespace/$samplePackage"
-            withAssetCleaner(defaultWskProps) {
-                (wp, assetHelper) =>
-                    assetHelper.withCleaner(wsk.pkg, name) {
-                        (pkg, _) => pkg.bind(provider, name, annotations = annotations)(wp)
-                    }
-
-                    val stdout = wsk.pkg.get(name)(defaultWskProps).stdout
-                    val annotationString = wsk.parseJsonString(stdout).fields("annotations").toString
-                    annotationString should include regex (""""key":"a"""")
-                    annotationString should include regex (""""value":"A"""")
-                    annotationString should include regex (s""""key":"${WhiskPackage.bindingFieldName}"""")
-                    annotationString should not include regex(""""key":"xxx"""")
-                    annotationString should include regex (s""""name":"${samplePackage}"""")
-            }
+  it should "get and invoke an action from package" in withAssetCleaner(guestWskProps) { (wp, assetHelper) =>
+    assetHelper.withCleaner(wsk.pkg, samplePackage) { (pkg, _) =>
+      pkg.create(samplePackage, parameters = Map("a" -> "A".toJson), shared = Some(true))(wp)
     }
 
-    it should "not create a package binding for private package" in withAssetCleaner(guestWskProps) {
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.pkg, samplePackage) {
-                (pkg, _) => pkg.create(samplePackage, shared = Some(false))(wp)
-            }
-
-            val name = "bindPackage"
-            val provider = s"/$guestNamespace/$samplePackage"
-            withAssetCleaner(defaultWskProps) {
-                (wp, assetHelper) =>
-                    assetHelper.withCleaner(wsk.pkg, name, confirmDelete = false) {
-                        (pkg, _) => pkg.bind(provider, name, expectedExitCode = FORBIDDEN)(wp)
-                    }
-            }
+    assetHelper.withCleaner(wsk.action, fullSampleActionName) {
+      val file = Some(TestUtils.getTestActionFilename("hello.js"))
+      (action, _) =>
+        action.create(fullSampleActionName, file)(wp)
     }
 
-    behavior of "Wsk Package Action"
+    val fullyQualifiedActionName = s"/$guestNamespace/$fullSampleActionName"
+    val stdout = wsk.action.get(fullyQualifiedActionName)(defaultWskProps).stdout
+    stdout should include("name")
+    stdout should include("parameters")
+    stdout should include("limits")
+    stdout should include regex (""""key": "a"""")
+    stdout should include regex (""""value": "A"""")
 
-    it should "get and invoke an action from package" in withAssetCleaner(guestWskProps) {
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.pkg, samplePackage) {
-                (pkg, _) => pkg.create(samplePackage, parameters = Map("a" -> "A".toJson), shared = Some(true))(wp)
-            }
+    val run = wsk.action.invoke(fullyQualifiedActionName)(defaultWskProps)
 
-            assetHelper.withCleaner(wsk.action, fullSampleActionName) {
-                val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
-                (action, _) => action.create(fullSampleActionName, file)(wp)
-            }
+    withActivation(wsk.activation, run)({
+      _.response.success shouldBe true
+    })(defaultWskProps)
+  }
 
-            val fullyQualifiedActionName = s"/$guestNamespace/$fullSampleActionName"
-            val stdout = wsk.action.get(fullyQualifiedActionName)(defaultWskProps).stdout
-            stdout should include("name")
-            stdout should include("parameters")
-            stdout should include("limits")
-            stdout should include regex (""""key": "a"""")
-            stdout should include regex (""""value": "A"""")
+  it should "invoke an action sequence from package" in withAssetCleaner(guestWskProps) { (wp, assetHelper) =>
+    assetHelper.withCleaner(wsk.pkg, samplePackage) { (pkg, _) =>
+      pkg.create(samplePackage, parameters = Map("a" -> "A".toJson), shared = Some(true))(wp)
+    }
+
+    assetHelper.withCleaner(wsk.action, fullSampleActionName) {
+      val file = Some(TestUtils.getTestActionFilename("hello.js"))
+      (action, _) =>
+        action.create(fullSampleActionName, file)(wp)
+    }
 
-            val run = wsk.action.invoke(fullyQualifiedActionName)(defaultWskProps)
+    withAssetCleaner(defaultWskProps) { (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.action, "sequence") { (action, name) =>
+        val fullyQualifiedActionName = s"/$guestNamespace/$fullSampleActionName"
+        action.create(name, Some(fullyQualifiedActionName), kind = Some("sequence"), update = true)(wp)
+      }
 
-            withActivation(wsk.activation, run)({
-                _.response.success shouldBe true
-            })(defaultWskProps)
+      val run = wsk.action.invoke("sequence")(defaultWskProps)
+      withActivation(wsk.activation, run)({
+        _.response.success shouldBe true
+      })(defaultWskProps)
+    }
+  }
+
+  it should "not allow invoke an action sequence with more than one component from package after entitlement change" in withAssetCleaner(
+    guestWskProps) { (guestwp, assetHelper) =>
+    val privateSamplePackage = samplePackage + "prv"
+    assetHelper.withCleaner(wsk.pkg, samplePackage) { (pkg, _) =>
+      pkg.create(samplePackage, parameters = Map("a" -> "A".toJson), shared = Some(true))(guestwp)
+      pkg.create(privateSamplePackage, parameters = Map("a" -> "A".toJson), shared = Some(true))(guestwp)
     }
 
-    it should "invoke an action sequence from package" in withAssetCleaner(guestWskProps) {
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.pkg, samplePackage) {
-                (pkg, _) => pkg.create(samplePackage, parameters = Map("a" -> "A".toJson), shared = Some(true))(wp)
-            }
-
-            assetHelper.withCleaner(wsk.action, fullSampleActionName) {
-                val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
-                (action, _) => action.create(fullSampleActionName, file)(wp)
-            }
-
-            withAssetCleaner(defaultWskProps) {
-                (wp, assetHelper) =>
-                    assetHelper.withCleaner(wsk.action, "sequence") {
-                        (action, name) =>
-                            val fullyQualifiedActionName = s"/$guestNamespace/$fullSampleActionName"
-                            action.create(name, Some(fullyQualifiedActionName), kind = Some("sequence"), update = true)(wp)
-                    }
-
-                    val run = wsk.action.invoke("sequence")(defaultWskProps)
-                    withActivation(wsk.activation, run)({
-                        _.response.success shouldBe true
-                    })(defaultWskProps)
-            }
+    assetHelper.withCleaner(wsk.action, fullSampleActionName) {
+      val file = Some(TestUtils.getTestActionFilename("hello.js"))
+      (action, _) =>
+        action.create(fullSampleActionName, file)(guestwp)
+        action.create(s"$privateSamplePackage/$sampleAction", file)(guestwp)
     }
 
-    it should "not allow invoke an action sequence with more than one component from package after entitlement change" in withAssetCleaner(guestWskProps) {
-        (guestwp, assetHelper) =>
-            val privateSamplePackage = samplePackage + "prv"
-            assetHelper.withCleaner(wsk.pkg, samplePackage) {
-                (pkg, _) =>
-                    pkg.create(samplePackage, parameters = Map("a" -> "A".toJson), shared = Some(true))(guestwp)
-                    pkg.create(privateSamplePackage, parameters = Map("a" -> "A".toJson), shared = Some(true))(guestwp)
-            }
-
-            assetHelper.withCleaner(wsk.action, fullSampleActionName) {
-                val file = Some(TestCLIUtils.getTestActionFilename("hello.js"))
-                (action, _) =>
-                    action.create(fullSampleActionName, file)(guestwp)
-                    action.create(s"$privateSamplePackage/$sampleAction", file)(guestwp)
-            }
-
-            withAssetCleaner(defaultWskProps) {
-                (dwp, assetHelper) =>
-                    assetHelper.withCleaner(wsk.action, "sequence") {
-                        (action, name) =>
-                            val fullyQualifiedActionName = s"/$guestNamespace/$fullSampleActionName"
-                            val fullyQualifiedActionName2 = s"/$guestNamespace/$privateSamplePackage/$sampleAction"
-                            action.create(name, Some(s"$fullyQualifiedActionName,$fullyQualifiedActionName2"),
-                                kind = Some("sequence"))(dwp)
-                    }
-
-                    // change package visibility
-                    wsk.pkg.create(privateSamplePackage, update = true, shared = Some(false))(guestwp)
-                    wsk.action.invoke("sequence", expectedExitCode = FORBIDDEN)(defaultWskProps)
-            }
+    withAssetCleaner(defaultWskProps) { (dwp, assetHelper) =>
+      assetHelper.withCleaner(wsk.action, "sequence") { (action, name) =>
+        val fullyQualifiedActionName = s"/$guestNamespace/$fullSampleActionName"
+        val fullyQualifiedActionName2 = s"/$guestNamespace/$privateSamplePackage/$sampleAction"
+        action.create(name, Some(s"$fullyQualifiedActionName,$fullyQualifiedActionName2"), kind = Some("sequence"))(dwp)
+      }
+
+      // change package visibility
+      wsk.pkg.create(privateSamplePackage, update = true, shared = Some(false))(guestwp)
+      wsk.action.invoke("sequence", expectedExitCode = FORBIDDEN)(defaultWskProps)
     }
+  }
+
+  it should "invoke a packaged action not owned by the subject to get the subject's namespace" in withAssetCleaner(
+    guestWskProps) { (_, assetHelper) =>
+    val packageName = "namespacePackage"
+    val actionName = "namespaceAction"
+    val packagedActionName = s"$packageName/$actionName"
 
-    it should "invoke a packaged action not owned by the subject to get the subject's namespace" in withAssetCleaner(guestWskProps) {
-        (_, assetHelper) =>
-            val packageName = "namespacePackage"
-            val actionName = "namespaceAction"
-            val packagedActionName = s"$packageName/$actionName"
-
-            assetHelper.withCleaner(wsk.pkg, packageName) {
-                (pkg, _) => pkg.create(packageName, shared = Some(true))(guestWskProps)
-            }
-
-            assetHelper.withCleaner(wsk.action, packagedActionName) {
-                val file = Some(TestCLIUtils.getTestActionFilename("helloContext.js"))
-                (action, _) => action.create(packagedActionName, file)(guestWskProps)
-            }
-
-            val fullyQualifiedActionName = s"/$guestNamespace/$packagedActionName"
-            val run = wsk.action.invoke(fullyQualifiedActionName)(defaultWskProps)
-
-            withActivation(wsk.activation, run)({ activation =>
-                val namespace = wsk.namespace.whois()(defaultWskProps)
-                activation.response.success shouldBe true
-                activation.response.result.get.toString should include regex (s""""namespace":\\s*"$namespace"""")
-            })(defaultWskProps)
+    assetHelper.withCleaner(wsk.pkg, packageName) { (pkg, _) =>
+      pkg.create(packageName, shared = Some(true))(guestWskProps)
     }
 
-    behavior of "Wsk Trigger Feed"
-
-    it should "not create a trigger with timeout error when feed fails to initialize" in withAssetCleaner(guestWskProps) {
-        (wp, assetHelper) =>
-            assetHelper.withCleaner(wsk.pkg, samplePackage) {
-                (pkg, _) => pkg.create(samplePackage, shared = Some(true))(wp)
-            }
-
-            val sampleFeed = s"$samplePackage/sampleFeed"
-            assetHelper.withCleaner(wsk.action, sampleFeed) {
-                val file = Some(TestCLIUtils.getTestActionFilename("empty.js"))
-                (action, _) => action.create(sampleFeed, file, kind = Some("nodejs:default"))(wp)
-            }
-
-            val fullyQualifiedFeedName = s"/$guestNamespace/$sampleFeed"
-            withAssetCleaner(defaultWskProps) {
-                (wp, assetHelper) =>
-                    assetHelper.withCleaner(wsk.trigger, "badfeed", confirmDelete = false) {
-                        (trigger, name) => trigger.create(name, feed = Some(fullyQualifiedFeedName), expectedExitCode = TIMEOUT)(wp)
-                    }
-                    wsk.trigger.get("badfeed", expectedExitCode = NOT_FOUND)(wp)
-            }
+    assetHelper.withCleaner(wsk.action, packagedActionName) {
+      val file = Some(TestUtils.getTestActionFilename("helloContext.js"))
+      (action, _) =>
+        action.create(packagedActionName, file)(guestWskProps)
     }
 
+    val fullyQualifiedActionName = s"/$guestNamespace/$packagedActionName"
+    val run = wsk.action.invoke(fullyQualifiedActionName)(defaultWskProps)
+
+    withActivation(wsk.activation, run)({ activation =>
+      val namespace = wsk.namespace.whois()(defaultWskProps)
+      activation.response.success shouldBe true
+      activation.response.result.get.toString should include regex (s""""namespace":\\s*"$namespace"""")
+    })(defaultWskProps)
+  }
+
+  behavior of "Wsk Trigger Feed"
+
+  it should "not create a trigger with timeout error when feed fails to initialize" in withAssetCleaner(guestWskProps) {
+    (wp, assetHelper) =>
+      assetHelper.withCleaner(wsk.pkg, samplePackage) { (pkg, _) =>
+        pkg.create(samplePackage, shared = Some(true))(wp)
+      }
+
+      val sampleFeed = s"$samplePackage/sampleFeed"
+      assetHelper.withCleaner(wsk.action, sampleFeed) {
+        val file = Some(TestUtils.getTestActionFilename("empty.js"))
+        (action, _) =>
+          action.create(sampleFeed, file, kind = Some("nodejs:default"))(wp)
+      }
+
+      val fullyQualifiedFeedName = s"/$guestNamespace/$sampleFeed"
+      withAssetCleaner(defaultWskProps) { (wp, assetHelper) =>
+        assetHelper.withCleaner(wsk.trigger, "badfeed", confirmDelete = false) { (trigger, name) =>
+          trigger.create(name, feed = Some(fullyQualifiedFeedName), expectedExitCode = TIMEOUT)(wp)
+        }
+        wsk.trigger.get("badfeed", expectedExitCode = NOT_FOUND)(wp)
+      }
+  }
+
 }
diff --git a/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala b/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala
index 8097ce9..c94c36e 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala
@@ -49,295 +49,289 @@ import whisk.core.entity.Subject
  */
 @RunWith(classOf[JUnitRunner])
 class WskWebActionsTests extends TestHelpers with WskTestHelpers with RestUtil with BeforeAndAfterAll {
-    val MAX_URL_LENGTH = 8192 // 8K matching nginx default
+  val MAX_URL_LENGTH = 8192 // 8K matching nginx default
 
-    val wsk = new Wsk
-    private implicit val wskprops = WskProps()
-    val namespace = wsk.namespace.whois()
+  val wsk = new Wsk
+  private implicit val wskprops = WskProps()
+  val namespace = wsk.namespace.whois()
 
-    protected val testRoutePath: String = "/api/v1/web"
+  protected val testRoutePath: String = "/api/v1/web"
 
-    behavior of "Wsk Web Actions"
+  behavior of "Wsk Web Actions"
 
-    /**
-     * Tests web actions, plus max url limit.
-     */
-    it should "create a web action accessible via HTTPS" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "webaction"
-            val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
-            val host = getServiceURL()
-            val requestPath = host + s"$testRoutePath/$namespace/default/$name.text/a?a="
-            val padAmount = MAX_URL_LENGTH - requestPath.length
+  /**
+   * Tests web actions, plus max url limit.
+   */
+  it should "create a web action accessible via HTTPS" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "webaction"
+    val file = Some(TestUtils.getTestActionFilename("echo.js"))
+    val host = getServiceURL()
+    val requestPath = host + s"$testRoutePath/$namespace/default/$name.text/a?a="
+    val padAmount = MAX_URL_LENGTH - requestPath.length
 
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, file, web = Some("true"))
-            }
-
-            Seq(("A", 200),
-                ("A" * padAmount, 200),
-                // ideally the bad case is just +1 but there's some differences
-                // in how characters are counted i.e., whether these count "https://:443"
-                // or not; it seems sufficient to test right around the boundary
-                ("A" * (padAmount + 100), 414))
-                .foreach {
-                    case (pad, code) =>
-                        val url = (requestPath + pad)
-                        val response = RestAssured.given().config(sslconfig).get(url)
-                        val responseCode = response.statusCode
-
-                        withClue(s"response code: $responseCode, url length: ${url.length}, pad amount: ${pad.length}, url: $url") {
-                            responseCode shouldBe code
-                            if (code == 200) {
-                                response.body.asString shouldBe pad
-                            } else {
-                                response.body.asString should include("414 Request-URI Too Large") // from nginx
-                            }
-                        }
-                }
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, file, web = Some("true"))
     }
 
-    /**
-     * Tests web action requiring authentication.
-     */
-    it should "create a web action requiring authentication accessible via HTTPS" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "webaction"
-            val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
-            val host = getServiceURL()
-            val url = s"$host$testRoutePath/$namespace/default/$name.text/__ow_user"
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) =>
-                    action.create(name, file, web = Some("true"), annotations = Map("require-whisk-auth" -> true.toJson))
+    Seq(
+      ("A", 200),
+      ("A" * padAmount, 200),
+      // ideally the bad case is just +1 but there's some differences
+      // in how characters are counted i.e., whether these count "https://:443"
+      // or not; it seems sufficient to test right around the boundary
+      ("A" * (padAmount + 100), 414))
+      .foreach {
+        case (pad, code) =>
+          val url = (requestPath + pad)
+          val response = RestAssured.given().config(sslconfig).get(url)
+          val responseCode = response.statusCode
+
+          withClue(s"response code: $responseCode, url length: ${url.length}, pad amount: ${pad.length}, url: $url") {
+            responseCode shouldBe code
+            if (code == 200) {
+              response.body.asString shouldBe pad
+            } else {
+              response.body.asString should include("414 Request-URI Too Large") // from nginx
             }
-
-            val unauthorizedResponse = RestAssured.given().config(sslconfig).get(url)
-            unauthorizedResponse.statusCode shouldBe 401
-
-            val authorizedResponse = RestAssured
-                .given()
-                .config(sslconfig)
-                .auth().preemptive().basic(wskprops.authKey.split(":")(0), wskprops.authKey.split(":")(1))
-                .get(url)
-
-            authorizedResponse.statusCode shouldBe 200
-            authorizedResponse.body.asString shouldBe namespace
+          }
+      }
+  }
+
+  /**
+   * Tests web action requiring authentication.
+   */
+  it should "create a web action requiring authentication accessible via HTTPS" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "webaction"
+      val file = Some(TestUtils.getTestActionFilename("echo.js"))
+      val host = getServiceURL()
+      val url = s"$host$testRoutePath/$namespace/default/$name.text/__ow_user"
+
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, file, web = Some("true"), annotations = Map("require-whisk-auth" -> true.toJson))
+      }
+
+      val unauthorizedResponse = RestAssured.given().config(sslconfig).get(url)
+      unauthorizedResponse.statusCode shouldBe 401
+
+      val authorizedResponse = RestAssured
+        .given()
+        .config(sslconfig)
+        .auth()
+        .preemptive()
+        .basic(wskprops.authKey.split(":")(0), wskprops.authKey.split(":")(1))
+        .get(url)
+
+      authorizedResponse.statusCode shouldBe 200
+      authorizedResponse.body.asString shouldBe namespace
+  }
+
+  it should "ensure that CORS header is preserved for custom options" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "webaction"
+      val file = Some(TestUtils.getTestActionFilename("corsHeaderMod.js"))
+      val host = getServiceURL()
+      val url = host + s"$testRoutePath/$namespace/default/$name.http"
+
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, file, web = Some("true"), annotations = Map("web-custom-options" -> true.toJson))
+      }
+
+      val response = RestAssured.given().config(sslconfig).options(url)
+
+      response.statusCode shouldBe 200
+      response.header("Access-Control-Allow-Origin") shouldBe "Origin set from Web Action"
+      response.header("Access-Control-Allow-Methods") shouldBe "Methods set from Web Action"
+      response.header("Access-Control-Allow-Headers") shouldBe "Headers set from Web Action"
+      response.header("Location") shouldBe "openwhisk.org"
+      response.header("Set-Cookie") shouldBe "cookie-cookie-cookie"
+  }
+
+  it should "ensure that default CORS header is preserved" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "webaction"
+    val file = Some(TestUtils.getTestActionFilename("corsHeaderMod.js"))
+    val host = getServiceURL()
+    val url = host + s"$testRoutePath/$namespace/default/$name"
+
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, file, web = Some("true"))
     }
 
-    it should "ensure that CORS header is preserved for custom options" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "webaction"
-            val file = Some(TestCLIUtils.getTestActionFilename("corsHeaderMod.js"))
-            val host = getServiceURL()
-            val url = host + s"$testRoutePath/$namespace/default/$name.http"
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) =>
-                    action.create(name, file, web = Some("true"), annotations = Map("web-custom-options" -> true.toJson))
-            }
-
-            val response = RestAssured.given().config(sslconfig).options(url)
-
-            response.statusCode shouldBe 200
-            response.header("Access-Control-Allow-Origin") shouldBe "Origin set from Web Action"
-            response.header("Access-Control-Allow-Methods") shouldBe "Methods set from Web Action"
-            response.header("Access-Control-Allow-Headers") shouldBe "Headers set from Web Action"
-            response.header("Location") shouldBe "openwhisk.org"
-            response.header("Set-Cookie") shouldBe "cookie-cookie-cookie"
+    val responses = Seq(
+      RestAssured.given().config(sslconfig).options(s"$url.http"),
+      RestAssured.given().config(sslconfig).get(s"$url.json"))
+
+    responses.foreach { response =>
+      response.statusCode shouldBe 200
+      response.header("Access-Control-Allow-Origin") shouldBe "*"
+      response.header("Access-Control-Allow-Methods") shouldBe "OPTIONS, GET, DELETE, POST, PUT, HEAD, PATCH"
+      response.header("Access-Control-Allow-Headers") shouldBe "Authorization, Content-Type"
+      response.header("Location") shouldBe null
+      response.header("Set-Cookie") shouldBe null
     }
-
-    it should "ensure that default CORS header is preserved" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "webaction"
-            val file = Some(TestCLIUtils.getTestActionFilename("corsHeaderMod.js"))
-            val host = getServiceURL()
-            val url = host + s"$testRoutePath/$namespace/default/$name"
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, file, web = Some("true"))
-            }
-
-            val responses = Seq(
-                RestAssured.given().config(sslconfig).options(s"$url.http"),
-                RestAssured.given().config(sslconfig).get(s"$url.json"))
-
-            responses.foreach { response =>
-                response.statusCode shouldBe 200
-                response.header("Access-Control-Allow-Origin") shouldBe "*"
-                response.header("Access-Control-Allow-Methods") shouldBe "OPTIONS, GET, DELETE, POST, PUT, HEAD, PATCH"
-                response.header("Access-Control-Allow-Headers") shouldBe "Authorization, Content-Type"
-                response.header("Location") shouldBe null
-                response.header("Set-Cookie") shouldBe null
-            }
+  }
+
+  it should "invoke web action to ensure the returned body argument is correct" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "webaction"
+      val file = Some(TestUtils.getTestActionFilename("echo.js"))
+      val bodyContent = "This is the body"
+      val host = getServiceURL()
+      val url = s"$host$testRoutePath/$namespace/default/webaction.text/__ow_body"
+
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, file, web = Some("true"))
+      }
+
+      val paramRes = RestAssured.given().contentType("text/html").param("key", "value").config(sslconfig).post(url)
+      paramRes.statusCode shouldBe 200
+      new String(paramRes.body.asByteArray, StandardCharsets.UTF_8) shouldBe "key=value"
+
+      val bodyRes = RestAssured.given().contentType("text/html").body(bodyContent).config(sslconfig).post(url)
+      bodyRes.statusCode shouldBe 200
+      new String(bodyRes.body.asByteArray, StandardCharsets.UTF_8) shouldBe bodyContent
+  }
+
+  it should "reject invocation of web action with invalid accept header" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "webaction"
+      val file = Some(TestUtils.getTestActionFilename("textBody.js"))
+      val host = getServiceURL()
+      val url = host + s"$testRoutePath/$namespace/default/$name.http"
+
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, file, web = Some("true"))
+      }
+
+      val response = RestAssured.given().header("accept", "application/json").config(sslconfig).get(url)
+      response.statusCode shouldBe 406
+      response.body.asString should include("Resource representation is only available with these types:\\ntext/html")
+  }
+
+  it should "support multiple response header values" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "webaction"
+    val file = Some(TestUtils.getTestActionFilename("multipleHeaders.js"))
+    val host = getServiceURL()
+    val url = host + s"$testRoutePath/$namespace/default/$name.http"
+
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, file, web = Some("true"), annotations = Map("web-custom-options" -> true.toJson))
     }
 
-    it should "invoke web action to ensure the returned body argument is correct" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "webaction"
-            val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
-            val bodyContent = "This is the body"
-            val host = getServiceURL()
-            val url = s"$host$testRoutePath/$namespace/default/webaction.text/__ow_body"
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, file, web = Some("true"))
-            }
-
-            val paramRes = RestAssured.given().contentType("text/html").param("key", "value").config(sslconfig).post(url)
-            paramRes.statusCode shouldBe 200
-            new String(paramRes.body.asByteArray, StandardCharsets.UTF_8) shouldBe "key=value"
-
-            val bodyRes = RestAssured.given().contentType("text/html").body(bodyContent).config(sslconfig).post(url)
-            bodyRes.statusCode shouldBe 200
-            new String(bodyRes.body.asByteArray, StandardCharsets.UTF_8) shouldBe bodyContent
-    }
+    val response = RestAssured.given().config(sslconfig).options(url)
 
-    it should "reject invocation of web action with invalid accept header" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "webaction"
-            val file = Some(TestCLIUtils.getTestActionFilename("textBody.js"))
-            val host = getServiceURL()
-            val url = host + s"$testRoutePath/$namespace/default/$name.http"
+    response.statusCode shouldBe 200
+    val cookieHeaders = response.headers.getList("Set-Cookie")
+    cookieHeaders should contain allOf (
+      new Header("Set-Cookie", "a=b"),
+      new Header("Set-Cookie", "c=d")
+    )
+  }
 
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) => action.create(name, file, web = Some("true"))
-            }
+  it should "handle http web action with base64 encoded response" in withAssetCleaner(wskprops) { (wp, assetHelper) =>
+    val name = "base64Web"
+    val file = Some(TestUtils.getTestActionFilename("base64Web.js"))
+    val host = getServiceURL
+    val url = host + s"$testRoutePath/$namespace/default/$name.http"
 
-            val response = RestAssured.given().header("accept", "application/json").config(sslconfig).get(url)
-            response.statusCode shouldBe 406
-            response.body.asString should include("Resource representation is only available with these types:\\ntext/html")
+    assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+      action.create(name, file, web = Some("raw"))
     }
 
-    it should "support multiple response header values" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "webaction"
-            val file = Some(TestCLIUtils.getTestActionFilename("multipleHeaders.js"))
-            val host = getServiceURL()
-            val url = host + s"$testRoutePath/$namespace/default/$name.http"
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) =>
-                    action.create(name, file, web = Some("true"), annotations = Map("web-custom-options" -> true.toJson))
-            }
-
-            val response = RestAssured.given().config(sslconfig).options(url)
-
-            response.statusCode shouldBe 200
-            val cookieHeaders = response.headers.getList("Set-Cookie")
-            cookieHeaders should contain allOf (
-                new Header("Set-Cookie", "a=b"),
-                new Header("Set-Cookie", "c=d")
-            )
-    }
-
-    it should "handle http web action with base64 encoded response" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "base64Web"
-            val file = Some(TestCLIUtils.getTestActionFilename("base64Web.js"))
-            val host = getServiceURL
-            val url = host + s"$testRoutePath/$namespace/default/$name.http"
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) =>
-                    action.create(name, file, web = Some("raw"))
-            }
-
-            val response = RestAssured.given().config(sslconfig).get(url)
-
-            response.statusCode shouldBe 200
-            response.header("Content-type") shouldBe "application/json"
-            response.body.asString.parseJson.asJsObject shouldBe JsObject("status" -> "success".toJson)
-    }
-
-    it should "handle http web action with base64 encoded binary response" in withAssetCleaner(wskprops) {
-        (wp, assetHelper) =>
-            val name = "binaryWeb"
-            val file = Some(TestUtils.getTestActionFilename("pngWeb.js"))
-            val host = getServiceURL
-            val url = host + s"$testRoutePath/$namespace/default/$name.http"
-            val png = "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAGCAYAAAD68A/GAAAA/klEQVQYGWNgAAEHBxaG//+ZQMyyn581Pfas+cRQnf1LfF" +
-                "Ljf+62smUgcUbt0FA2Zh7drf/ffMy9vLn3RurrW9e5hCU11i2azfD4zu1/DHz8TAy/foUxsXBrFzHzC7r8+M9S1vn1qxQT07dDjL" +
-                "9fdemrqKxlYGT6z8AIMo6hgeUfA0PUvy9fGFh5GWK3z7vNxSWt++jX99+8SoyiGQwsW38w8PJEM7x5v5SJ8f+/xv8MDAzffv9hev" +
-                "fkWjiXBGMpMx+j2awovjcMjFztDO8+7GF49LkbZDCDeXLTWnZO7qDfn1/+5jbw/8pjYWS4wZLztXnuEuYTk2M+MzIw/AcA36Vewa" +
-                "D6fzsAAAAASUVORK5CYII="
-
-            assetHelper.withCleaner(wsk.action, name) {
-                (action, _) =>
-                    action.create(name, file, web = Some("true"))
-            }
-
-            val response = RestAssured.given().config(sslconfig).get(url)
-
-            response.statusCode shouldBe 200
-            response.header("Content-type") shouldBe "image/png"
-            response.body.asByteArray shouldBe Base64.getDecoder().decode(png)
-    }
-
-    private val subdomainRegex = Seq.fill(WhiskProperties.getPartsInVanitySubdomain)("[a-zA-Z0-9]+").mkString("-")
-
-    private val (vanitySubdomain, vanityNamespace, makeTestSubject) = {
-        if (namespace.matches(subdomainRegex)) {
-            (namespace, namespace, false)
-        } else {
-            val s = Subject().asString.toLowerCase // this will generate two confirming parts
-            (s, s.replace("-", "_"), true)
-        }
-    }
-
-    private val wskPropsForSubdomainTest = if (makeTestSubject) {
-        getAdditionalTestSubject(vanityNamespace) // create new subject for the test
+    val response = RestAssured.given().config(sslconfig).get(url)
+
+    response.statusCode shouldBe 200
+    response.header("Content-type") shouldBe "application/json"
+    response.body.asString.parseJson.asJsObject shouldBe JsObject("status" -> "success".toJson)
+  }
+
+  it should "handle http web action with base64 encoded binary response" in withAssetCleaner(wskprops) {
+    (wp, assetHelper) =>
+      val name = "binaryWeb"
+      val file = Some(TestUtils.getTestActionFilename("pngWeb.js"))
+      val host = getServiceURL
+      val url = host + s"$testRoutePath/$namespace/default/$name.http"
+      val png = "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAGCAYAAAD68A/GAAAA/klEQVQYGWNgAAEHBxaG//+ZQMyyn581Pfas+cRQnf1LfF" +
+        "Ljf+62smUgcUbt0FA2Zh7drf/ffMy9vLn3RurrW9e5hCU11i2azfD4zu1/DHz8TAy/foUxsXBrFzHzC7r8+M9S1vn1qxQT07dDjL" +
+        "9fdemrqKxlYGT6z8AIMo6hgeUfA0PUvy9fGFh5GWK3z7vNxSWt++jX99+8SoyiGQwsW38w8PJEM7x5v5SJ8f+/xv8MDAzffv9hev" +
+        "fkWjiXBGMpMx+j2awovjcMjFztDO8+7GF49LkbZDCDeXLTWnZO7qDfn1/+5jbw/8pjYWS4wZLztXnuEuYTk2M+MzIw/AcA36Vewa" +
+        "D6fzsAAAAASUVORK5CYII="
+
+      assetHelper.withCleaner(wsk.action, name) { (action, _) =>
+        action.create(name, file, web = Some("true"))
+      }
+
+      val response = RestAssured.given().config(sslconfig).get(url)
+
+      response.statusCode shouldBe 200
+      response.header("Content-type") shouldBe "image/png"
+      response.body.asByteArray shouldBe Base64.getDecoder().decode(png)
+  }
+
+  private val subdomainRegex = Seq.fill(WhiskProperties.getPartsInVanitySubdomain)("[a-zA-Z0-9]+").mkString("-")
+
+  private val (vanitySubdomain, vanityNamespace, makeTestSubject) = {
+    if (namespace.matches(subdomainRegex)) {
+      (namespace, namespace, false)
     } else {
-        WskProps()
+      val s = Subject().asString.toLowerCase // this will generate two confirming parts
+      (s, s.replace("-", "_"), true)
     }
+  }
 
-    override def afterAll() = {
-        if (makeTestSubject) {
-            disposeAdditionalTestSubject(vanityNamespace)
-        }
-    }
+  private val wskPropsForSubdomainTest = if (makeTestSubject) {
+    getAdditionalTestSubject(vanityNamespace) // create new subject for the test
+  } else {
+    WskProps()
+  }
 
-    "test subdomain" should "have conforming parts" in {
-        vanitySubdomain should fullyMatch regex subdomainRegex.r
-        vanitySubdomain.length should be <= 63
-    }
-
-    "vanity subdomain" should "access a web action via namespace subdomain" in withAssetCleaner(wskPropsForSubdomainTest) {
-        (wp, assetHelper) =>
-            val actionName = "webaction"
-
-            val file = Some(TestUtils.getTestActionFilename("echo.js"))
-            assetHelper.withCleaner(wsk.action, actionName) {
-                (action, _) => action.create(actionName, file, web = Some(true.toString))(wp)
-            }
-
-            val url = getServiceApiHost(vanitySubdomain, true) + s"/default/$actionName.text/a?a=A"
-            println(s"url: $url")
-
-            // try the rest assured path first, failing that, try curl with explicit resolve
-            Try {
-                val response = RestAssured.given().config(sslconfig).get(url)
-                val responseCode = response.statusCode
-                responseCode shouldBe 200
-                response.body.asString shouldBe "A"
-            } match {
-                case Failure(t) =>
-                    println(s"RestAssured path failed, trying curl: $t")
-                    implicit val tid = TransactionId.testing
-                    implicit val logger = new PrintStreamLogging(Console.out)
-                    val host = getServiceApiHost(vanitySubdomain, false)
-                    // if the edge host is a name, try to resolve it, otherwise, it should be an ip address already
-                    val edgehost = WhiskProperties.getEdgeHost
-                    val ip = Try(java.net.InetAddress.getByName(edgehost).getHostAddress) getOrElse "???"
-                    println(s"edge: $edgehost, ip: $ip")
-                    val cmd = Seq("curl", "-k", url, "--resolve", s"$host:$ip")
-                    val (stdout, stderr, exitCode) = SimpleExec.syncRunCmd(cmd)
-                    withClue(s"\n$stderr\n") {
-                        stdout shouldBe "A"
-                        exitCode shouldBe 0
-                    }
-
-                case _ =>
-            }
+  override def afterAll() = {
+    if (makeTestSubject) {
+      disposeAdditionalTestSubject(vanityNamespace)
     }
+  }
+
+  "test subdomain" should "have conforming parts" in {
+    vanitySubdomain should fullyMatch regex subdomainRegex.r
+    vanitySubdomain.length should be <= 63
+  }
+
+  "vanity subdomain" should "access a web action via namespace subdomain" in withAssetCleaner(wskPropsForSubdomainTest) {
+    (wp, assetHelper) =>
+      val actionName = "webaction"
+
+      val file = Some(TestUtils.getTestActionFilename("echo.js"))
+      assetHelper.withCleaner(wsk.action, actionName) { (action, _) =>
+        action.create(actionName, file, web = Some(true.toString))(wp)
+      }
+
+      val url = getServiceApiHost(vanitySubdomain, true) + s"/default/$actionName.text/a?a=A"
+      println(s"url: $url")
+
+      // try the rest assured path first, failing that, try curl with explicit resolve
+      Try {
+        val response = RestAssured.given().config(sslconfig).get(url)
+        val responseCode = response.statusCode
+        responseCode shouldBe 200
+        response.body.asString shouldBe "A"
+      } match {
+        case Failure(t) =>
+          println(s"RestAssured path failed, trying curl: $t")
+          implicit val tid = TransactionId.testing
+          implicit val logger = new PrintStreamLogging(Console.out)
+          val host = getServiceApiHost(vanitySubdomain, false)
+          // if the edge host is a name, try to resolve it, otherwise, it should be an ip address already
+          val edgehost = WhiskProperties.getEdgeHost
+          val ip = Try(java.net.InetAddress.getByName(edgehost).getHostAddress) getOrElse "???"
+          println(s"edge: $edgehost, ip: $ip")
+          val cmd = Seq("curl", "-k", url, "--resolve", s"$host:$ip")
+          val (stdout, stderr, exitCode) = SimpleExec.syncRunCmd(cmd)
+          withClue(s"\n$stderr\n") {
+            stdout shouldBe "A"
+            exitCode shouldBe 0
+          }
+
+        case _ =>
+      }
+  }
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 08/16: Fix handing of binary content-types in webactions (#2683)

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csantanapr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git

commit 0d50da1e8196167b991224df8a63031be238975f
Author: James Dubee <jw...@us.ibm.com>
AuthorDate: Thu Aug 31 21:34:57 2017 -0400

    Fix handing of binary content-types in webactions (#2683)
---
 .../whisk/core/cli/test/WskWebActionsTests.scala   | 25 ++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala b/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala
index aacc3ad..8097ce9 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala
@@ -18,6 +18,7 @@
 package whisk.core.cli.test
 
 import java.nio.charset.StandardCharsets
+import java.util.Base64
 
 import scala.util.Failure
 import scala.util.Try
@@ -249,6 +250,30 @@ class WskWebActionsTests extends TestHelpers with WskTestHelpers with RestUtil w
             response.body.asString.parseJson.asJsObject shouldBe JsObject("status" -> "success".toJson)
     }
 
+    it should "handle http web action with base64 encoded binary response" in withAssetCleaner(wskprops) {
+        (wp, assetHelper) =>
+            val name = "binaryWeb"
+            val file = Some(TestUtils.getTestActionFilename("pngWeb.js"))
+            val host = getServiceURL
+            val url = host + s"$testRoutePath/$namespace/default/$name.http"
+            val png = "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAGCAYAAAD68A/GAAAA/klEQVQYGWNgAAEHBxaG//+ZQMyyn581Pfas+cRQnf1LfF" +
+                "Ljf+62smUgcUbt0FA2Zh7drf/ffMy9vLn3RurrW9e5hCU11i2azfD4zu1/DHz8TAy/foUxsXBrFzHzC7r8+M9S1vn1qxQT07dDjL" +
+                "9fdemrqKxlYGT6z8AIMo6hgeUfA0PUvy9fGFh5GWK3z7vNxSWt++jX99+8SoyiGQwsW38w8PJEM7x5v5SJ8f+/xv8MDAzffv9hev" +
+                "fkWjiXBGMpMx+j2awovjcMjFztDO8+7GF49LkbZDCDeXLTWnZO7qDfn1/+5jbw/8pjYWS4wZLztXnuEuYTk2M+MzIw/AcA36Vewa" +
+                "D6fzsAAAAASUVORK5CYII="
+
+            assetHelper.withCleaner(wsk.action, name) {
+                (action, _) =>
+                    action.create(name, file, web = Some("true"))
+            }
+
+            val response = RestAssured.given().config(sslconfig).get(url)
+
+            response.statusCode shouldBe 200
+            response.header("Content-type") shouldBe "image/png"
+            response.body.asByteArray shouldBe Base64.getDecoder().decode(png)
+    }
+
     private val subdomainRegex = Seq.fill(WhiskProperties.getPartsInVanitySubdomain)("[a-zA-Z0-9]+").mkString("-")
 
     private val (vanitySubdomain, vanityNamespace, makeTestSubject) = {

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 13/16: CLI User Agent Header (#2591)

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csantanapr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git

commit 2038ba5507f79b6e953736e66e4343b52cab9d04
Author: David Cariello <dr...@us.ibm.com>
AuthorDate: Thu Sep 7 22:33:17 2017 -0500

    CLI User Agent Header (#2591)
---
 tests/src/test/scala/whisk/core/cli/test/WskBasicUsageTests.scala | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/tests/src/test/scala/whisk/core/cli/test/WskBasicUsageTests.scala b/tests/src/test/scala/whisk/core/cli/test/WskBasicUsageTests.scala
index 03b4fc3..6514963 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskBasicUsageTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskBasicUsageTests.scala
@@ -58,6 +58,7 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
   implicit val wskprops = WskProps()
   val wsk = new Wsk
   val defaultAction = Some(TestUtils.getTestActionFilename("hello.js"))
+  val usrAgentHeaderRegEx = """\bUser-Agent\b": \[\s+"OpenWhisk\-CLI/1.\d+.*"""
 
   behavior of "Wsk CLI usage"
 
@@ -117,6 +118,11 @@ class WskBasicUsageTests extends TestHelpers with WskTestHelpers {
       wsk.action.get(fullQualifiedName).stdout should include(s"ok: got action ${packageName}/${actionName}")
   }
 
+  it should "include CLI user agent headers with outbound requests" in {
+    val stdout = wsk.cli(Seq("list", "--auth", wskprops.authKey) ++ wskprops.overrides, verbose = true).stdout
+    stdout should include regex (usrAgentHeaderRegEx)
+  }
+
   behavior of "Wsk actions"
 
   it should "reject creating entities with invalid names" in withAssetCleaner(wskprops) { (wp, assetHelper) =>

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 07/16: remove experimental web actions support

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csantanapr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git

commit 12a12ba99a01239c4e5e6a0afbbd4c73863a94e7
Author: David Cariello <dr...@us.ibm.com>
AuthorDate: Wed Aug 30 19:17:11 2017 -0500

    remove experimental web actions support
---
 .../whisk/core/cli/test/WskWebActionsTests.scala   | 163 +++++++++------------
 1 file changed, 71 insertions(+), 92 deletions(-)

diff --git a/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala b/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala
index 2834948..aacc3ad 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskWebActionsTests.scala
@@ -47,94 +47,14 @@ import whisk.core.entity.Subject
  * Tests web actions.
  */
 @RunWith(classOf[JUnitRunner])
-class WskWebActionsTestsV1 extends WskWebActionsTests {
-    override val testRoutePath = "/api/v1/experimental/web"
-}
-
-@RunWith(classOf[JUnitRunner])
-class WskWebActionsTestsV2 extends WskWebActionsTests with BeforeAndAfterAll {
-    override val testRoutePath = "/api/v1/web"
-
-    private val subdomainRegex = Seq.fill(WhiskProperties.getPartsInVanitySubdomain)("[a-zA-Z0-9]+").mkString("-")
-
-    private val (vanitySubdomain, vanityNamespace, makeTestSubject) = {
-        if (namespace.matches(subdomainRegex)) {
-            (namespace, namespace, false)
-        } else {
-            val s = Subject().asString.toLowerCase // this will generate two confirming parts
-            (s, s.replace("-", "_"), true)
-        }
-    }
-
-    private val wskPropsForSubdomainTest = if (makeTestSubject) {
-        getAdditionalTestSubject(vanityNamespace) // create new subject for the test
-    } else {
-        WskProps()
-    }
-
-    override def afterAll() = {
-        if (makeTestSubject) {
-            disposeAdditionalTestSubject(vanityNamespace)
-        }
-    }
-
-    "test subdomain" should "have conforming parts" in {
-        vanitySubdomain should fullyMatch regex subdomainRegex.r
-        vanitySubdomain.length should be <= 63
-    }
-
-    "vanity subdomain" should "access a web action via namespace subdomain" in withAssetCleaner(wskPropsForSubdomainTest) {
-        (wp, assetHelper) =>
-            val actionName = "webaction"
-            val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
-
-            assetHelper.withCleaner(wsk.action, actionName) {
-                (action, _) => action.create(actionName, file, web = Some(true.toString))(wp)
-            }
-
-            val url = getServiceApiHost(vanitySubdomain, true) + s"/default/$actionName.text/a?a=A"
-            println(s"url: $url")
-
-            // try the rest assured path first, failing that, try curl with explicit resolve
-            Try {
-                val response = RestAssured.given().config(sslconfig).get(url)
-                val responseCode = response.statusCode
-                responseCode shouldBe 200
-                response.body.asString shouldBe "A"
-            } match {
-                case Failure(t) =>
-                    println(s"RestAssured path failed, trying curl: $t")
-                    implicit val tid = TransactionId.testing
-                    implicit val logger = new PrintStreamLogging(Console.out)
-                    val host = getServiceApiHost(vanitySubdomain, false)
-                    // if the edge host is a name, try to resolve it, otherwise, it should be an ip address already
-                    val edgehost = WhiskProperties.getEdgeHost
-                    val ip = Try(java.net.InetAddress.getByName(edgehost).getHostAddress) getOrElse "???"
-                    println(s"edge: $edgehost, ip: $ip")
-                    val cmd = Seq("curl", "-k", url, "--resolve", s"$host:$ip")
-                    val (stdout, stderr, exitCode) = SimpleExec.syncRunCmd(cmd)
-                    withClue(s"\n$stderr\n") {
-                        stdout shouldBe "A"
-                        exitCode shouldBe 0
-                    }
-
-                case _ =>
-            }
-    }
-}
-
-trait WskWebActionsTests
-    extends TestHelpers
-    with WskTestHelpers
-    with RestUtil {
-
+class WskWebActionsTests extends TestHelpers with WskTestHelpers with RestUtil with BeforeAndAfterAll {
     val MAX_URL_LENGTH = 8192 // 8K matching nginx default
 
     val wsk = new Wsk
     private implicit val wskprops = WskProps()
     val namespace = wsk.namespace.whois()
 
-    protected val testRoutePath: String
+    protected val testRoutePath: String = "/api/v1/web"
 
     behavior of "Wsk Web Actions"
 
@@ -184,11 +104,7 @@ trait WskWebActionsTests
             val name = "webaction"
             val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
             val host = getServiceURL()
-            val url = if (testRoutePath == "/api/v1/experimental/web") {
-                s"$host$testRoutePath/$namespace/default/$name.text/__ow_meta_namespace"
-            } else {
-                s"$host$testRoutePath/$namespace/default/$name.text/__ow_user"
-            }
+            val url = s"$host$testRoutePath/$namespace/default/$name.text/__ow_user"
 
             assetHelper.withCleaner(wsk.action, name) {
                 (action, _) =>
@@ -261,11 +177,7 @@ trait WskWebActionsTests
             val file = Some(TestCLIUtils.getTestActionFilename("echo.js"))
             val bodyContent = "This is the body"
             val host = getServiceURL()
-            val url = if (testRoutePath == "/api/v1/experimental/web") {
-                s"$host$testRoutePath/$namespace/default/$name.text/__ow_meta_body"
-            } else {
-                s"$host$testRoutePath/$namespace/default/$name.text/__ow_body"
-            }
+            val url = s"$host$testRoutePath/$namespace/default/webaction.text/__ow_body"
 
             assetHelper.withCleaner(wsk.action, name) {
                 (action, _) => action.create(name, file, web = Some("true"))
@@ -336,4 +248,71 @@ trait WskWebActionsTests
             response.header("Content-type") shouldBe "application/json"
             response.body.asString.parseJson.asJsObject shouldBe JsObject("status" -> "success".toJson)
     }
+
+    private val subdomainRegex = Seq.fill(WhiskProperties.getPartsInVanitySubdomain)("[a-zA-Z0-9]+").mkString("-")
+
+    private val (vanitySubdomain, vanityNamespace, makeTestSubject) = {
+        if (namespace.matches(subdomainRegex)) {
+            (namespace, namespace, false)
+        } else {
+            val s = Subject().asString.toLowerCase // this will generate two confirming parts
+            (s, s.replace("-", "_"), true)
+        }
+    }
+
+    private val wskPropsForSubdomainTest = if (makeTestSubject) {
+        getAdditionalTestSubject(vanityNamespace) // create new subject for the test
+    } else {
+        WskProps()
+    }
+
+    override def afterAll() = {
+        if (makeTestSubject) {
+            disposeAdditionalTestSubject(vanityNamespace)
+        }
+    }
+
+    "test subdomain" should "have conforming parts" in {
+        vanitySubdomain should fullyMatch regex subdomainRegex.r
+        vanitySubdomain.length should be <= 63
+    }
+
+    "vanity subdomain" should "access a web action via namespace subdomain" in withAssetCleaner(wskPropsForSubdomainTest) {
+        (wp, assetHelper) =>
+            val actionName = "webaction"
+
+            val file = Some(TestUtils.getTestActionFilename("echo.js"))
+            assetHelper.withCleaner(wsk.action, actionName) {
+                (action, _) => action.create(actionName, file, web = Some(true.toString))(wp)
+            }
+
+            val url = getServiceApiHost(vanitySubdomain, true) + s"/default/$actionName.text/a?a=A"
+            println(s"url: $url")
+
+            // try the rest assured path first, failing that, try curl with explicit resolve
+            Try {
+                val response = RestAssured.given().config(sslconfig).get(url)
+                val responseCode = response.statusCode
+                responseCode shouldBe 200
+                response.body.asString shouldBe "A"
+            } match {
+                case Failure(t) =>
+                    println(s"RestAssured path failed, trying curl: $t")
+                    implicit val tid = TransactionId.testing
+                    implicit val logger = new PrintStreamLogging(Console.out)
+                    val host = getServiceApiHost(vanitySubdomain, false)
+                    // if the edge host is a name, try to resolve it, otherwise, it should be an ip address already
+                    val edgehost = WhiskProperties.getEdgeHost
+                    val ip = Try(java.net.InetAddress.getByName(edgehost).getHostAddress) getOrElse "???"
+                    println(s"edge: $edgehost, ip: $ip")
+                    val cmd = Seq("curl", "-k", url, "--resolve", s"$host:$ip")
+                    val (stdout, stderr, exitCode) = SimpleExec.syncRunCmd(cmd)
+                    withClue(s"\n$stderr\n") {
+                        stdout shouldBe "A"
+                        exitCode shouldBe 0
+                    }
+
+                case _ =>
+            }
+    }
 }

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 04/16: Add activation logs strip option. (#2620)

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csantanapr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git

commit 1d97cc6d9ec9a300573cacccbe9107377cc75ec5
Author: David Liu <no...@126.com>
AuthorDate: Sat Sep 16 00:10:47 2017 +0800

    Add activation logs strip option. (#2620)
    
    * Add activation logs strip option.
    
    * Add proper test for strip option.
    
    * Remove dead code.
---
 Godeps/Godeps.json               |  2 +-
 commands/activation.go           |  2 +-
 commands/flags.go                |  1 +
 commands/util.go                 |  7 ++++++-
 wski18n/i18n_resources.go        | 22 +++++++++++-----------
 wski18n/resources/en_US.all.json |  4 ++++
 6 files changed, 24 insertions(+), 14 deletions(-)

diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json
index f8f6eaf..eb1b09c 100644
--- a/Godeps/Godeps.json
+++ b/Godeps/Godeps.json
@@ -65,7 +65,7 @@
 		},
         {
             "ImportPath": "github.com/apache/incubator-openwhisk-client-go/...",
-            "Rev": "b239221db78b0578518daa81d97ab66cad6d08db"
+            "Rev": "d9d11f0b21f8c32b3d78cd632d41a69a818be200"
         }
 	]
 }
diff --git a/commands/activation.go b/commands/activation.go
index 29f8f48..6d5d1d8 100644
--- a/commands/activation.go
+++ b/commands/activation.go
@@ -401,7 +401,7 @@ func init() {
     activationGetCmd.Flags().BoolVarP(&Flags.activation.last, "last", "l", false, wski18n.T("retrieves the last activation"))
 
     activationLogsCmd.Flags().BoolVarP(&Flags.activation.last, "last", "l", false, wski18n.T("retrieves the last activation"))
-
+    activationLogsCmd.Flags().BoolVarP(&Flags.activation.strip, "strip", "r", false, wski18n.T("strip timestamp and stream information"))
     activationResultCmd.Flags().BoolVarP(&Flags.activation.last, "last", "l", false, wski18n.T("retrieves the last activation"))
 
     activationPollCmd.Flags().IntVarP(&Flags.activation.exit, "exit", "e", 0, wski18n.T("stop polling after `SECONDS` seconds"))
diff --git a/commands/flags.go b/commands/flags.go
index 9a3454f..b30d04f 100644
--- a/commands/flags.go
+++ b/commands/flags.go
@@ -94,6 +94,7 @@ type FlagsStruct struct {
         sinceDays       int
         exit            int
         last            bool
+        strip           bool
     }
 
     // rule
diff --git a/commands/util.go b/commands/util.go
index e7ba176..e148470 100644
--- a/commands/util.go
+++ b/commands/util.go
@@ -274,7 +274,12 @@ func printFullActivationList(activations []whisk.Activation) {
 
 func printActivationLogs(logs []string) {
     for _, log := range logs {
-        fmt.Printf("%s\n", log)
+        if (flags.activation.strip){
+            fmt.Printf("%s\n", log[39:])
+        } else {
+            fmt.Printf("%s\n", log)
+        }
+
     }
 }
 
diff --git a/wski18n/i18n_resources.go b/wski18n/i18n_resources.go
index 0d90c6a..000257d 100644
--- a/wski18n/i18n_resources.go
+++ b/wski18n/i18n_resources.go
@@ -109,12 +109,12 @@ func wski18nResourcesDe_deAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/de_DE.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502980774, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/de_DE.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1505508829, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
 
-var _wski18nResourcesEn_usAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x7d\x4f\x73\xdb\x38\xd2\xf7\x7d\x3e\x45\x57\x2e\x76\xde\x92\x9d\xdd\xd3\x5b\x4f\x52\x73\xd0\x24\x9e\x8d\x37\x89\xed\x8a\x9d\xd9\x9d\xda\x6c\x8d\x20\x12\x92\xb0\xa6\x00\x0e\x00\x5a\x51\xb2\xfe\xee\x4f\x01\x20\x29\x52\xc2\x5f\x52\x4e\x9e\x53\x1c\xb1\xfb\xd7\x0d\xa0\x01\x34\x1a\x0d\xe0\x5f\x3f\x01\x7c\xfb\x09\x00\xe0\x19\xc9\x9f\xbd\x84\x67\xd3\xb2\x2c\x48\x86\x24\x61\x14\xf0\x17\x22\x71\x0e\x15\xc5\x5f [...]
+var _wski18nResourcesEn_usAllJson = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xcc\x7d\x4f\x73\xdb\x38\xd2\xf7\x7d\x3e\x45\x57\x2e\x76\xde\x92\x9d\xdd\xd3\x5b\x4f\x52\x73\xd0\x24\x9e\x8d\x37\x89\xed\x8a\x9d\xd9\x9d\xda\x6c\x8d\x20\x12\x92\xb0\xa6\x00\x0e\x00\x5a\x51\xb2\xfe\xee\x4f\x01\x20\x29\x52\xc2\x5f\x52\x4e\x9e\x53\x1c\xb1\xfb\xd7\x0d\xa0\x01\x34\x1a\x0d\xe0\x5f\x3f\x01\x7c\xfb\x09\x00\xe0\x19\xc9\x9f\xbd\x84\x67\xd3\xb2\x2c\x48\x86\x24\x61\x14\xf0\x17\x22\x71\x0e\x15\xc5\x5f [...]
 
 func wski18nResourcesEn_usAllJsonBytes() ([]byte, error) {
     return bindataRead(
@@ -129,7 +129,7 @@ func wski18nResourcesEn_usAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/en_US.all.json", size: 50834, mode: os.FileMode(420), modTime: time.Unix(1502981211, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/en_US.all.json", size: 50955, mode: os.FileMode(420), modTime: time.Unix(1505509004, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -149,7 +149,7 @@ func wski18nResourcesEs_esAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/es_ES.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502980774, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/es_ES.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1505508829, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -169,7 +169,7 @@ func wski18nResourcesFr_frAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/fr_FR.all.json", size: 101, mode: os.FileMode(420), modTime: time.Unix(1502980774, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/fr_FR.all.json", size: 101, mode: os.FileMode(420), modTime: time.Unix(1505508829, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -189,7 +189,7 @@ func wski18nResourcesIt_itAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/it_IT.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502980774, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/it_IT.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1505508829, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -209,7 +209,7 @@ func wski18nResourcesJa_jaAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/ja_JA.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502980774, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/ja_JA.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1505508829, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -229,7 +229,7 @@ func wski18nResourcesKo_krAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/ko_KR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502980774, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/ko_KR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1505508829, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -249,7 +249,7 @@ func wski18nResourcesPt_brAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/pt_BR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502980774, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/pt_BR.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1505508829, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -269,7 +269,7 @@ func wski18nResourcesZh_hansAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/zh_Hans.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502980774, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/zh_Hans.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1505508829, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
@@ -289,7 +289,7 @@ func wski18nResourcesZh_hantAllJson() (*asset, error) {
         return nil, err
     }
 
-    info := bindataFileInfo{name: "wski18n/resources/zh_Hant.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1502980774, 0)}
+    info := bindataFileInfo{name: "wski18n/resources/zh_Hant.all.json", size: 0, mode: os.FileMode(420), modTime: time.Unix(1505508829, 0)}
     a := &asset{bytes: bytes, info: info}
     return a, nil
 }
diff --git a/wski18n/resources/en_US.all.json b/wski18n/resources/en_US.all.json
index 39551d0..5f5bdf8 100644
--- a/wski18n/resources/en_US.all.json
+++ b/wski18n/resources/en_US.all.json
@@ -1064,6 +1064,10 @@
     "translation": "retrieves the last activation"
   },
   {
+    "id": "strip timestamp and stream information",
+    "translation": "strip timestamp and stream information"
+  },
+  {
     "id": "stop polling after `SECONDS` seconds",
     "translation": "stop polling after `SECONDS` seconds"
   },

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 01/16: CLI User Agent Header (#2591)

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csantanapr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git

commit 0eafc9b09cb1b8bcb0311513989dd768fe95aef1
Author: David Cariello <dr...@us.ibm.com>
AuthorDate: Thu Sep 7 22:33:17 2017 -0500

    CLI User Agent Header (#2591)
---
 commands/commands.go | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/commands/commands.go b/commands/commands.go
index 7bd00b0..d15eae5 100644
--- a/commands/commands.go
+++ b/commands/commands.go
@@ -30,6 +30,7 @@ import (
 
 var client *whisk.Client
 const DefaultOpenWhiskApiPath string = "/api"
+var UserAgent string = "OpenWhisk-CLI"
 
 func setupClientConfig(cmd *cobra.Command, args []string) (error){
     baseURL, err := GetURLBase(Properties.APIHost, DefaultOpenWhiskApiPath)
@@ -60,6 +61,7 @@ func setupClientConfig(cmd *cobra.Command, args []string) (error){
         Version:    Properties.APIVersion,
         Insecure:   Flags.Global.Insecure,
         Host:       Properties.APIHost,
+        UserAgent:  UserAgent + "/1.0 (" + Properties.CLIVersion + ")",
     }
 
     // Setup client

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 06/16: Rename CliActivationResponse & CliActivation, and change them from (#2592)

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csantanapr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git

commit f48f7ea45fe76be126a0f3e747af35bb70422872
Author: Vincent <sh...@us.ibm.com>
AuthorDate: Wed Aug 23 10:09:05 2017 -0400

    Rename CliActivationResponse & CliActivation, and change them from (#2592)
    
    This PR renames the class CliActivation and CliActivationResponse
    and makes them available to be accessed from another package, because
    REST call can use both of the classes as well.
    
    Partially-closes-bug: #2430
---
 tests/src/test/scala/system/basic/WskActionTests.scala   | 5 +++--
 tests/src/test/scala/system/basic/WskBasicTests.scala    | 3 ++-
 tests/src/test/scala/system/basic/WskSequenceTests.scala | 5 +++--
 3 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/tests/src/test/scala/system/basic/WskActionTests.scala b/tests/src/test/scala/system/basic/WskActionTests.scala
index 390b342..06778a3 100644
--- a/tests/src/test/scala/system/basic/WskActionTests.scala
+++ b/tests/src/test/scala/system/basic/WskActionTests.scala
@@ -20,6 +20,7 @@ package system.basic
 import org.junit.runner.RunWith
 import org.scalatest.junit.JUnitRunner
 
+import common.ActivationResult
 import common.JsHelpers
 import common.TestHelpers
 import common.TestCLIUtils
@@ -290,7 +291,7 @@ class WskActionTests
             }
 
             val run = wsk.action.invoke(name, Map("payload" -> testString.toJson), blocking = true)
-            val activation = wsk.parseJsonString(run.stdout).convertTo[CliActivation]
+            val activation = wsk.parseJsonString(run.stdout).convertTo[ActivationResult]
 
             withClue(s"check failed for activation: $activation") {
                 val wordCount = testString.split(" ").length
@@ -306,7 +307,7 @@ class WskActionTests
             }
 
             val run = wsk.action.invoke(name, Map("payload" -> testString.toJson), blocking = true)
-            val activation = wsk.parseJsonString(run.stdout).convertTo[CliActivation]
+            val activation = wsk.parseJsonString(run.stdout).convertTo[ActivationResult]
 
             withClue(s"check failed for activation: $activation") {
                 activation.response.status shouldBe "success"
diff --git a/tests/src/test/scala/system/basic/WskBasicTests.scala b/tests/src/test/scala/system/basic/WskBasicTests.scala
index 7dba348..d83cf6f 100644
--- a/tests/src/test/scala/system/basic/WskBasicTests.scala
+++ b/tests/src/test/scala/system/basic/WskBasicTests.scala
@@ -25,6 +25,7 @@ import scala.language.postfixOps
 import org.junit.runner.RunWith
 import org.scalatest.junit.JUnitRunner
 
+import common.ActivationResult
 import common.TestHelpers
 import common.TestCLIUtils
 import common.TestUtils._
@@ -370,7 +371,7 @@ class WskBasicTests
             }
 
             val stderr = wsk.action.invoke(name, blocking = true, expectedExitCode = 246).stderr
-            CliActivation.serdes.read(removeCLIHeader(stderr).parseJson).response.result shouldBe Some {
+            ActivationResult.serdes.read(removeCLIHeader(stderr).parseJson).response.result shouldBe Some {
                 JsObject("error" -> JsObject("msg" -> "failed activation on purpose".toJson))
             }
     }
diff --git a/tests/src/test/scala/system/basic/WskSequenceTests.scala b/tests/src/test/scala/system/basic/WskSequenceTests.scala
index 688c5c6..3a1dbe3 100644
--- a/tests/src/test/scala/system/basic/WskSequenceTests.scala
+++ b/tests/src/test/scala/system/basic/WskSequenceTests.scala
@@ -27,6 +27,7 @@ import scala.util.matching.Regex
 import org.junit.runner.RunWith
 import org.scalatest.junit.JUnitRunner
 
+import common.ActivationResult
 import common.StreamLogging
 import common.TestHelpers
 import common.TestCLIUtils
@@ -475,7 +476,7 @@ class WskSequenceTests
      * checks duration
      * checks memory
      */
-    private def checkSequenceLogsAndAnnotations(activation: CliActivation, size: Int) = {
+    private def checkSequenceLogsAndAnnotations(activation: ActivationResult, size: Int) = {
         activation.logs shouldBe defined
         // check that the logs are what they are supposed to be (activation ids)
         // check that the cause field is properly set for these activations
@@ -520,7 +521,7 @@ class WskSequenceTests
         }
     }
 
-    private def extractMemoryAnnotation(activation: CliActivation): Long = {
+    private def extractMemoryAnnotation(activation: ActivationResult): Long = {
         val limits = activation.getAnnotationValue("limits")
         limits shouldBe defined
         limits.get.asJsObject.getFields("memory")(0).convertTo[Long]

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 10/16: Restore throttle check before each CLI call. (#2702)

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csantanapr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git

commit 613e6312232b7a3089a5e8f81074ff291648dfcb
Author: rodric rabbah <ro...@gmail.com>
AuthorDate: Wed Sep 6 00:12:48 2017 -0400

    Restore throttle check before each CLI call. (#2702)
---
 tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala b/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
index 77943c5..ac0f01c 100644
--- a/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala
@@ -75,7 +75,7 @@ class ApiGwTests
         val invocationCount = invocationsLast60Seconds.length
         println(s"Action invokes within last minute: ${invocationCount}")
 
-        if (invocationCount + expectedActivationsPerTest >= maxInvocationsBeforeThrottle) {
+        if (invocationCount >= maxInvocationsBeforeThrottle) {
             // Instead of waiting a fixed 60 seconds to settle the throttle,
             // calculate a wait time that will clear out about half of the
             // current invocations (assuming even distribution) from the
@@ -97,7 +97,7 @@ class ApiGwTests
     }
 
     override def beforeEach() = {
-        checkThrottle()
+        //checkThrottle()
     }
 
     /*
@@ -129,6 +129,8 @@ class ApiGwTests
         responsetype: Option[String] = None,
         expectedExitCode: Int = SUCCESS_EXIT,
         cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath()))(implicit wskpropsOverride: WskProps): RunResult = {
+
+        checkThrottle()
         wsk.api.create(basepath, relpath, operation, action, apiname, swagger, responsetype, expectedExitCode, cliCfgFile)(wskpropsOverride)
     }
 
@@ -142,6 +144,8 @@ class ApiGwTests
         nameSort: Option[Boolean] = None,
         expectedExitCode: Int = SUCCESS_EXIT,
         cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath())): RunResult = {
+
+        checkThrottle()
         wsk.api.list(basepathOrApiName, relpath, operation, limit, since, full, nameSort, expectedExitCode, cliCfgFile)
     }
 
@@ -151,6 +155,8 @@ class ApiGwTests
         expectedExitCode: Int = SUCCESS_EXIT,
         cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath()),
         format: Option[String] = None): RunResult = {
+
+        checkThrottle()
         wsk.api.get(basepathOrApiName, full, expectedExitCode, cliCfgFile, format)
     }
 
@@ -160,6 +166,8 @@ class ApiGwTests
         operation: Option[String] = None,
         expectedExitCode: Int = SUCCESS_EXIT,
         cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath())): RunResult = {
+
+        checkThrottle()
         wsk.api.delete(basepathOrApiName, relpath, operation, expectedExitCode, cliCfgFile)
     }
 

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.

[incubator-openwhisk-cli] 14/16: Test change for api host setting which previously caused CLI to crash.

Posted by cs...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

csantanapr pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git

commit a8e3016ad1edb3d44652d99c4e11d5cec9937de7
Author: Rodric Rabbah <ra...@us.ibm.com>
AuthorDate: Thu Sep 7 23:20:58 2017 -0400

    Test change for api host setting which previously caused CLI to crash.
---
 .../scala/whisk/core/cli/test/WskConfigTests.scala  | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/tests/src/test/scala/whisk/core/cli/test/WskConfigTests.scala b/tests/src/test/scala/whisk/core/cli/test/WskConfigTests.scala
index 90b014d..8e34aea 100644
--- a/tests/src/test/scala/whisk/core/cli/test/WskConfigTests.scala
+++ b/tests/src/test/scala/whisk/core/cli/test/WskConfigTests.scala
@@ -259,6 +259,27 @@ class WskConfigTests extends TestHelpers with WskTestHelpers {
     }
   }
 
+  it should "set api host with or without http prefix" in {
+    val tmpwskprops = File.createTempFile("wskprops", ".tmp")
+    try {
+      val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())
+      Seq("", "http://", "https://").foreach { prefix =>
+        Seq("10", "10:123", "aaa", "aaa:123").foreach { host =>
+          val apihost = s"$prefix$host"
+          withClue(apihost) {
+            val rr = wsk.cli(Seq("property", "set", "--apihost", apihost), env = env)
+            rr.stdout.trim shouldBe s"ok: whisk API host set to $apihost"
+            rr.stderr shouldBe 'empty
+            val fileContent = FileUtils.readFileToString(tmpwskprops)
+            fileContent should include(s"APIHOST=$apihost")
+          }
+        }
+      }
+    } finally {
+      tmpwskprops.delete()
+    }
+  }
+
   it should "set auth in property file" in {
     val tmpwskprops = File.createTempFile("wskprops", ".tmp")
     val env = Map("WSK_CONFIG_FILE" -> tmpwskprops.getAbsolutePath())

-- 
To stop receiving notification emails like this one, please contact
"commits@openwhisk.apache.org" <co...@openwhisk.apache.org>.