flamingo.me/flamingo-commerce/v3@v3.11.0/test/integrationtest/helper.go (about) 1 package integrationtest 2 3 import ( 4 "context" 5 "fmt" 6 "log" 7 "net" 8 "net/http" 9 "net/url" 10 "os" 11 "strconv" 12 "sync" 13 "time" 14 15 "flamingo.me/dingo" 16 "github.com/gavv/httpexpect/v2" 17 18 "flamingo.me/flamingo/v3" 19 "flamingo.me/flamingo/v3/framework/config" 20 flamingoFramework "flamingo.me/flamingo/v3/framework/flamingo" 21 "flamingo.me/flamingo/v3/framework/web" 22 ) 23 24 type ( 25 testModule struct { 26 eventRouter flamingoFramework.EventRouter 27 router *web.Router 28 server *http.Server 29 } 30 31 //BootupInfo about the booted app 32 BootupInfo struct { 33 ShutdownFunc func() 34 Application *flamingo.Application 35 BaseURL string 36 Running chan struct{} 37 } 38 ) 39 40 // Side effect vars to get status and exchange stuff with the testModule 41 var rw sync.Mutex 42 43 var additionalConfig config.Map 44 45 // Configure for your testModule in the app 46 func (t *testModule) Inject(eventRouter flamingoFramework.EventRouter, router *web.Router) { 47 t.eventRouter = eventRouter 48 t.router = router 49 } 50 51 // Configure for your testModule in the app 52 func (t *testModule) Configure(i *dingo.Injector) { 53 flamingoFramework.BindEventSubscriber(i).To(t) 54 } 55 56 // Notify gets notified by event router 57 func (t *testModule) Notify(_ context.Context, event flamingoFramework.Event) { 58 switch event.(type) { 59 case *flamingoFramework.ShutdownEvent: 60 log.Printf("ShutdownEvent event received...") 61 } 62 } 63 64 // DefaultConfig of test module 65 func (t *testModule) DefaultConfig() config.Map { 66 return additionalConfig 67 } 68 69 // shutdown until 70 func (t *testModule) shutdownServer() { 71 log.Printf("Trigger ServerShutdownEvent...") 72 t.eventRouter.Dispatch(context.Background(), &flamingoFramework.ServerShutdownEvent{}) 73 _ = t.server.Shutdown(context.Background()) 74 } 75 76 // returns the port or error 77 func (t *testModule) startServer(listenAndServeQuited chan struct{}) (string, error) { 78 port := os.Getenv("INTEGRATION_TEST_PORT") 79 if port == "" { 80 port = "0" 81 } 82 83 t.eventRouter.Dispatch(context.Background(), &flamingoFramework.ServerStartEvent{}) 84 t.server = &http.Server{ 85 Addr: ":" + port, 86 } 87 88 t.server.Handler = t.router.Handler() 89 listener, err := net.Listen("tcp", t.server.Addr) 90 if err != nil { 91 return "", err 92 } 93 94 listenerPort := listener.Addr().(*net.TCPAddr).Port 95 96 log.Printf("startServer on port %v", listenerPort) 97 go func() { 98 _ = t.server.Serve(listener) 99 listenAndServeQuited <- struct{}{} 100 }() 101 return strconv.Itoa(listenerPort), nil 102 } 103 104 // Bootup flamingo app with the given modules (and the config in folder given ) 105 func Bootup(modules []dingo.Module, configDir string, config config.Map) BootupInfo { 106 if configDir != "" { 107 if _, err := os.Stat(configDir); os.IsNotExist(err) { 108 panic("configdir: " + configDir + " does not exist") 109 } 110 } 111 rw.Lock() 112 defer rw.Unlock() 113 //add testModule that listens 114 modules = append(modules, new(testModule)) 115 //rootArea := rootArea("config") 116 if len(os.Args) > 1 { 117 os.Args[1] = "serve" 118 } 119 additionalConfig = config 120 121 application, err := flamingo.NewApplication(modules, flamingo.ConfigDir(configDir)) 122 if err != nil { 123 panic(fmt.Sprintf("unable to get flamingo application: %v", err)) 124 } 125 126 testModuleInterface, err := application.ConfigArea().Injector.GetInstance(new(testModule)) 127 testModule := testModuleInterface.(*testModule) 128 if err != nil { 129 panic("unable to get testModule in flamingo execution area") 130 } 131 listenAndServeQuited := make(chan struct{}) 132 port, err := testModule.startServer(listenAndServeQuited) 133 if err != nil { 134 panic(err) 135 } 136 137 time.Sleep(1 * time.Second) 138 139 return BootupInfo{ 140 func() { 141 testModule.shutdownServer() 142 }, 143 application, 144 "localhost:" + port, 145 listenAndServeQuited, 146 } 147 } 148 149 // NewHTTPExpectWithCookies returns a new Expect object without printer with preset cookies to the base URL 150 func NewHTTPExpectWithCookies(testingTB httpexpect.TestingTB, baseURL string, cookies map[string]string) *httpexpect.Expect { 151 cookieJar := httpexpect.NewCookieJar() 152 parse, err := url.Parse(baseURL) 153 if err != nil { 154 testingTB.Errorf(err.Error()) 155 } 156 theCookies := make([]*http.Cookie, 0, len(cookies)) 157 for key, value := range cookies { 158 theCookies = append(theCookies, &http.Cookie{Name: key, Value: value}) 159 } 160 161 cookieJar.SetCookies(parse, theCookies) 162 163 return httpexpect.WithConfig(httpexpect.Config{ 164 BaseURL: baseURL, 165 Client: &http.Client{ 166 Jar: cookieJar, 167 }, 168 Reporter: httpexpect.NewAssertReporter(testingTB), 169 Printers: nil, 170 }) 171 } 172 173 // NewHTTPExpect returns a new Expect object without printer 174 func NewHTTPExpect(tb httpexpect.TestingTB, baseURL string) *httpexpect.Expect { 175 return NewHTTPExpectWithCookies(tb, baseURL, nil) 176 }