[
  {
    "comment": "create a user account",
    "request": {
      "uri": "users",
      "method": "put",
      "entity": {
        "name": "test_user_recurring@example.com",
        "password": "password1!",
        "agreeToTerms": true
      }
    }
  },

  {
    "before": "sleep 22s",  // wait for account objects to be created
    "comment": "login as new user",
    "request": {
      "session": "new",
      "uri": "auth/login",
      "entity": {
        "name": "test_user_recurring@example.com",
        "password": "password1!"
      }
    },
    "response": {
      "store": "testAccount",
      "sessionName": "userSession",
      "session": "token"
    }
  },

  {
    "comment": "get payment methods, tokenize a credit card",
    "request": { "uri": "paymentMethods" },
    "response": {
      "store": "paymentMethods"
    },
    "after": "stripe_tokenize_card"
  },

  {
    "before": "sleep 1s",
    "comment": "as root, check email inbox for welcome message",
    "request": {
      "session": "rootSession",
      "uri": "debug/inbox/email/test_user_recurring@example.com?type=notice&action=welcome&target=account"
    },
    "response": {
      "store": "emailInbox",
      "check": [
        {"condition": "'{{json.[0].ctx.message.messageType}}' == 'notice'"},
        {"condition": "'{{json.[0].ctx.message.action}}' == 'welcome'"},
        {"condition": "'{{json.[0].ctx.message.target}}' == 'account'"}
      ]
    }
  },

  {
    "comment": "approve email verification request",
    "request": {
      "session": "userSession",
      "uri": "auth/approve/{{emailInbox.[0].ctx.confirmationToken}}",
      "method": "post"
    }
  },

  {
    "comment": "get plans",
    "request": { "uri": "plans" },
    "response": {
      "store": "plans",
      "check": [{"condition": "json.length >= 1"}]
    }
  },

  {
    "comment": "add plan, using 'credit' payment method with a valid card token, creates a stripe customer",
    "request": {
      "uri": "me/plans",
      "method": "put",
      "entity": {
        "name": "test-net-{{rand 5}}",
        "domain": "{{defaultDomain}}",
        "locale": "en_US",
        "timezone": "EST",
        "plan": "{{plans.[0].name}}",
        "footprint": "US",
        "paymentMethodObject": {
          "paymentMethodType": "credit",
          "paymentInfo": "{{stripeToken}}"
        }
      }
    },
    "response": {
      "store": "accountPlan"
    }
  },

  {
    "before": "sleep 15s",
    "comment": "verify account payment methods, should be one",
    "request": { "uri": "me/paymentMethods" },
    "response": {
      "check": [
        {"condition": "json.length === 1"},
        {"condition": "json[0].getPaymentMethodType().name() === 'credit'"}
      ]
    }
  },

  {
    "comment": "verify account plans, should be one",
    "request": { "uri": "me/plans" },
    "response": {
      "check": [
        {"condition": "json.length === 1"},
        {"condition": "json[0].getName() === accountPlan.getName()"},
        {"condition": "json[0].enabled()"}
      ]
    }
  },

  {
    "comment": "verify account plan payment info",
    "request": { "uri": "me/plans/{{accountPlan.uuid}}/paymentMethod" },
    "response": {
      "store": "savedPaymentMethod",
      "check": [
        {"condition": "json.getPaymentMethodType().name() === 'credit'"},
        {"condition": "json.getMaskedPaymentInfo() === 'XXXX-XXXX-XXXX-4242'"}
      ]
    }
  },

  {
    "comment": "verify bill exists for new service with correct price and has been paid",
    "request": { "uri": "me/bills" },
    "response": {
      "store": "bills",
      "check": [
        {"condition": "json.length === 1"},
        {"condition": "json[0].getAccountPlan() === '{{accountPlan.uuid}}'"},
        {"condition": "json[0].getTotal() === {{plans.[0].price}}"},
        {"condition": "json[0].getStatus().name() === 'paid'"}
      ]
    }
  },

  {
    "comment": "verify successful payment exists for new service",
    "request": { "uri": "me/payments" },
    "response": {
      "store": "payments",
      "check": [
        {"condition": "json.length === 1"},
        {"condition": "json[0].getAccountPlan() === '{{accountPlan.uuid}}'"},
        {"condition": "json[0].getAmount() === {{plans.[0].price}}"},
        {"condition": "json[0].getType().name() === 'payment'"},
        {"condition": "json[0].getStatus().name() === 'success'"}
      ]
    }
  },

  {
    "comment": "verify successful payment has paid for the bill above",
    "request": { "uri": "me/plans/{{accountPlan.uuid}}/bills" },
    "response": {
      "check": [
        {"condition": "json.length === 1"},
        {"condition": "json[0].getUuid() === '{{bills.[0].uuid}}'"},
        {"condition": "json[0].getStatus().name() === 'paid'"},
        {"condition": "json[0].getRefundedAmount() === 0"}
      ]
    }
  },

  {
    "comment": "start the network",
    "request": {
      "uri": "me/networks/{{accountPlan.network}}/actions/start?cloud=MockCompute&region=nyc_mock",
      "method": "post"
    },
    "response": {
      "store": "newNetworkNotification"
    }
  },

  {
    "before": "sleep 5s",
    "comment": "verify the network is running",
    "request": { "uri": "me/networks/{{accountPlan.network}}" },
    "response": {
      "check": [ {"condition": "json.getState().name() == 'running'"} ]
    }
  },

  {
    "before": "fast_forward_and_bill 31d",
    "comment": "1st fast-forward: +31 days, verify a new bill exists for accountPlan",
    "request": { "uri": "me/plans/{{accountPlan.uuid}}/bills" },
    "response": {
      "check": [
        {"condition": "json.length === 2"},
        {"condition": "json[0].getPlan() === '{{plans.[0].uuid}}'"},
        {"condition": "json[0].getAccountPlan() === '{{accountPlan.uuid}}'"},
        {"condition": "json[0].getTotal() === {{plans.[0].price}}"},
        {"condition": "json[0].getStatus().name() === 'paid'"}
      ]
    }
  },

  {
    "comment": "1st fast-forward: verify a successful payment has been made for the new bill for accountPlan",
    "request": { "uri": "me/plans/{{accountPlan.uuid}}/payments" },
    "response": {
      "check": [
        {"condition": "json.length === 2"},
        {"condition": "json[0].getPlan() === '{{plans.[0].uuid}}'"},
        {"condition": "json[0].getAccountPlan() === '{{accountPlan.uuid}}'"},
        {"condition": "json[0].getAmount() === {{plans.[0].price}}"},
        {"condition": "json[0].getStatus().name() === 'success'"},
        {"condition": "json[0].getBillObject().getPlan() === '{{plans.[0].uuid}}'"},
        {"condition": "json[0].getBillObject().getAccountPlan() === '{{accountPlan.uuid}}'"},
        {"condition": "json[0].getBillObject().getTotal() === {{plans.[0].price}}"},
        {"condition": "json[0].getBillObject().getStatus().name() === 'paid'"}
      ]
    }
  },

  {
    "before": "fast_forward_and_bill 31d",
    "comment": "2nd fast-forward: fast-forward another +31 days, verify a new bill exists for accountPlan",
    "request": { "uri": "me/plans/{{accountPlan.uuid}}/bills" },
    "response": {
      "check": [
        {"condition": "json.length === 3"},
        {"condition": "json[0].getPlan() === '{{plans.[0].uuid}}'"},
        {"condition": "json[0].getAccountPlan() === '{{accountPlan.uuid}}'"},
        {"condition": "json[0].getTotal() === {{plans.[0].price}}"},
        {"condition": "json[0].getStatus().name() === 'paid'"}
      ]
    }
  },

  {
    "comment": "2nd fast-forward: verify a successful payment has been made for the new bill for accountPlan",
    "request": { "uri": "me/plans/{{accountPlan.uuid}}/payments" },
    "response": {
      "check": [
        {"condition": "json.length === 3"},
        {"condition": "json[0].getPlan() === '{{plans.[0].uuid}}'"},
        {"condition": "json[0].getAccountPlan() === '{{accountPlan.uuid}}'"},
        {"condition": "json[0].getAmount() === {{plans.[0].price}}"},
        {"condition": "json[0].getStatus().name() === 'success'"},
        {"condition": "json[0].getBillObject().getPlan() === '{{plans.[0].uuid}}'"},
        {"condition": "json[0].getBillObject().getAccountPlan() === '{{accountPlan.uuid}}'"},
        {"condition": "json[0].getBillObject().getTotal() === {{plans.[0].price}}"},
        {"condition": "json[0].getBillObject().getStatus().name() === 'paid'"}
      ]
    }
  },

  {
    "before": "fast_forward_and_bill 62d 20s",
    "comment": "3rd fast-forward: fast-forward even more, +66 days, we have missed a billing cycle, so two new bills should be created",
    "request": { "uri": "me/plans/{{accountPlan.uuid}}/bills" },
    "response": {
      "check": [
        {"condition": "json.length === 5"},
        {"condition": "json[0].getPlan() === '{{plans.[0].uuid}}'"},
        {"condition": "json[0].getAccountPlan() === '{{accountPlan.uuid}}'"},
        {"condition": "json[0].getTotal() === {{plans.[0].price}}"},
        {"condition": "json[0].getStatus().name() === 'paid'"},
        {"condition": "json[1].getPlan() === '{{plans.[0].uuid}}'"},
        {"condition": "json[1].getAccountPlan() === '{{accountPlan.uuid}}'"},
        {"condition": "json[1].getTotal() === {{plans.[0].price}}"},
        {"condition": "json[1].getStatus().name() === 'paid'"}
      ]
    }
  },

  {
    "comment": "3rd fast-forward: verify a successful payment has been made for all new bills for accountPlan",
    "request": { "uri": "me/plans/{{accountPlan.uuid}}/payments" },
    "response": {
      "check": [
        {"condition": "json.length === 5"},
        {"condition": "json[0].getPlan() === '{{plans.[0].uuid}}'"},
        {"condition": "json[0].getAccountPlan() === '{{accountPlan.uuid}}'"},
        {"condition": "json[0].getAmount() === {{plans.[0].price}}"},
        {"condition": "json[0].getStatus().name() === 'success'"},
        {"condition": "json[0].getBillObject().getPlan() === '{{plans.[0].uuid}}'"},
        {"condition": "json[0].getBillObject().getAccountPlan() === '{{accountPlan.uuid}}'"},
        {"condition": "json[0].getBillObject().getTotal() === {{plans.[0].price}}"},
        {"condition": "json[0].getBillObject().getStatus().name() === 'paid'"},
        {"condition": "json[1].getPlan() === '{{plans.[0].uuid}}'"},
        {"condition": "json[1].getAccountPlan() === '{{accountPlan.uuid}}'"},
        {"condition": "json[1].getAmount() === {{plans.[0].price}}"},
        {"condition": "json[1].getStatus().name() === 'success'"},
        {"condition": "json[1].getBillObject().getPlan() === '{{plans.[0].uuid}}'"},
        {"condition": "json[1].getBillObject().getAccountPlan() === '{{accountPlan.uuid}}'"},
        {"condition": "json[1].getBillObject().getTotal() === {{plans.[0].price}}"},
        {"condition": "json[1].getBillObject().getStatus().name() === 'paid'"}
      ]
    },
    "after": "set_stripe_error charge"  // set mock so charging the card fails
  },

  {
    "before": "fast_forward_and_bill 31d",
    "comment": "4nd fast-forward: fast-forward another +33 days, verify new bill (unpaid) created",
    "request": { "uri": "me/plans/{{accountPlan.uuid}}/bills" },
    "response": {
      "store": "bills",
      "check": [
        {"condition": "json.length === 6"},
        {"condition": "json[0].getPlan() === '{{plans.[0].uuid}}'"},
        {"condition": "json[0].getAccountPlan() === '{{accountPlan.uuid}}'"},
        {"condition": "json[0].getTotal() === {{plans.[0].price}}"},
        {"condition": "json[0].getStatus().name() === 'unpaid'"}
      ]
    }
  },

  {
    "comment": "4th fast-forward: verify payment failed",
    "request": { "uri": "me/plans/{{accountPlan.uuid}}/payments" },
    "response": {
      "check": [
        {"condition": "json.length === 6"},
        {"condition": "json[0].getPlan() === '{{plans.[0].uuid}}'"},
        {"condition": "json[0].getAccountPlan() === '{{accountPlan.uuid}}'"},
        {"condition": "json[0].getAmount() === {{plans.[0].price}}"},
        {"condition": "json[0].getStatus().name() === 'failure'"},
        {"condition": "json[0].getBillObject().getPlan() === '{{plans.[0].uuid}}'"},
        {"condition": "json[0].getBillObject().getAccountPlan() === '{{accountPlan.uuid}}'"},
        {"condition": "json[0].getBillObject().getTotal() === {{plans.[0].price}}"},
        {"condition": "json[0].getBillObject().getStatus().name() === 'unpaid'"}
      ]
    }
  },

  {
    "comment": "as root, verify payment reminder message has been sent",
    "request": {
      "session": "rootSession",
      "uri": "debug/inbox/email/test_user_recurring@example.com?type=request&action=payment&target=network"
    },
    "response": {
      "store": "emailInbox",
      "check": [
        {"condition": "'{{json.[0].ctx.message.messageType}}' === 'request'"},
        {"condition": "'{{json.[0].ctx.message.action}}' === 'payment'"},
        {"condition": "'{{json.[0].ctx.message.target}}' === 'network'"}
      ]
    }
  },

  {
    "before": "fast_forward_and_bill 7d",
    "comment": "5th fast-forward: fast-forward another +6 days, bill is still unpaid, bubble is stopped",
    "request": {
      "session": "userSession",
      "uri": "me/plans/{{accountPlan.uuid}}/bills"
    },
    "response": {
      "check": [
        {"condition": "json.length === 6"},
        {"condition": "json[0].getPlan() === '{{plans.[0].uuid}}'"},
        {"condition": "json[0].getAccountPlan() === '{{accountPlan.uuid}}'"},
        {"condition": "json[0].getTotal() === {{plans.[0].price}}"}
      ]
    }
  },

  {
    "before": "sleep 10s",
    "comment": "as root, verify nonpayment message has been sent",
    "request": {
      "session": "rootSession",
      "uri": "debug/inbox/email/test_user_recurring@example.com?type=notice&action=payment&target=network"
    },
    "response": {
      "store": "emailInbox",
      "check": [
        {"condition": "'{{json.[0].ctx.message.messageType}}' === 'notice'"},
        {"condition": "'{{json.[0].ctx.message.action}}' === 'payment'"},
        {"condition": "'{{json.[0].ctx.message.target}}' === 'network'"}
      ]
    }
  },

  {
    "before": "sleep 10s",
    "comment": "verify the network has been stopped",
    "request": {
      "session": "userSession",
      "uri": "me/networks/{{accountPlan.network}}"
    },
    "response": {
      "check": [ {"condition": "json.getState().name() == 'stopped'"} ]
    }
  },

  {
    "comment": "verify plan is no longer enabled",
    "request": { "uri": "me/plans/{{accountPlan.uuid}}" },
    "response": {
      "check": [ {"condition": "json.disabled()"} ]
    }
  },

  {
    "comment": "try to start network, fails due to non-payment",
    "request": {
      "uri": "me/networks/{{accountPlan.network}}/actions/start?cloud=MockCompute&region=nyc_mock",
      "method": "post"
    },
    "response": {
      "status": 422,
      "check": [ {"condition": "json.has('err.accountPlan.disabled')"} ]
    }
  },

  {
    "before": "stripe_tokenize_card",
    "comment": "add another payment method",
    "request": {
      "uri": "me/paymentMethods",
      "method": "put",
      "entity": {
        "paymentMethodType": "credit",
        "paymentInfo": "{{stripeToken}}"
      }
    },
    "response": {
      "store": "newPaymentMethod"
    }
  },

  {
    "comment": "update payment method for plan",
    "request": {
      "uri": "me/plans/{{accountPlan.uuid}}",
      "entity": {
        "paymentMethodObject": {
          "uuid": "{{newPaymentMethod.uuid}}"
        }
      }
    }
  },

  {
    "before": "unset_stripe_error",
    "comment": "submit payment for unpaid bill",
    "request": {
      "uri": "me/plans/{{accountPlan.uuid}}/bills/{{bills.[0].uuid}}/pay",
      "method": "post"
    },
    "response": {
      "check": [ {"condition": "json.getStatus().name() == 'paid'"} ]
    }
  },

  {
    "comment": "verify plan has been re-enabled",
    "request": { "uri": "me/plans/{{accountPlan.uuid}}" },
    "response": {
      "check": [ {"condition": "json.enabled()"} ]
    }
  },

  {
    "comment": "start the network, succeeds because accountPlan is now current",
    "request": {
      "uri": "me/networks/{{accountPlan.network}}/actions/start?cloud=MockCompute&region=nyc_mock",
      "method": "post"
    },
    "response": {
      "store": "newNetworkNotification"
    }
  },

  {
    "before": "sleep 10s",
    "comment": "verify the network is running once again",
    "request": { "uri": "me/networks/{{accountPlan.network}}" },
    "response": {
      "check": [ {"condition": "json.getState().name() == 'running'"} ]
    }
  }
]