github.com/dcarley/cf-cli@v6.24.1-0.20170220111324-4225ff346898+incompatible/command/v2/app_command_test.go (about)

     1  package v2_test
     2  
     3  import (
     4  	"errors"
     5  	"time"
     6  
     7  	"code.cloudfoundry.org/cli/actor/sharedaction"
     8  	"code.cloudfoundry.org/cli/actor/v2action"
     9  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2"
    10  	"code.cloudfoundry.org/cli/command"
    11  	"code.cloudfoundry.org/cli/command/commandfakes"
    12  	"code.cloudfoundry.org/cli/command/v2"
    13  	"code.cloudfoundry.org/cli/command/v2/v2fakes"
    14  	"code.cloudfoundry.org/cli/util/configv3"
    15  	"code.cloudfoundry.org/cli/util/ui"
    16  	"github.com/cloudfoundry/bytefmt"
    17  	. "github.com/onsi/ginkgo"
    18  	. "github.com/onsi/gomega"
    19  	. "github.com/onsi/gomega/gbytes"
    20  )
    21  
    22  var _ = Describe("App Command", func() {
    23  	var (
    24  		cmd             v2.AppCommand
    25  		testUI          *ui.UI
    26  		fakeConfig      *commandfakes.FakeConfig
    27  		fakeSharedActor *commandfakes.FakeSharedActor
    28  		fakeActor       *v2fakes.FakeAppActor
    29  		binaryName      string
    30  		executeErr      error
    31  	)
    32  
    33  	BeforeEach(func() {
    34  		testUI = ui.NewTestUI(nil, NewBuffer(), NewBuffer())
    35  		fakeConfig = new(commandfakes.FakeConfig)
    36  		fakeSharedActor = new(commandfakes.FakeSharedActor)
    37  		fakeActor = new(v2fakes.FakeAppActor)
    38  
    39  		cmd = v2.AppCommand{
    40  			UI:          testUI,
    41  			Config:      fakeConfig,
    42  			SharedActor: fakeSharedActor,
    43  			Actor:       fakeActor,
    44  		}
    45  
    46  		cmd.RequiredArgs.AppName = "some-app"
    47  
    48  		binaryName = "faceman"
    49  		fakeConfig.BinaryNameReturns(binaryName)
    50  
    51  		// TODO: remove when experimental flag is removed
    52  		fakeConfig.ExperimentalReturns(true)
    53  	})
    54  
    55  	JustBeforeEach(func() {
    56  		executeErr = cmd.Execute(nil)
    57  	})
    58  
    59  	// TODO: remove when experimental flag is removed
    60  	It("Displays the experimental warning message", func() {
    61  		Expect(testUI.Out).To(Say(command.ExperimentalWarning))
    62  	})
    63  
    64  	Context("when checking target fails", func() {
    65  		BeforeEach(func() {
    66  			fakeSharedActor.CheckTargetReturns(sharedaction.NotLoggedInError{BinaryName: binaryName})
    67  		})
    68  
    69  		It("returns an error if the check fails", func() {
    70  			Expect(executeErr).To(MatchError(command.NotLoggedInError{BinaryName: "faceman"}))
    71  
    72  			Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1))
    73  			_, checkTargetedOrg, checkTargetedSpace := fakeSharedActor.CheckTargetArgsForCall(0)
    74  			Expect(checkTargetedOrg).To(BeTrue())
    75  			Expect(checkTargetedSpace).To(BeTrue())
    76  		})
    77  	})
    78  
    79  	Context("when the user is logged in, and org and space are targeted", func() {
    80  		BeforeEach(func() {
    81  			fakeConfig.HasTargetedOrganizationReturns(true)
    82  			fakeConfig.TargetedOrganizationReturns(configv3.Organization{Name: "some-org"})
    83  			fakeConfig.HasTargetedSpaceReturns(true)
    84  			fakeConfig.TargetedSpaceReturns(configv3.Space{
    85  				GUID: "some-space-guid",
    86  				Name: "some-space"})
    87  			fakeConfig.CurrentUserReturns(
    88  				configv3.User{Name: "some-user"},
    89  				nil)
    90  		})
    91  
    92  		Context("when getting the current user returns an error", func() {
    93  			var expectedErr error
    94  
    95  			BeforeEach(func() {
    96  				expectedErr = errors.New("getting current user error")
    97  				fakeConfig.CurrentUserReturns(
    98  					configv3.User{},
    99  					expectedErr)
   100  			})
   101  
   102  			It("returns the error", func() {
   103  				Expect(executeErr).To(MatchError(expectedErr))
   104  			})
   105  		})
   106  
   107  		It("displays flavor text", func() {
   108  			Expect(testUI.Out).To(Say("Showing health and status for app some-app in org some-org / space some-space as some-user..."))
   109  		})
   110  
   111  		Context("when the --guid flag is provided", func() {
   112  			BeforeEach(func() {
   113  				cmd.GUID = true
   114  			})
   115  
   116  			Context("when no errors occur", func() {
   117  				BeforeEach(func() {
   118  					fakeActor.GetApplicationByNameAndSpaceReturns(
   119  						v2action.Application{GUID: "some-guid"},
   120  						v2action.Warnings{"warning-1", "warning-2"},
   121  						nil)
   122  				})
   123  
   124  				It("displays the application guid and all warnings", func() {
   125  					Expect(executeErr).ToNot(HaveOccurred())
   126  
   127  					Expect(testUI.Out).To(Say("some-guid"))
   128  					Expect(testUI.Err).To(Say("warning-1"))
   129  					Expect(testUI.Err).To(Say("warning-2"))
   130  				})
   131  			})
   132  
   133  			Context("when an error is encountered getting the app", func() {
   134  				Context("when the error is translatable", func() {
   135  					BeforeEach(func() {
   136  						fakeActor.GetApplicationByNameAndSpaceReturns(
   137  							v2action.Application{},
   138  							v2action.Warnings{"warning-1", "warning-2"},
   139  							v2action.ApplicationNotFoundError{Name: "some-app"})
   140  					})
   141  
   142  					It("returns a translatable error and all warnings", func() {
   143  						Expect(executeErr).To(MatchError(command.ApplicationNotFoundError{Name: "some-app"}))
   144  
   145  						Expect(testUI.Err).To(Say("warning-1"))
   146  						Expect(testUI.Err).To(Say("warning-2"))
   147  					})
   148  				})
   149  
   150  				Context("when the error is not translatable", func() {
   151  					var expectedErr error
   152  
   153  					BeforeEach(func() {
   154  						expectedErr = errors.New("get app summary error")
   155  						fakeActor.GetApplicationByNameAndSpaceReturns(
   156  							v2action.Application{},
   157  							v2action.Warnings{"warning-1", "warning-2"},
   158  							expectedErr)
   159  					})
   160  
   161  					It("returns the error and all warnings", func() {
   162  						Expect(executeErr).To(MatchError(expectedErr))
   163  
   164  						Expect(testUI.Err).To(Say("warning-1"))
   165  						Expect(testUI.Err).To(Say("warning-2"))
   166  					})
   167  				})
   168  			})
   169  		})
   170  
   171  		Context("when the --guid flag is not provided", func() {
   172  			Context("when no errors occur", func() {
   173  				var (
   174  					applicationSummary v2action.ApplicationSummary
   175  					warnings           []string
   176  				)
   177  
   178  				BeforeEach(func() {
   179  					applicationSummary = v2action.ApplicationSummary{
   180  						Application: v2action.Application{
   181  							Name:              "some-app",
   182  							GUID:              "some-app-guid",
   183  							Instances:         3,
   184  							Memory:            128,
   185  							PackageUpdatedAt:  time.Unix(0, 0),
   186  							DetectedBuildpack: "some-buildpack",
   187  							State:             "STARTED",
   188  						},
   189  						Stack: v2action.Stack{
   190  							Name: "potatos",
   191  						},
   192  						Routes: []v2action.Route{
   193  							{
   194  								Host:   "banana",
   195  								Domain: "fruit.com",
   196  								Path:   "/hi",
   197  							},
   198  							{
   199  								Domain: "foobar.com",
   200  								Port:   13,
   201  							},
   202  						},
   203  					}
   204  					warnings = []string{"app-summary-warning"}
   205  				})
   206  
   207  				Context("when the app does not have running instances", func() {
   208  					BeforeEach(func() {
   209  						applicationSummary.RunningInstances = []v2action.ApplicationInstanceWithStats{}
   210  						fakeActor.GetApplicationSummaryByNameAndSpaceReturns(applicationSummary, warnings, nil)
   211  					})
   212  
   213  					It("displays the app summary, 'no running instances' message, and all warnings", func() {
   214  						Expect(testUI.Out).To(Say("Showing health and status for app some-app in org some-org / space some-space as some-user..."))
   215  						Expect(testUI.Out).To(Say(""))
   216  						Expect(testUI.Out).To(Say("Name:\\s+some-app"))
   217  						Expect(testUI.Out).To(Say("Requested state:\\s+started"))
   218  						Expect(testUI.Out).To(Say("Instances:\\s+0\\/3"))
   219  						Expect(testUI.Out).To(Say("Usage:\\s+128M x 3 instances"))
   220  						Expect(testUI.Out).To(Say("Routes:\\s+banana.fruit.com/hi, foobar.com:13"))
   221  						Expect(testUI.Out).To(Say("Last uploaded:\\s+1970-01-01T00:00:00Z"))
   222  						Expect(testUI.Out).To(Say("Stack:\\s+potatos"))
   223  						Expect(testUI.Out).To(Say("Buildpack:\\s+some-buildpack"))
   224  						Expect(testUI.Out).To(Say(""))
   225  						Expect(testUI.Out).To(Say("There are no running instances of this app"))
   226  
   227  						Expect(testUI.Err).To(Say("app-summary-warning"))
   228  					})
   229  
   230  					It("should not display the instance table", func() {
   231  						Expect(testUI.Out).NotTo(Say("State\\s+Since\\s+CPU\\s+Memory\\s+Disk"))
   232  					})
   233  				})
   234  
   235  				Context("when the app has running instances", func() {
   236  					BeforeEach(func() {
   237  						applicationSummary.RunningInstances = []v2action.ApplicationInstanceWithStats{
   238  							{
   239  								ID:          0,
   240  								State:       v2action.ApplicationInstanceState(ccv2.ApplicationInstanceRunning),
   241  								Since:       1403140717.984577,
   242  								CPU:         0.73,
   243  								Disk:        50 * bytefmt.MEGABYTE,
   244  								DiskQuota:   2048 * bytefmt.MEGABYTE,
   245  								Memory:      100 * bytefmt.MEGABYTE,
   246  								MemoryQuota: 128 * bytefmt.MEGABYTE,
   247  								Details:     "info from the backend",
   248  							},
   249  							{
   250  								ID:          1,
   251  								State:       v2action.ApplicationInstanceState(ccv2.ApplicationInstanceCrashed),
   252  								Since:       1403100000.900000,
   253  								CPU:         0.37,
   254  								Disk:        50 * bytefmt.MEGABYTE,
   255  								DiskQuota:   2048 * bytefmt.MEGABYTE,
   256  								Memory:      100 * bytefmt.MEGABYTE,
   257  								MemoryQuota: 128 * bytefmt.MEGABYTE,
   258  								Details:     "potato",
   259  							},
   260  						}
   261  						fakeActor.GetApplicationSummaryByNameAndSpaceReturns(applicationSummary, warnings, nil)
   262  					})
   263  
   264  					It("displays app summary, instance table, and all warnings", func() {
   265  						Expect(testUI.Out).To(Say("Showing health and status for app some-app in org some-org / space some-space as some-user..."))
   266  						Expect(testUI.Out).To(Say(""))
   267  						Expect(testUI.Out).To(Say("Name:\\s+some-app"))
   268  						Expect(testUI.Out).To(Say("Requested state:\\s+started"))
   269  						Expect(testUI.Out).To(Say("Instances:\\s+2\\/3"))
   270  						Expect(testUI.Out).To(Say("Usage:\\s+128M x 3 instances"))
   271  						Expect(testUI.Out).To(Say("Routes:\\s+banana.fruit.com/hi, foobar.com:13"))
   272  						Expect(testUI.Out).To(Say("Last uploaded:\\s+1970-01-01T00:00:00Z"))
   273  						Expect(testUI.Out).To(Say("Stack:\\s+potatos"))
   274  						Expect(testUI.Out).To(Say("Buildpack:\\s+some-buildpack"))
   275  						Expect(testUI.Out).To(Say(""))
   276  						Expect(testUI.Out).To(Say("State\\s+Since\\s+CPU\\s+Memory\\s+Disk\\s+Details"))
   277  						Expect(testUI.Out).To(Say(`#0\s+running\s+2014-06-19T01:18:37Z\s+73.0%\s+100M of 128M\s+50M of 2G\s+info from the backend`))
   278  						Expect(testUI.Out).To(Say(`#1\s+crashed\s+2014-06-18T14:00:00Z\s+37.0%\s+100M of 128M\s+50M of 2G\s+potato`))
   279  
   280  						Expect(testUI.Err).To(Say("app-summary-warning"))
   281  
   282  						Expect(fakeActor.GetApplicationSummaryByNameAndSpaceCallCount()).To(Equal(1))
   283  						appName, spaceGUID := fakeActor.GetApplicationSummaryByNameAndSpaceArgsForCall(0)
   284  						Expect(appName).To(Equal("some-app"))
   285  						Expect(spaceGUID).To(Equal("some-space-guid"))
   286  					})
   287  				})
   288  			})
   289  
   290  			Context("when an error is encountered getting app summary", func() {
   291  				Context("when the error is not translatable", func() {
   292  					var expectedErr error
   293  
   294  					BeforeEach(func() {
   295  						expectedErr = errors.New("get app summary error")
   296  						fakeActor.GetApplicationSummaryByNameAndSpaceReturns(
   297  							v2action.ApplicationSummary{},
   298  							nil,
   299  							expectedErr)
   300  					})
   301  
   302  					It("returns the error", func() {
   303  						Expect(executeErr).To(MatchError(expectedErr))
   304  					})
   305  				})
   306  
   307  				Context("when the error is translatable", func() {
   308  					BeforeEach(func() {
   309  						fakeActor.GetApplicationSummaryByNameAndSpaceReturns(
   310  							v2action.ApplicationSummary{},
   311  							nil,
   312  							v2action.ApplicationNotFoundError{Name: "some-app"})
   313  					})
   314  
   315  					It("returns a translatable error", func() {
   316  						Expect(executeErr).To(MatchError(command.ApplicationNotFoundError{Name: "some-app"}))
   317  					})
   318  				})
   319  			})
   320  		})
   321  	})
   322  })