// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0

package describe

import (
	"errors"
	"fmt"
	"testing"

	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/copilot-cli/internal/pkg/aws/apprunner"
	"github.com/aws/copilot-cli/internal/pkg/describe/mocks"
	"github.com/aws/copilot-cli/internal/pkg/describe/stack"
	"github.com/golang/mock/gomock"
	"github.com/stretchr/testify/require"
)

const humanStringWithResources = `About

  Application  testapp
  Name         testsvc
  Type         Request-Driven Web Service

Configurations

  Environment  CPU (vCPU)  Memory (MiB)  Port
  -----------  ----------  ------------  ----
  test         1           2048          80
  prod         2           3072            "

Routes

  Environment  Ingress      URL
  -----------  -------      ---
  test         environment  https://6znxd4ra33.public.us-east-1.apprunner.amazonaws.com
  prod         internet     https://tumkjmvjjf.public.us-east-1.apprunner.amazonaws.com

Variables

  Name                      Environment  Value
  ----                      -----------  -----
  COPILOT_ENVIRONMENT_NAME  prod         prod
    "                       test         test

Secrets

  Name           Environment  Value
  ----           -----------  -----
  my-ssm-secret  prod         prod
    "            test         test

Resources

  test
    AWS::AppRunner::Service  arn:aws:apprunner:us-east-1:111111111111:service/testapp-test-testsvc

  prod
    AWS::AppRunner::Service  arn:aws:apprunner:us-east-1:111111111111:service/testapp-prod-testsvc
`

type apprunnerSvcDescriberMocks struct {
	storeSvc        *mocks.MockDeployedEnvServicesLister
	ecsSvcDescriber *mocks.MockapprunnerDescriber
}

