github.com/nimakaviani/cli@v6.37.1-0.20180619223813-e734901a73fa+incompatible/actor/pushaction/actualize_test.go (about) 1 package pushaction_test 2 3 import ( 4 "errors" 5 "time" 6 7 . "code.cloudfoundry.org/cli/actor/pushaction" 8 "code.cloudfoundry.org/cli/actor/pushaction/pushactionfakes" 9 "code.cloudfoundry.org/cli/actor/v3action" 10 11 . "github.com/onsi/ginkgo" 12 . "github.com/onsi/gomega" 13 . "github.com/onsi/gomega/gstruct" 14 ) 15 16 func actualizedStreamsDrainedAndClosed( 17 configStream <-chan PushState, 18 eventStream <-chan Event, 19 warningsStream <-chan Warnings, 20 errorStream <-chan error, 21 ) bool { 22 var configStreamClosed, eventStreamClosed, warningsStreamClosed, errorStreamClosed bool 23 for { 24 select { 25 case _, ok := <-configStream: 26 if !ok { 27 configStreamClosed = true 28 } 29 case _, ok := <-eventStream: 30 if !ok { 31 eventStreamClosed = true 32 } 33 case _, ok := <-warningsStream: 34 if !ok { 35 warningsStreamClosed = true 36 } 37 case _, ok := <-errorStream: 38 if !ok { 39 errorStreamClosed = true 40 } 41 } 42 if configStreamClosed && eventStreamClosed && warningsStreamClosed && errorStreamClosed { 43 break 44 } 45 } 46 return true 47 } 48 49 // TODO: for refactor: We can use the following style of code to validate that 50 // each event is received in a specific order 51 52 // Expect(nextEvent()).Should(Equal(SettingUpApplication)) 53 // Expect(nextEvent()).Should(Equal(CreatingApplication)) 54 // Expect(nextEvent()).Should(Equal(...)) 55 // Expect(nextEvent()).Should(Equal(...)) 56 // Expect(nextEvent()).Should(Equal(...)) 57 func getNextEvent(c <-chan PushState, e <-chan Event, w <-chan Warnings) func() Event { 58 timeOut := time.Tick(500 * time.Millisecond) 59 60 return func() Event { 61 for { 62 select { 63 case <-c: 64 case event, ok := <-e: 65 if ok { 66 return event 67 } 68 return "" 69 case <-w: 70 case <-timeOut: 71 return "" 72 } 73 } 74 } 75 } 76 77 var _ = Describe("Actualize", func() { 78 var ( 79 actor *Actor 80 fakeV2Actor *pushactionfakes.FakeV2Actor 81 fakeV3Actor *pushactionfakes.FakeV3Actor 82 fakeSharedActor *pushactionfakes.FakeSharedActor 83 84 state PushState 85 fakeProgressBar *pushactionfakes.FakeProgressBar 86 87 stateStream <-chan PushState 88 eventStream <-chan Event 89 warningsStream <-chan Warnings 90 errorStream <-chan error 91 ) 92 93 BeforeEach(func() { 94 fakeV2Actor = new(pushactionfakes.FakeV2Actor) 95 fakeV3Actor = new(pushactionfakes.FakeV3Actor) 96 fakeSharedActor = new(pushactionfakes.FakeSharedActor) 97 actor = NewActor(fakeV2Actor, fakeV3Actor, fakeSharedActor) 98 99 fakeProgressBar = new(pushactionfakes.FakeProgressBar) 100 state = PushState{ 101 Application: v3action.Application{ 102 Name: "some-app", 103 }, 104 SpaceGUID: "some-space-guid", 105 } 106 }) 107 108 AfterEach(func() { 109 Eventually(actualizedStreamsDrainedAndClosed(stateStream, eventStream, warningsStream, errorStream)).Should(BeTrue()) 110 }) 111 112 JustBeforeEach(func() { 113 stateStream, eventStream, warningsStream, errorStream = actor.Actualize(state, fakeProgressBar) 114 }) 115 116 Describe("application creation", func() { 117 Context("when the application exists", func() { 118 BeforeEach(func() { 119 state.Application.GUID = "some-app-guid" 120 }) 121 122 It("returns a skipped app creation event", func() { 123 Eventually(getNextEvent(stateStream, eventStream, warningsStream)).Should(Equal(SkipingApplicationCreation)) 124 125 Eventually(stateStream).Should(Receive(MatchFields(IgnoreExtras, 126 Fields{ 127 "Application": Equal(v3action.Application{ 128 Name: "some-app", 129 GUID: "some-app-guid", 130 }), 131 }))) 132 133 Consistently(fakeV3Actor.CreateApplicationInSpaceCallCount).Should(Equal(0)) 134 }) 135 }) 136 137 Context("when the application does not exist", func() { 138 Context("when the creation is successful", func() { 139 var expectedApp v3action.Application 140 141 BeforeEach(func() { 142 expectedApp = v3action.Application{ 143 GUID: "some-app-guid", 144 Name: "some-app", 145 } 146 147 fakeV3Actor.CreateApplicationInSpaceReturns(expectedApp, v3action.Warnings{"some-app-warnings"}, nil) 148 }) 149 150 It("returns an app created event, warnings, and updated state", func() { 151 Eventually(warningsStream).Should(Receive(ConsistOf("some-app-warnings"))) 152 Eventually(getNextEvent(stateStream, eventStream, warningsStream)).Should(Equal(CreatedApplication)) 153 Eventually(stateStream).Should(Receive(MatchFields(IgnoreExtras, 154 Fields{ 155 "Application": Equal(expectedApp), 156 }))) 157 }) 158 159 It("creates the application", func() { 160 Eventually(fakeV3Actor.CreateApplicationInSpaceCallCount).Should(Equal(1)) 161 passedApp, passedSpaceGUID := fakeV3Actor.CreateApplicationInSpaceArgsForCall(0) 162 Expect(passedApp).To(Equal(state.Application)) 163 Expect(passedSpaceGUID).To(Equal(state.SpaceGUID)) 164 }) 165 }) 166 167 Context("when the creation errors", func() { 168 var expectedErr error 169 170 BeforeEach(func() { 171 expectedErr = errors.New("SPICY!!") 172 173 fakeV3Actor.CreateApplicationInSpaceReturns(v3action.Application{}, v3action.Warnings{"some-app-warnings"}, expectedErr) 174 }) 175 176 It("returns warnings and error", func() { 177 Eventually(warningsStream).Should(Receive(ConsistOf("some-app-warnings"))) 178 Eventually(errorStream).Should(Receive(MatchError(expectedErr))) 179 }) 180 }) 181 }) 182 }) 183 184 Context("when all operations are finished", func() { 185 It("returns a complete event", func() { 186 Eventually(getNextEvent(stateStream, eventStream, warningsStream)).Should(Equal(Complete)) 187 }) 188 }) 189 })