github.com/liamawhite/cli-with-i18n@v6.32.1-0.20171122084555-dede0a5c3448+incompatible/actor/pluginaction/uninstall_test.go (about) 1 package pluginaction_test 2 3 import ( 4 "errors" 5 "io/ioutil" 6 "os" 7 "os/exec" 8 "path/filepath" 9 10 . "github.com/liamawhite/cli-with-i18n/actor/pluginaction" 11 "github.com/liamawhite/cli-with-i18n/actor/pluginaction/pluginactionfakes" 12 "github.com/liamawhite/cli-with-i18n/util/configv3" 13 . "github.com/onsi/ginkgo" 14 . "github.com/onsi/gomega" 15 ) 16 17 var _ = Describe("Plugin actor", func() { 18 var ( 19 actor *Actor 20 fakeConfig *pluginactionfakes.FakeConfig 21 ) 22 23 BeforeEach(func() { 24 fakeConfig = new(pluginactionfakes.FakeConfig) 25 actor = NewActor(fakeConfig, nil) 26 }) 27 28 Describe("UninstallPlugin", func() { 29 var ( 30 binaryPath string 31 fakePluginUninstaller *pluginactionfakes.FakePluginUninstaller 32 pluginHome string 33 ) 34 35 BeforeEach(func() { 36 var err error 37 pluginHome, err = ioutil.TempDir("", "") 38 Expect(err).ToNot(HaveOccurred()) 39 40 binaryPath = filepath.Join(pluginHome, "banana-faceman") 41 err = ioutil.WriteFile(binaryPath, nil, 0600) 42 Expect(err).ToNot(HaveOccurred()) 43 44 fakePluginUninstaller = new(pluginactionfakes.FakePluginUninstaller) 45 }) 46 47 AfterEach(func() { 48 os.RemoveAll(pluginHome) 49 }) 50 51 Context("when the plugin does not exist", func() { 52 BeforeEach(func() { 53 fakeConfig.GetPluginReturns(configv3.Plugin{}, false) 54 }) 55 56 It("returns a PluginNotFoundError", func() { 57 err := actor.UninstallPlugin(fakePluginUninstaller, "some-non-existent-plugin") 58 Expect(err).To(MatchError(PluginNotFoundError{PluginName: "some-non-existent-plugin"})) 59 }) 60 }) 61 62 Context("when the plugin exists", func() { 63 BeforeEach(func() { 64 fakeConfig.GetPluginReturns(configv3.Plugin{ 65 Name: "some-plugin", 66 Location: binaryPath, 67 }, true) 68 }) 69 70 Context("when no errors are encountered", func() { 71 It("runs the plugin cleanup, deletes the binary and removes the plugin config", func() { 72 err := actor.UninstallPlugin(fakePluginUninstaller, "some-plugin") 73 Expect(err).ToNot(HaveOccurred()) 74 75 Expect(fakeConfig.GetPluginCallCount()).To(Equal(1)) 76 Expect(fakeConfig.GetPluginArgsForCall(0)).To(Equal("some-plugin")) 77 78 Expect(fakePluginUninstaller.RunCallCount()).To(Equal(1)) 79 path, command := fakePluginUninstaller.RunArgsForCall(0) 80 Expect(path).To(Equal(binaryPath)) 81 Expect(command).To(Equal("CLI-MESSAGE-UNINSTALL")) 82 83 _, err = os.Stat(binaryPath) 84 Expect(os.IsNotExist(err)).To(BeTrue()) 85 86 Expect(fakeConfig.RemovePluginCallCount()).To(Equal(1)) 87 Expect(fakeConfig.RemovePluginArgsForCall(0)).To(Equal("some-plugin")) 88 89 Expect(fakeConfig.WritePluginConfigCallCount()).To(Equal(1)) 90 }) 91 }) 92 93 Context("when the plugin binary does not exist", func() { 94 BeforeEach(func() { 95 Expect(os.Remove(binaryPath)).ToNot(HaveOccurred()) 96 }) 97 98 It("removes the plugin config", func() { 99 err := actor.UninstallPlugin(fakePluginUninstaller, "some-plugin") 100 Expect(err).ToNot(HaveOccurred()) 101 102 Expect(fakePluginUninstaller.RunCallCount()).To(Equal(0)) 103 104 Expect(fakeConfig.RemovePluginCallCount()).To(Equal(1)) 105 Expect(fakeConfig.RemovePluginArgsForCall(0)).To(Equal("some-plugin")) 106 107 Expect(fakeConfig.WritePluginConfigCallCount()).To(Equal(1)) 108 }) 109 }) 110 111 Context("when the plugin uninstaller returns an os.PathError", func() { 112 var expectedErr error 113 114 BeforeEach(func() { 115 expectedErr = &os.PathError{} 116 fakePluginUninstaller.RunReturns(expectedErr) 117 }) 118 119 It("returns a PluginExecuteError, deletes the binary and removes the plugin config", func() { 120 err := actor.UninstallPlugin(fakePluginUninstaller, "some-plugin") 121 Expect(err).To(MatchError(PluginExecuteError{Err: expectedErr})) 122 123 _, err = os.Stat(binaryPath) 124 Expect(os.IsNotExist(err)).To(BeTrue()) 125 126 Expect(fakeConfig.RemovePluginCallCount()).To(Equal(1)) 127 Expect(fakeConfig.WritePluginConfigCallCount()).To(Equal(1)) 128 }) 129 }) 130 131 Context("when the plugin uninstaller returns an exec.ExitError", func() { 132 var expectedErr error 133 134 BeforeEach(func() { 135 expectedErr = &exec.ExitError{} 136 fakePluginUninstaller.RunReturns(expectedErr) 137 }) 138 139 It("returns the error, deletes the binary and removes the plugin config", func() { 140 err := actor.UninstallPlugin(fakePluginUninstaller, "some-plugin") 141 Expect(err).To(MatchError(PluginExecuteError{Err: expectedErr})) 142 143 _, err = os.Stat(binaryPath) 144 Expect(os.IsNotExist(err)).To(BeTrue()) 145 146 Expect(fakeConfig.RemovePluginCallCount()).To(Equal(1)) 147 Expect(fakeConfig.WritePluginConfigCallCount()).To(Equal(1)) 148 }) 149 }) 150 151 Context("when the plugin uninstaller returns any other error", func() { 152 var expectedErr error 153 154 BeforeEach(func() { 155 expectedErr = errors.New("some error") 156 fakePluginUninstaller.RunReturns(expectedErr) 157 }) 158 159 It("returns the error and does not delete the binary or remove the plugin config", func() { 160 err := actor.UninstallPlugin(fakePluginUninstaller, "some-plugin") 161 Expect(err).To(MatchError(expectedErr)) 162 163 _, err = os.Stat(binaryPath) 164 Expect(err).ToNot(HaveOccurred()) 165 166 Expect(fakeConfig.RemovePluginCallCount()).To(Equal(0)) 167 }) 168 }) 169 170 Context("when deleting the plugin binary returns a 'file does not exist' error", func() { 171 BeforeEach(func() { 172 err := os.Remove(binaryPath) 173 Expect(err).ToNot(HaveOccurred()) 174 }) 175 176 It("does not return the error and removes the plugin config", func() { 177 err := actor.UninstallPlugin(fakePluginUninstaller, "some-plugin") 178 Expect(err).ToNot(HaveOccurred()) 179 180 Expect(fakeConfig.RemovePluginCallCount()).To(Equal(1)) 181 }) 182 }) 183 184 Context("when deleting the plugin binary returns a path error", func() { 185 BeforeEach(func() { 186 err := os.Remove(binaryPath) 187 Expect(err).ToNot(HaveOccurred()) 188 err = os.Mkdir(binaryPath, 0700) 189 Expect(err).ToNot(HaveOccurred()) 190 err = ioutil.WriteFile(filepath.Join(binaryPath, "foooooo"), nil, 0500) 191 Expect(err).ToNot(HaveOccurred()) 192 }) 193 194 It("returns the error and removes the plugin config", func() { 195 err := actor.UninstallPlugin(fakePluginUninstaller, "some-plugin") 196 pluginBinaryRemoveErr, ok := err.(PluginBinaryRemoveFailedError) 197 Expect(ok).To(BeTrue()) 198 _, isPathError := pluginBinaryRemoveErr.Err.(*os.PathError) 199 Expect(isPathError).To(BeTrue()) 200 201 Expect(fakeConfig.RemovePluginCallCount()).To(Equal(1)) 202 Expect(fakeConfig.WritePluginConfigCallCount()).To(Equal(1)) 203 }) 204 }) 205 206 Context("when writing the config returns an error", func() { 207 var expectedErr error 208 209 BeforeEach(func() { 210 expectedErr = errors.New("some plugin config write error") 211 fakeConfig.WritePluginConfigReturns(expectedErr) 212 }) 213 214 It("returns the error", func() { 215 err := actor.UninstallPlugin(fakePluginUninstaller, "some-plugin") 216 Expect(err).To(MatchError(expectedErr)) 217 }) 218 }) 219 }) 220 }) 221 })