func TestRDWebServiceDescriber_Describe(t *testing.T) {
	const (
		testApp = "testapp"
		testSvc = "testsvc"
		testEnv = "test"
		prodEnv = "prod"
	)
	mockErr := errors.New("some error")
	testCases := map[string]struct {
		shouldOutputResources bool

		setupMocks func(mocks apprunnerSvcDescriberMocks)

		wantedSvcDesc *rdWebSvcDesc
		wantedError   error
	}{
		"return error if fail to list environment": {
			setupMocks: func(m apprunnerSvcDescriberMocks) {
				gomock.InOrder(
					m.storeSvc.EXPECT().ListEnvironmentsDeployedTo(testApp, testSvc).Return(nil, mockErr),
				)
			},
			wantedError: fmt.Errorf("list deployed environments for application testapp: some error"),
		},
		"return error if fail to retrieve service configuration": {
			setupMocks: func(m apprunnerSvcDescriberMocks) {
				gomock.InOrder(
					m.storeSvc.EXPECT().ListEnvironmentsDeployedTo(testApp, testSvc).Return([]string{testEnv}, nil),
					m.ecsSvcDescriber.EXPECT().Service().Return(nil, mockErr),
				)
			},
			wantedError: fmt.Errorf("retrieve service configuration: some error"),
		},
		"return error if fail to get service url": {
			shouldOutputResources: true,
			setupMocks: func(m apprunnerSvcDescriberMocks) {
				gomock.InOrder(
					m.storeSvc.EXPECT().ListEnvironmentsDeployedTo(testApp, testSvc).Return([]string{testEnv}, nil),
					m.ecsSvcDescriber.EXPECT().Service().Return(&apprunner.Service{}, nil),
					m.ecsSvcDescriber.EXPECT().ServiceURL().Return("", mockErr),
				)
			},
			wantedError: fmt.Errorf("retrieve service url: some error"),
		},
		"return error if fail to check if private": {
			shouldOutputResources: true,
			setupMocks: func(m apprunnerSvcDescriberMocks) {
				gomock.InOrder(
					m.storeSvc.EXPECT().ListEnvironmentsDeployedTo(testApp, testSvc).Return([]string{testEnv}, nil),
					m.ecsSvcDescriber.EXPECT().Service().Return(&apprunner.Service{}, nil),
					m.ecsSvcDescriber.EXPECT().ServiceURL().Return("", nil),
					m.ecsSvcDescriber.EXPECT().IsPrivate().Return(false, mockErr),
				)
			},
			wantedError: fmt.Errorf("check if service is private: some error"),
		},
		"return error if fail to retrieve service resources": {
			shouldOutputResources: true,
			setupMocks: func(m apprunnerSvcDescriberMocks) {
				gomock.InOrder(
					m.storeSvc.EXPECT().ListEnvironmentsDeployedTo(testApp, testSvc).Return([]string{testEnv}, nil),
					m.ecsSvcDescriber.EXPECT().Service().Return(&apprunner.Service{}, nil),
					m.ecsSvcDescriber.EXPECT().ServiceURL().Return("", nil),
					m.ecsSvcDescriber.EXPECT().IsPrivate().Return(false, nil),
					m.ecsSvcDescriber.EXPECT().StackResources().Return(nil, mockErr),
				)
			},
			wantedError: fmt.Errorf("retrieve service resources: some error"),
		},
		"success": {
			shouldOutputResources: true,
			setupMocks: func(m apprunnerSvcDescriberMocks) {
				gomock.InOrder(
					m.storeSvc.EXPECT().ListEnvironmentsDeployedTo(testApp, testSvc).Return([]string{testEnv, prodEnv}, nil),
					m.ecsSvcDescriber.EXPECT().Service().Return(&apprunner.Service{
						ServiceARN: "arn:aws:apprunner:us-east-1:111111111111:service/testapp-test-testsvc",
						ServiceURL: "6znxd4ra33.public.us-east-1.apprunner.amazonaws.com",
						CPU:        "1024",
						Memory:     "2048",
						Port:       "80",
						EnvironmentVariables: []*apprunner.EnvironmentVariable{
							{
								Name:  "COPILOT_ENVIRONMENT_NAME",
								Value: "test",
							},
						},
						EnvironmentSecrets: []*apprunner.EnvironmentSecret{
							{
								Name:  "SOME_OTHER_SECRET",
								Value: "arn:aws:ssm:us-east-1:111111111111:parameter/SHHHHH",
							},
						},
					}, nil),
					m.ecsSvcDescriber.EXPECT().ServiceURL().Return("https://6znxd4ra33.public.us-east-1.apprunner.amazonaws.com", nil),
					m.ecsSvcDescriber.EXPECT().IsPrivate().Return(true, nil),
					m.ecsSvcDescriber.EXPECT().StackResources().Return([]*stack.Resource{
						{
							Type:       "AWS::AppRunner::Service",
							PhysicalID: "arn:aws:apprunner:us-east-1:111111111111:service/testapp-test-testsvc",
						},
					}, nil),
					m.ecsSvcDescriber.EXPECT().Service().Return(&apprunner.Service{
						ServiceARN: "arn:aws:apprunner:us-east-1:111111111111:service/testapp-prod-testsvc",
						ServiceURL: "tumkjmvjjf.public.us-east-1.apprunner.amazonaws.com",
						CPU:        "2048",
						Memory:     "3072",
						Port:       "80",
						EnvironmentVariables: []*apprunner.EnvironmentVariable{
							{
								Name:  "COPILOT_ENVIRONMENT_NAME",
								Value: "prod",
							},
						},
						EnvironmentSecrets: []*apprunner.EnvironmentSecret{
							{
								Name:  "my-ssm-secret",
								Value: "arn:aws:ssm:us-east-1:111111111111:parameter/jan11ssm",
							},
						},
					}, nil),
					m.ecsSvcDescriber.EXPECT().ServiceURL().Return("https://tumkjmvjjf.public.us-east-1.apprunner.amazonaws.com", nil),
					m.ecsSvcDescriber.EXPECT().IsPrivate().Return(false, nil),
					m.ecsSvcDescriber.EXPECT().StackResources().Return([]*stack.Resource{
						{
							Type:       "AWS::AppRunner::Service",
							PhysicalID: "arn:aws:apprunner:us-east-1:111111111111:service/testapp-prod-testsvc",
						},
					}, nil),
				)
			},
			wantedSvcDesc: &rdWebSvcDesc{
				Service: testSvc,
				Type:    "Request-Driven Web Service",
				App:     testApp,
				AppRunnerConfigurations: []*ServiceConfig{
					{
						CPU:         "1024",
						Environment: "test",
						Memory:      "2048",
						Port:        "80",
					},
					{
						CPU:         "2048",
						Environment: "prod",
						Memory:      "3072",
						Port:        "80",
					},
				},
				Routes: []*RDWSRoute{
					{
						Environment: "test",
						URL:         "https://6znxd4ra33.public.us-east-1.apprunner.amazonaws.com",
						Ingress:     rdwsIngressEnvironment,
					},
					{
						Environment: "prod",
						URL:         "https://tumkjmvjjf.public.us-east-1.apprunner.amazonaws.com",
						Ingress:     rdwsIngressInternet,
					},
				},
				Variables: []*envVar{
					{
						Environment: "test",
						Name:        "COPILOT_ENVIRONMENT_NAME",
						Value:       "test",
					},
					{
						Environment: "prod",
						Name:        "COPILOT_ENVIRONMENT_NAME",
						Value:       "prod",
					},
				},
				Secrets: []*rdwsSecret{
					{
						Environment: "test",
						Name:        "SOME_OTHER_SECRET",
						ValueFrom:   "arn:aws:ssm:us-east-1:111111111111:parameter/SHHHHH",
					},
					{
						Environment: "prod",
						Name:        "my-ssm-secret",
						ValueFrom:   "arn:aws:ssm:us-east-1:111111111111:parameter/jan11ssm",
					},
				},
				Resources: map[string][]*stack.Resource{
					"test": {
						{
							Type:       "AWS::AppRunner::Service",
							PhysicalID: "arn:aws:apprunner:us-east-1:111111111111:service/testapp-test-testsvc",
						},
					},
					"prod": {
						{
							Type:       "AWS::AppRunner::Service",
							PhysicalID: "arn:aws:apprunner:us-east-1:111111111111:service/testapp-prod-testsvc",
						},
					},
				},
				environments: []string{"test", "prod"},
			},
		},
		"success with observability": {
			shouldOutputResources: true,
			setupMocks: func(m apprunnerSvcDescriberMocks) {
				gomock.InOrder(
					m.storeSvc.EXPECT().ListEnvironmentsDeployedTo(testApp, testSvc).Return([]string{testEnv, prodEnv}, nil),
					m.ecsSvcDescriber.EXPECT().Service().Return(&apprunner.Service{
						ServiceARN: "arn:aws:apprunner:us-east-1:111111111111:service/testapp-test-testsvc",
						ServiceURL: "6znxd4ra33.public.us-east-1.apprunner.amazonaws.com",
						CPU:        "1024",
						Memory:     "2048",
						Port:       "80",
						EnvironmentVariables: []*apprunner.EnvironmentVariable{
							{
								Name:  "COPILOT_ENVIRONMENT_NAME",
								Value: "test",
							},
						},
						EnvironmentSecrets: []*apprunner.EnvironmentSecret{
							{
								Name:  "SOME_OTHER_SECRET",
								Value: "arn:aws:ssm:us-east-1:111111111111:parameter/SHHHHH",
							},
						},
						Observability: apprunner.ObservabilityConfiguration{
							TraceConfiguration: &apprunner.TraceConfiguration{
								Vendor: aws.String("mockVendor"),
							},
						},
					}, nil),
					m.ecsSvcDescriber.EXPECT().ServiceURL().Return("https://6znxd4ra33.public.us-east-1.apprunner.amazonaws.com", nil),
					m.ecsSvcDescriber.EXPECT().IsPrivate().Return(true, nil),
					m.ecsSvcDescriber.EXPECT().StackResources().Return([]*stack.Resource{
						{
							Type:       "AWS::AppRunner::Service",
							PhysicalID: "arn:aws:apprunner:us-east-1:111111111111:service/testapp-test-testsvc",
						},
					}, nil),
					m.ecsSvcDescriber.EXPECT().Service().Return(&apprunner.Service{
						ServiceARN: "arn:aws:apprunner:us-east-1:111111111111:service/testapp-prod-testsvc",
						ServiceURL: "tumkjmvjjf.public.us-east-1.apprunner.amazonaws.com",
						CPU:        "2048",
						Memory:     "3072",
						Port:       "80",
						EnvironmentVariables: []*apprunner.EnvironmentVariable{
							{
								Name:  "COPILOT_ENVIRONMENT_NAME",
								Value: "prod",
							},
						},
						EnvironmentSecrets: []*apprunner.EnvironmentSecret{
							{
								Name:  "my-ssm-secret",
								Value: "arn:aws:ssm:us-east-1:111111111111:parameter/jan11ssm",
							},
						},
					}, nil),
					m.ecsSvcDescriber.EXPECT().ServiceURL().Return("https://tumkjmvjjf.public.us-east-1.apprunner.amazonaws.com", nil),
					m.ecsSvcDescriber.EXPECT().IsPrivate().Return(false, nil),
					m.ecsSvcDescriber.EXPECT().StackResources().Return([]*stack.Resource{
						{
							Type:       "AWS::AppRunner::Service",
							PhysicalID: "arn:aws:apprunner:us-east-1:111111111111:service/testapp-prod-testsvc",
						},
					}, nil),
				)
			},
			wantedSvcDesc: &rdWebSvcDesc{
				Service: testSvc,
				Type:    "Request-Driven Web Service",
				App:     testApp,
				AppRunnerConfigurations: []*ServiceConfig{
					{
						CPU:         "1024",
						Environment: "test",
						Memory:      "2048",
						Port:        "80",
					},
					{
						CPU:         "2048",
						Environment: "prod",
						Memory:      "3072",
						Port:        "80",
					},
				},
				Routes: []*RDWSRoute{
					{
						Environment: "test",
						URL:         "https://6znxd4ra33.public.us-east-1.apprunner.amazonaws.com",
						Ingress:     rdwsIngressEnvironment,
					},
					{
						Environment: "prod",
						URL:         "https://tumkjmvjjf.public.us-east-1.apprunner.amazonaws.com",
						Ingress:     rdwsIngressInternet,
					},
				},
				Variables: []*envVar{
					{
						Environment: "test",
						Name:        "COPILOT_ENVIRONMENT_NAME",
						Value:       "test",
					},
					{
						Environment: "prod",
						Name:        "COPILOT_ENVIRONMENT_NAME",
						Value:       "prod",
					},
				},
				Secrets: []*rdwsSecret{
					{
						Environment: "test",
						Name:        "SOME_OTHER_SECRET",
						ValueFrom:   "arn:aws:ssm:us-east-1:111111111111:parameter/SHHHHH",
					},
					{
						Environment: "prod",
						Name:        "my-ssm-secret",
						ValueFrom:   "arn:aws:ssm:us-east-1:111111111111:parameter/jan11ssm",
					},
				},
				Observability: []observabilityInEnv{
					{
						Environment: "test",
						Tracing: &tracing{
							Vendor: "mockVendor",
						},
					},
					{
						Environment: "prod",
					},
				},
				Resources: map[string][]*stack.Resource{
					"test": {
						{
							Type:       "AWS::AppRunner::Service",
							PhysicalID: "arn:aws:apprunner:us-east-1:111111111111:service/testapp-test-testsvc",
						},
					},
					"prod": {
						{
							Type:       "AWS::AppRunner::Service",
							PhysicalID: "arn:aws:apprunner:us-east-1:111111111111:service/testapp-prod-testsvc",
						},
					},
				},
				environments: []string{"test", "prod"},
			},
		},
	}

	for name, tc := range testCases {
		t.Run(name, func(t *testing.T) {
			ctrl := gomock.NewController(t)
			defer ctrl.Finish()

			mockStore := mocks.NewMockDeployedEnvServicesLister(ctrl)
			mockSvcDescriber := mocks.NewMockapprunnerDescriber(ctrl)
			mocks := apprunnerSvcDescriberMocks{
				storeSvc:        mockStore,
				ecsSvcDescriber: mockSvcDescriber,
			}

			tc.setupMocks(mocks)

			d := &RDWebServiceDescriber{
				app:                    testApp,
				svc:                    testSvc,
				enableResources:        tc.shouldOutputResources,
				store:                  mockStore,
				initAppRunnerDescriber: func(string) (apprunnerDescriber, error) { return mockSvcDescriber, nil },
			}

			// WHEN
			svcDesc, err := d.Describe()

			// THEN
			if tc.wantedError != nil {
				require.EqualError(t, err, tc.wantedError.Error())
			} else {
				require.NoError(t, err)
				require.Equal(t, tc.wantedSvcDesc, svcDesc, "expected output content match")
			}
		})
	}
}

