Esempio n. 1
0
        public async Task WorkflowCanContainMinimalReadmeInfo()
        {
            var stubRequests = Yaml <StubHttpClientHandlerFactory>(@"
Responses:
    https://localhost/minimal/workflow.yaml: 
        GET:
            status: 200
            body: |
                operations:
                - message: Just a workflow file
    https://localhost/minimal/readme.md: 
        GET:
            status: 200
            body: |
                ``` yaml
                info:
                  title: minimal
                ```
");

            InitializeServices(stubRequests);

            Services.App.Execute("deploy", "https://localhost/minimal/workflow.yaml");

            Console.AssertContainsInOrder("Just a workflow file");
        }
        public async Task OutputFlowsBackMultipleLevelsWhenNotInterrupted()
        {
            var stubs = Yaml <StubBlueprintManager>(@"
Blueprints:
 the-test:
  Files:
   workflow.yaml: |
    operations:
    - message: (['data is ', @])
    - message: has nested operations
      operations:
      - message: (['data is ', @])
      - message: returning 42
        output: {x: 42}
      - message: (['data is ', @])
    - message: (['data is ', @])
");

            InitializeServices(stubs);

            var result = Services.App.Execute("deploy", "the-test");

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder("returning 42", "x: 42");
        }
Esempio n. 3
0
        public async Task OnlyWorkflowOperationValuesPassThrough()
        {
            var stubs = Yaml <StubHttpClientHandlerFactory>(@"
Files:
  https://localhost/the-test/workflow.yaml: |
    operations:
    - workflow: ../step1
      values: { x: ( xValue ) }
  https://localhost/step1/workflow.yaml: |
    operations:
    - message: (['x=<', x, '>'])
    - message: (['y=<', y, '>'])
    - message: (['xValue=<', xValue, '>'])
    - message: (['yValue=<', yValue, '>'])
");

            InitializeServices(stubs);

            var result = Services.App.Execute(
                "deploy",
                "https://localhost/the-test",
                "--set",
                "xValue=alpha",
                "--set",
                "yValue=beta",
                "--set",
                "x=gamma",
                "--set",
                "y=delta");

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder("x=<alpha>", "y=<>", "xValue=<>", "yValue=<>");
        }
Esempio n. 4
0
        public async Task WorkflowOutputWorksSameAsOperationOutput()
        {
            var stubs = Yaml <StubHttpClientHandlerFactory>(@"
Files:
  https://localhost/the-test/workflow.yaml: |
    operations:
    - workflow: ../step1
      output: { xOut: ( result.x ) }
    - message: ([ 'everything is ', to_string(@) ])
  https://localhost/step1/workflow.yaml: |
    operations:
    - output:
        xOperation: alpha
        yOperation: beta
    output:
      x: ( xOperation )
");

            InitializeServices(stubs);

            var result = Services.App.Execute("deploy", "https://localhost/the-test");

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder(@"everything is {""xOut"":""alpha""}");
        }
Esempio n. 5
0
        public async Task FileSystemRelativeReferenceImportsFiles()
        {
            var stubs = Yaml <StubFileSystem>(@"
Files:
  the-test/readme.md: |
    ``` yaml
    info:
        title: TheTest
    workflows:
      local:
        inputs:
        - step1
    ```
  the-test/workflow.yaml: |
    operations:
    - message: Before
    - workflow: workflows/step1
    - message: After
  step1/workflow.yaml: |
    operations:
    - message: During
");

            InitializeServices(stubs);

            var result = Services.App.Execute("deploy", "the-test");

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder("Before", "During", "After");
        }
Esempio n. 6
0
        public void SeveralArraysCanBeIterated()
        {
            var stubBlueprints = Yaml <StubBlueprintManager>(@"
                Blueprints:
                  the-test:
                    Files:
                      workflow.yaml: |
                        operations:
                        - foreach:
                            values:
                              x: ['a', 'b', 'c']
                              y: 
                                z: ['d', 'e', 'f']
                          message: (['x is ', x, ' y.z is ', y.z])
            ");

            InitializeServices(stubBlueprints);

            var result = Services.App.Execute("deploy", "the-test");

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder(
                "x is a",
                "y.z is d",
                "x is b",
                "y.z is e",
                "x is c",
                "y.z is f");
        }
Esempio n. 7
0
        public void WorkflowCanRunEntirelyFromStubHttpResponses()
        {
            var stubHttpClients = Yaml <StubHttpClientHandlerFactory>(@"
Responses:
  https://example.net/the-test/readme.md:
    GET:
      status: 200
      body: |
        ``` yaml
        info:
            title: TheTest
        ```
  https://example.net/the-test/workflow.yaml:
    GET:
      status: 200
      body:
        operations:
        - message: This is a test
          output: { x: green }
            ");

            InitializeServices(stubHttpClients);

            var result = Services.App.Execute("deploy", "https://example.net/the-test");

            System.Console.Error.WriteLine(Console.ErrorStringWriter.ToString());
            System.Console.Out.WriteLine(Console.OutStringWriter.ToString());

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder("This is a test", "x: green");
        }
Esempio n. 8
0
        public void NotCaughtIfConditionIsFalse()
        {
            var stubBlueprints = Yaml <StubBlueprintManager>(@"
                Blueprints:
                  the-test:
                    Files:
                      workflow.yaml: |
                        operations:
                        - message: Catching operation
                          operations:
                          - message: Throwing operation
                            throw: { message: different }
                          catch:
                            condition: Message == 'boom'
                        - message: Still Running
            ");

            InitializeServices(stubBlueprints);

            var ex = Assert.ThrowsException <OperationException>(() => Services.App.Execute("deploy", "the-test"));

            Assert.AreEqual("different", ex.Message);

            Console.AssertContainsInOrder("Catching operation", "Throwing operation", "different");
        }
Esempio n. 9
0
        public void CatchesIfConditionIsTrue()
        {
            var stubBlueprints = Yaml <StubBlueprintManager>(@"
                Blueprints:
                  the-test:
                    Files:
                      workflow.yaml: |
                        operations:
                        - message: Catching operation
                          operations:
                          - message: Throwing operation
                            throw: { message: boom }
                          catch:
                            condition: error.message == 'boom'
                        - message: Still Running
            ");

            InitializeServices(stubBlueprints);

            var result = Services.App.Execute("deploy", "the-test");

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder("Catching operation", "Throwing operation", "Still Running");
        }
Esempio n. 10
0
        public void ResponseBodyMayBeQueried()
        {
            var stubBlueprints = Yaml <StubBlueprintManager>(@"
                Blueprints:
                  the-test:
                    Files:
                      workflow.yaml: |
                        operations:
                        - request: request.yaml
                          output:
                            x: (result.body.color)
                            y: (result.body.id)
                      request.yaml: |
                        method: GET
                        url: https://localhost/
            ");

            var stubHttpClients = Yaml <StubHttpClientHandlerFactory>(@"
                Responses:
                  https://localhost/:
                    GET:
                      status: 200
                      body:
                        id: 4
                        color: green
            ");

            InitializeServices(stubBlueprints, stubHttpClients);

            var result = Services.App.Execute("deploy", "the-test");

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder("x: green", "y:", "4");
        }
Esempio n. 11
0
        public async Task SimpleGetOperationBeingExecuted()
        {
            var stubHttpClients = Yaml <StubHttpClientHandlerFactory>($@"
Responses:
  https://example.net/the-test/readme.md:
    GET:
      status: 200
      body: |
        ``` yaml
        info:
          title: TheTest
        swagger:
          foo:
            target: apis/path
            source: https://example.org/specs/
            inputs:
            - testing/swagger.json
        ```
  https://example.net/the-test/workflow.yaml:
    GET:
      status: 200
      body:
        operations:
        - request: apis/path/TestingClient/Me_Get.yaml
          output: ( result )
  https://example.org/specs/testing/swagger.json:
    GET:
      status: 200
      body:
        swagger: 2.0
        info:
          title: TestingClient
        host: example.com
        paths:
          /me:
            get:
              operationId: Me_Get
  https://example.com/me:
    GET:
      status: 200
      body:
        name: one
        id: 42
            ");

            InitializeServices(stubHttpClients);

            var result = Services.App.Execute("deploy", "https://example.net/the-test");

            System.Console.Error.WriteLine(Console.ErrorStringWriter.ToString());
            System.Console.Out.WriteLine(Console.OutStringWriter.ToString());

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder("name: one", "id: 42");
        }
Esempio n. 12
0
        public void ExceptionAndResultDetailsCanBeSavedInCatch()
        {
            var stubBlueprints = Yaml <StubBlueprintManager>(@"
                Blueprints:
                  the-test:
                    Files:
                      workflow.yaml: |
                        operations:
                        - message: Catching 400
                          request: badrequest.yaml
                          catch:
                            output:
                              the-result: (result)
                              the-error: (error)
                        - message: Still Running
                      badrequest.yaml: |
                        method: GET
                        url: https://localhost/badrequest
            ");

            var stubHttpClients = Yaml <StubHttpClientHandlerFactory>(@"
                Responses:
                  https://localhost/badrequest:
                    GET:
                      status: 400
                      headers: { Content-Type: ['application/json'] }
                      body: 
                        oops:
                          code: 1234
                          summary: This is a bad request
            ");

            InitializeServices(stubBlueprints, stubHttpClients);

            var result = Services.App.Execute("deploy", "the-test");

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder(
                "Catching 400",
                "Still Running",
                "the-result:",
                "status: 400",
                "body:",
                "oops:",
                "code:",
                "1234",
                "summary: This is a bad request",
                "the-error:",
                "message:",
                "400");
        }
Esempio n. 13
0
        public async Task WebServerTransitiveRelativeReferenceImportsFiles()
        {
            var stubs = Yaml <StubHttpClientHandlerFactory>(@"
Files:
  https://localhost/the-test/readme.md: |
    ``` yaml
    info:
        title: TheTest
    workflows:
      local:
        inputs:
        - step1
    ```
  https://localhost/the-test/workflow.yaml: |
    operations:
    - message: BeginTheTest
    - workflow: workflows/step1
    - message: EndTheTest
  https://localhost/step1/readme.md: |
    ``` yaml
    info:
        title: Step1
    workflows:
      local:
        inputs:
        - step2
    ```
  https://localhost/step1/workflow.yaml: |
    operations:
    - message: BeginStep1
    - workflow: workflows/step2
    - message: EndStep1
  https://localhost/step2/readme.md: |
    ``` yaml
    info:
        title: Step2
    ```
  https://localhost/step2/workflow.yaml: |
    operations:
    - message: DuringStep2
");

            InitializeServices(stubs);

            var result = Services.App.Execute("deploy", "https://localhost/the-test");

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder("BeginTheTest", "BeginStep1", "DuringStep2", "EndStep1", "EndTheTest");
        }
Esempio n. 14
0
        public void CatchByStatusCode()
        {
            var stubBlueprints = Yaml <StubBlueprintManager>(@"
                Blueprints:
                  the-test:
                    Files:
                      workflow.yaml: |
                        operations:
                        - message: Catching 404
                          request: notfound.yaml
                          catch:
                            condition: result.status == `404`
                        - message: Not Catching 503
                          request: servererror.yaml
                          catch:
                            condition: result.status == `404`
                        - message: Still Running
                      notfound.yaml: |
                        method: GET
                        url: https://localhost/notfound
                      servererror.yaml: |
                        method: GET
                        url: https://localhost/servererror
            ");

            var stubHttpClients = Yaml <StubHttpClientHandlerFactory>(@"
                Responses:
                  https://localhost/notfound:
                    GET:
                      status: 404
                      body: Page error
                  https://localhost/servererror:
                    GET:
                      status: 503
                      body: Page error
            ");

            InitializeServices(stubBlueprints, stubHttpClients);

            var ex = Assert.ThrowsException <RequestException>(() => Services.App.Execute("deploy", "the-test"));

            Assert.IsTrue(ex.Message.Contains("503"));

            Assert.AreEqual(503, ex.Response.status);

            Console.AssertContainsInOrder("Catching 404", "Not Catching 503");

            Console.AssertNotContains("Still Running");
        }
Esempio n. 15
0
        public async Task WorkflowCanRunWithOnlyHttpsWorkflowYamlFile()
        {
            var stubRequests = Yaml <StubHttpClientHandlerFactory>(@"
Responses:
    https://localhost/just/workflow.yaml: 
        GET:
            status: 200
            body: |
                operations:
                - message: Just a workflow file
");

            InitializeServices(stubRequests);

            Services.App.Execute("deploy", "https://localhost/just/workflow.yaml");

            Console.AssertContainsInOrder("Just a workflow file");
        }
Esempio n. 16
0
        public void ForeachHashObject()
        {
            var stubBlueprints = Yaml <StubBlueprintManager>(@"
                Blueprints:
                  the-test:
                    Files:
                      values.yaml: |
                          hash:
                            a: b
                            c: d
                            e: f
                      workflow.yaml: |
                        operations:
                        - foreach:
                            values: ( map(&{ key:[0], value:[1] }, items(hash)) )
                          message: ""(['1: ', key, ' is ', value])""
                        - foreach:
                            values:
                              key: ( keys(hash) )
                              value: ( values(hash) )
                          message: ""(['2: ', key, ' is ', value])""
                        - foreach:
                            values:
                              kv: ( items(hash) )
                          message: ""(['3: ', kv[0], ' is ', kv[1]])""
            ");

            InitializeServices(stubBlueprints);

            var result = Services.App.Execute("deploy", "the-test");

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder(
                "1: a is b",
                "1: c is d",
                "1: e is f",
                "2: a is b",
                "2: c is d",
                "2: e is f",
                "3: a is b",
                "3: c is d",
                "3: e is f");
        }
Esempio n. 17
0
        public void HttpResponseSecretsAreHidden()
        {
            var stubBlueprints = Yaml <StubBlueprintManager>(@"
                Blueprints:
                  hide-secrets:
                    Files:
                      workflow.yaml: |
                        operations:
                        - message: Fetching secrets
                          request: request.yaml
                          output:
                            things:
                              one: (keys[0].value)
                              two: (keys[1].value)
                      request.yaml: |
                        method: GET
                        url: https://localhost/
                        secret: keys[*].value
            ");

            var stubHttpClients = Yaml <StubHttpClientHandlerFactory>(@"
                Responses:
                  https://localhost/:
                    GET:
                      status: 200
                      body:
                        keys:
                        - name: key-1
                          value: alpha
                        - name: key-2
                          value: beta
            ");

            InitializeServices(stubBlueprints, stubHttpClients);

            var result = Services.App.Execute("deploy", "hide-secrets");

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder("Fetching secrets", "one: xxxxxxxx", "two: xxxxxxxx");
        }
Esempio n. 18
0
        public void ResponseHeadersMayBeSecret()
        {
            var stubBlueprints = Yaml <StubBlueprintManager>(@"
                Blueprints:
                  hide-secrets:
                    Files:
                      workflow.yaml: |
                        operations:
                        - message: Fetching secrets
                          request: request.yaml
                          output:
                            things:
                              one: (result.headers.""Set-Cookie""[0])
                              two: (result.headers.""Set-Cookie""[1])
                      request.yaml: |
                        method: GET
                        url: https://localhost/
                        secret: result.headers.""Set-Cookie""
            ");

            var stubHttpClients = Yaml <StubHttpClientHandlerFactory>(@"
                Responses:
                  https://localhost/:
                    GET:
                      status: 200
                      headers:
                        Set-Cookie:
                        - secret-cookie-one
                        - secret-cookie-two
                      body: doesn't matter
            ");

            InitializeServices(stubBlueprints, stubHttpClients);

            var result = Services.App.Execute("deploy", "hide-secrets");

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder("Fetching secrets", "one: xxxxxxxx", "two: xxxxxxxx");
        }
Esempio n. 19
0
        public void ForeachValuesAreIterated()
        {
            var stubBlueprints = Yaml <StubBlueprintManager>(@"
                Blueprints:
                  the-test:
                    Files:
                      workflow.yaml: |
                        operations:
                        - foreach:
                            values:
                              x: ['a', 'b', 'c']
                          message: (['x is ', x])
            ");

            InitializeServices(stubBlueprints);

            var result = Services.App.Execute("deploy", "the-test");

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder("x is a", "x is b", "x is c");
        }
Esempio n. 20
0
        public async Task FileSystemSubWorkflowCanBeCalled()
        {
            var stubs = Yaml <StubFileSystem>(@"
  Files:
   the-test/workflow.yaml: |
    operations:
    - message: Before
    - workflow: lib/step1
    - message: After
   the-test/lib/step1/workflow.yaml: |
    operations:
    - message: During
");

            InitializeServices(stubs);

            var result = Services.App.Execute("deploy", "the-test");

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder("Before", "During", "After");
        }
Esempio n. 21
0
        public async Task WebServerSubWorkflowCanBeCalled()
        {
            var stubRequests = Yaml <StubHttpClientHandlerFactory>(@"
Files:
  https://localhost/the-test/workflow.yaml: |
    operations:
    - message: Before
    - workflow: lib/step1
    - message: After
  https://localhost/the-test/lib/step1/workflow.yaml: |
    operations:
    - message: During
");

            InitializeServices(stubRequests, new StubFileSystem());

            var result = Services.App.Execute("deploy", "https://localhost/the-test/workflow.yaml");

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder("Before", "During", "After");
        }
Esempio n. 22
0
        public void ThrowDetailsCanBeSavedInCatch()
        {
            var stubBlueprints = Yaml <StubBlueprintManager>(@"
                Blueprints:
                  the-test:
                    Files:
                      workflow.yaml: |
                        operations:
                        - message: Catching Exception
                          operations:
                          - message: Throwing Exception
                            throw:
                              message: one
                              details:
                                x: two
                                y: three
                          catch:
                            output:
                              the-details: (error.details)
                              the-message: (error.message)
                        - message: Still Running
            ");

            InitializeServices(stubBlueprints);

            var result = Services.App.Execute("deploy", "the-test");

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder(
                "Catching Exception",
                "Throwing Exception",
                "Still Running",
                "the-details:",
                "x: two",
                "y: three",
                "the-message: one");
        }
Esempio n. 23
0
        public void StatusAndHeadersAreAvailable()
        {
            var stubBlueprints = Yaml <StubBlueprintManager>(@"
                Blueprints:
                  the-test:
                    Files:
                      workflow.yaml: |
                        operations:
                        - request: request.yaml
                          output:
                            x: (result.status)
                            y: (result.headers.""Content-Type""[0])
                            z: (result.headers.""Content-Length""[0])
                      request.yaml: |
                        method: GET
                        url: https://localhost/
            ");

            var stubHttpClients = Yaml <StubHttpClientHandlerFactory>(@"
                Responses:
                  https://localhost/:
                    GET:
                      status: 200
                      headers:
                        Content-Type: [text/plain]
                        Content-Length: [12]
                      body: Hello world!
            ");

            InitializeServices(stubBlueprints, stubHttpClients);

            var result = Services.App.Execute("deploy", "the-test");

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder("x:", "200", "y:", "text/plain", "z:", "12");
        }
Esempio n. 24
0
        public void ResponseMayBeMergedWithWorkingMemory()
        {
            var stubBlueprints = Yaml <StubBlueprintManager>(@"
                Blueprints:
                  the-test:
                    Files:
                      workflow.yaml: |
                        operations:
                        - output:
                            b: [three,four]
                        - values:
                            a: [one,two]
                          request: request.yaml
                          output:
                            d: ([a,b,result.body,c][])
                      request.yaml: |
                        method: GET
                        url: https://localhost/
            ");

            var stubHttpClients = Yaml <StubHttpClientHandlerFactory>(@"
                Responses:
                  https://localhost/:
                    GET:
                      status: 200
                      body:
                        c: [five,six]
            ");

            InitializeServices(stubBlueprints, stubHttpClients);

            var result = Services.App.Execute("deploy", "the-test");

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder("d:", "one", "two", "three", "four", "five", "six");
        }
Esempio n. 25
0
        public void ForeachOutputIsConcatinated()
        {
            var stubBlueprints = Yaml <StubBlueprintManager>(@"
                Blueprints:
                  the-test:
                    Files:
                      workflow.yaml: |
                        operations:
                        - foreach:
                            values:
                              x: ['a', 'b', 'c']
                            output:
                              y: ([x])
                        - message: (join('+', y))
            ");

            InitializeServices(stubBlueprints);

            var result = Services.App.Execute("deploy", "the-test");

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder("a+b+c");
        }
Esempio n. 26
0
        public async Task ApiVersionComesFromInfoVersionByDefault()
        {
            var stubHttpClients = Yaml <StubHttpClientHandlerFactory>($@"
Responses:
  https://example.net/the-test/readme.md:
    GET:
      status: 200
      body: |
        ``` yaml
        info:
          title: TheTest
        swagger:
          foo:
            target: apis/path
            source: https://example.org/specs/
            inputs:
            - testing/swagger.json
        ```
  https://example.net/the-test/workflow.yaml:
    GET:
      status: 200
      body:
        operations:
        - request: apis/path/TestingClient/MethodOne.yaml
          output:
            one: ( result )
        - request: apis/path/TestingClient/MethodTwo.yaml
          output:
            two: ( result )
  https://example.org/specs/testing/swagger.json:
    GET:
      status: 200
      body:
        swagger: 2.0
        info:
          title: TestingClient
          version: 5.0-preview.2
        host: example.com
        paths:
          /method/one:
            get:
              operationId: MethodOne
              parameters:
              - name: api-version
                in: query
                required: true
          /v{{api-version}}/method/two:
            get:
              operationId: MethodTwo
              parameters:
              - name: api-version
                in: path
                required: true
  https://example.com/method/one?api-version=5.0-preview.2:
    GET:
      status: 200
      body:
      - request has arrived
  https://example.com/v5.0-preview.2/method/two:
    GET:
      status: 200
      body:
      - request has arrived
            ");

            InitializeServices(stubHttpClients);

            var result = Services.App.Execute("deploy", "https://example.net/the-test");

            System.Console.Error.WriteLine(Console.ErrorStringWriter.ToString());
            System.Console.Out.WriteLine(Console.OutStringWriter.ToString());

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder("request has arrived", "request has arrived");
        }
Esempio n. 27
0
        public async Task ParametersAppearInPathQueryAndBody()
        {
            var stubHttpClients = Yaml <StubHttpClientHandlerFactory>($@"
Responses:
  https://example.net/the-test/readme.md:
    GET:
      status: 200
      body: |
        ``` yaml
        info:
          title: TheTest
        swagger:
          foo:
            target: apis/path
            source: https://example.org/specs/
            inputs:
            - testing/swagger.json
        ```
  https://example.net/the-test/workflow.yaml:
    GET:
      status: 200
      body:
        operations:
        - request: apis/path/TestingClient/CreateSomething.yaml
          values:
            request:
              parameters:
                one: uno
                two: dos
              body:
                four: quatro
                five: 5
          output: ( result )
  https://example.org/specs/testing/swagger.json:
    GET:
      status: 200
      body:
        swagger: 2.0
        info:
          title: TestingClient
        host: example.com
        paths:
          /somethings/{{one}}:
            put:
              operationId: CreateSomething
              parameters:
              - name: one
                in: path
              - name: two
                in: query
              - name: three
                in: body
                schema:
                  type: object
                  properties:
                    four:
                      type: string
                    five:
                      type: integer
  https://example.com/somethings/uno?two=dos:
    PUT:
      status: 200
      body:
      - request has arrived
            ");

            InitializeServices(stubHttpClients);

            var result = Services.App.Execute("deploy", "https://example.net/the-test");

            System.Console.Error.WriteLine(Console.ErrorStringWriter.ToString());
            System.Console.Out.WriteLine(Console.OutStringWriter.ToString());

            Assert.AreEqual(0, result);

            Console.AssertContainsInOrder("request has arrived");

            var put  = stubHttpClients.AssertRequest("PUT", "https://example.com/somethings/uno?two=dos");
            var body = await put.Content.ReadAsStringAsync();

            Assert.IsTrue(body.Contains("\"four\": \"quatro\""), "Unable to find expected text in " + body);
            Assert.IsTrue(body.Contains("\"five\": 5"), "Unable to find expected text in " + body);
        }