func TestRDWebServiceDesc_String(t *testing.T) {
	t.Run("correct output including resources", func(t *testing.T) {
		wantedHumanString := humanStringWithResources
		wantedJSONString := "{\"service\":\"testsvc\",\"type\":\"Request-Driven Web Service\",\"application\":\"testapp\",\"configurations\":[{\"environment\":\"test\",\"port\":\"80\",\"cpu\":\"1024\",\"memory\":\"2048\"},{\"environment\":\"prod\",\"port\":\"80\",\"cpu\":\"2048\",\"memory\":\"3072\"}],\"routes\":[{\"environment\":\"test\",\"url\":\"https://6znxd4ra33.public.us-east-1.apprunner.amazonaws.com\",\"ingress\":\"environment\"},{\"environment\":\"prod\",\"url\":\"https://tumkjmvjjf.public.us-east-1.apprunner.amazonaws.com\",\"ingress\":\"internet\"}],\"variables\":[{\"environment\":\"prod\",\"name\":\"COPILOT_ENVIRONMENT_NAME\",\"value\":\"prod\"},{\"environment\":\"test\",\"name\":\"COPILOT_ENVIRONMENT_NAME\",\"value\":\"test\"}],\"resources\":{\"prod\":[{\"type\":\"AWS::AppRunner::Service\",\"physicalID\":\"arn:aws:apprunner:us-east-1:111111111111:service/testapp-prod-testsvc\"}],\"test\":[{\"type\":\"AWS::AppRunner::Service\",\"physicalID\":\"arn:aws:apprunner:us-east-1:111111111111:service/testapp-test-testsvc\"}]},\"secrets\":[{\"environment\":\"prod\",\"name\":\"my-ssm-secret\",\"value\":\"prod\"},{\"environment\":\"test\",\"name\":\"my-ssm-secret\",\"value\":\"test\"}]}\n"
		svcDesc := &rdWebSvcDesc{
			Service: "testsvc",
			Type:    "Request-Driven Web Service",
			App:     "testapp",
			AppRunnerConfigurations: []*ServiceConfig{
				{
					CPU:         "1024",
					Environment: "test",
					Memory:      "2048",
					Port:        "80",
				},
				{
					CPU:         "2048",
					Environment: "prod",
					Memory:      "3072",
					Port:        "80",
				},
			},
			Routes: []*RDWSRoute{
				{
					Environment: "test",
					URL:         "https://6znxd4ra33.public.us-east-1.apprunner.amazonaws.com",
					Ingress:     rdwsIngressEnvironment,
				},
				{
					Environment: "prod",
					URL:         "https://tumkjmvjjf.public.us-east-1.apprunner.amazonaws.com",
					Ingress:     rdwsIngressInternet,
				},
			},
			Variables: []*envVar{
				{
					Environment: "test",
					Name:        "COPILOT_ENVIRONMENT_NAME",
					Value:       "test",
				},
				{
					Environment: "prod",
					Name:        "COPILOT_ENVIRONMENT_NAME",
					Value:       "prod",
				},
			},
			Secrets: []*rdwsSecret{
				{
					Environment: "prod",
					Name:        "my-ssm-secret",
					ValueFrom:   "prod",
				},
				{
					Environment: "test",
					Name:        "my-ssm-secret",
					ValueFrom:   "test",
				},
			},
			Resources: map[string][]*stack.Resource{
				"test": {
					{
						Type:       "AWS::AppRunner::Service",
						PhysicalID: "arn:aws:apprunner:us-east-1:111111111111:service/testapp-test-testsvc",
					},
				},
				"prod": {
					{
						Type:       "AWS::AppRunner::Service",
						PhysicalID: "arn:aws:apprunner:us-east-1:111111111111:service/testapp-prod-testsvc",
					},
				},
			},
			environments: []string{"test", "prod"},
		}
		human := svcDesc.HumanString()
		json, _ := svcDesc.JSONString()

		require.Equal(t, wantedHumanString, human)
		require.Equal(t, wantedJSONString, json)
	})

	t.Run("correct output including resources with observability", func(t *testing.T) {
		wantedHumanString := `About

  Application  testapp
  Name         testsvc
  Type         Request-Driven Web Service

Configurations

  Environment  CPU (vCPU)  Memory (MiB)  Port
  -----------  ----------  ------------  ----
  test         1           2048          80
  prod         2           3072            "

Observability

  Environment  Tracing
  -----------  -------
  test         mockVendor
  prod         None

Routes

  Environment  Ingress      URL
  -----------  -------      ---
  test         environment  https://6znxd4ra33.public.us-east-1.apprunner.amazonaws.com
  prod         internet     https://tumkjmvjjf.public.us-east-1.apprunner.amazonaws.com

Variables

  Name                      Environment  Value
  ----                      -----------  -----
  COPILOT_ENVIRONMENT_NAME  prod         prod
    "                       test         test

Secrets

  Name           Environment  Value
  ----           -----------  -----
  my-ssm-secret  prod         prod
    "            test         test

Resources

  test
    AWS::AppRunner::Service  arn:aws:apprunner:us-east-1:111111111111:service/testapp-test-testsvc

  prod
    AWS::AppRunner::Service  arn:aws:apprunner:us-east-1:111111111111:service/testapp-prod-testsvc
`
		wantedJSONString := "{\"service\":\"testsvc\",\"type\":\"Request-Driven Web Service\",\"application\":\"testapp\",\"configurations\":[{\"environment\":\"test\",\"port\":\"80\",\"cpu\":\"1024\",\"memory\":\"2048\"},{\"environment\":\"prod\",\"port\":\"80\",\"cpu\":\"2048\",\"memory\":\"3072\"}],\"routes\":[{\"environment\":\"test\",\"url\":\"https://6znxd4ra33.public.us-east-1.apprunner.amazonaws.com\",\"ingress\":\"environment\"},{\"environment\":\"prod\",\"url\":\"https://tumkjmvjjf.public.us-east-1.apprunner.amazonaws.com\",\"ingress\":\"internet\"}],\"variables\":[{\"environment\":\"prod\",\"name\":\"COPILOT_ENVIRONMENT_NAME\",\"value\":\"prod\"},{\"environment\":\"test\",\"name\":\"COPILOT_ENVIRONMENT_NAME\",\"value\":\"test\"}],\"resources\":{\"prod\":[{\"type\":\"AWS::AppRunner::Service\",\"physicalID\":\"arn:aws:apprunner:us-east-1:111111111111:service/testapp-prod-testsvc\"}],\"test\":[{\"type\":\"AWS::AppRunner::Service\",\"physicalID\":\"arn:aws:apprunner:us-east-1:111111111111:service/testapp-test-testsvc\"}]},\"observability\":[{\"environment\":\"test\",\"tracing\":{\"vendor\":\"mockVendor\"}},{\"environment\":\"prod\"}],\"secrets\":[{\"environment\":\"prod\",\"name\":\"my-ssm-secret\",\"value\":\"prod\"},{\"environment\":\"test\",\"name\":\"my-ssm-secret\",\"value\":\"test\"}]}\n"
		svcDesc := &rdWebSvcDesc{
			Service: "testsvc",
			Type:    "Request-Driven Web Service",
			App:     "testapp",
			AppRunnerConfigurations: []*ServiceConfig{
				{
					CPU:         "1024",
					Environment: "test",
					Memory:      "2048",
					Port:        "80",
				},
				{
					CPU:         "2048",
					Environment: "prod",
					Memory:      "3072",
					Port:        "80",
				},
			},
			Routes: []*RDWSRoute{
				{
					Environment: "test",
					URL:         "https://6znxd4ra33.public.us-east-1.apprunner.amazonaws.com",
					Ingress:     rdwsIngressEnvironment,
				},
				{
					Environment: "prod",
					URL:         "https://tumkjmvjjf.public.us-east-1.apprunner.amazonaws.com",
					Ingress:     rdwsIngressInternet,
				},
			},
			Variables: []*envVar{
				{
					Environment: "test",
					Name:        "COPILOT_ENVIRONMENT_NAME",
					Value:       "test",
				},
				{
					Environment: "prod",
					Name:        "COPILOT_ENVIRONMENT_NAME",
					Value:       "prod",
				},
			},
			Secrets: []*rdwsSecret{
				{
					Environment: "prod",
					Name:        "my-ssm-secret",
					ValueFrom:   "prod",
				},
				{
					Environment: "test",
					Name:        "my-ssm-secret",
					ValueFrom:   "test",
				},
			},
			Observability: []observabilityInEnv{
				{
					Environment: "test",
					Tracing: &tracing{
						Vendor: "mockVendor",
					},
				},
				{
					Environment: "prod",
				},
			},
			Resources: map[string][]*stack.Resource{
				"test": {
					{
						Type:       "AWS::AppRunner::Service",
						PhysicalID: "arn:aws:apprunner:us-east-1:111111111111:service/testapp-test-testsvc",
					},
				},
				"prod": {
					{
						Type:       "AWS::AppRunner::Service",
						PhysicalID: "arn:aws:apprunner:us-east-1:111111111111:service/testapp-prod-testsvc",
					},
				},
			},
			environments: []string{"test", "prod"},
		}
		human := svcDesc.HumanString()
		json, _ := svcDesc.JSONString()

		require.Equal(t, wantedHumanString, human)
		require.Equal(t, wantedJSONString, json)
	})
}