func Test_Render_Funcs(t *testing.T) { m := martini.Classic() m.Use(Renderer(Options{ Directory: "fixtures/custom_funcs", Funcs: []template.FuncMap{ { "myCustomFunc": func() string { return "My custom function" }, }, }, })) // routing m.Get("/foobar", func(r Render) { r.HTML(200, "index", "jeremy") }) res := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/foobar", nil) m.ServeHTTP(res, req) expect(t, res.Body.String(), "My custom function\n") }
func Test_Render_NoRace(t *testing.T) { // This test used to fail if run with -race m := martini.Classic() m.Use(Renderer(Options{ Directory: "fixtures/basic", })) // routing m.Get("/foobar", func(r Render) { r.HTML(200, "hello", "world") }) done := make(chan bool) doreq := func() { res := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/foobar", nil) m.ServeHTTP(res, req) expect(t, res.Code, 200) expect(t, res.Header().Get(ContentType), ContentHTML+"; charset=UTF-8") // ContentLength should be deferred to the ResponseWriter and not Render expect(t, res.Header().Get(ContentLength), "") expect(t, res.Body.String(), "<h1>Hello world</h1>\n") done <- true } // Run two requests to check there is no race condition go doreq() go doreq() <-done <-done }
func Test_Render_Layout_Current(t *testing.T) { m := martini.Classic() m.Use(Renderer(Options{ Directory: "fixtures/basic", Layout: "current_layout", })) // routing m.Get("/foobar", func(r Render) { r.HTML(200, "content", "jeremy") }) res := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/foobar", nil) m.ServeHTTP(res, req) expect(t, res.Body.String(), "content head\n<h1>jeremy</h1>\n\ncontent foot\n") }
func Test_Render_Bad_HTML(t *testing.T) { m := martini.Classic() m.Use(Renderer(Options{ Directory: "fixtures/basic", })) // routing m.Get("/foobar", func(r Render) { r.HTML(200, "nope", nil) }) res := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/foobar", nil) m.ServeHTTP(res, req) expect(t, res.Code, 500) expect(t, res.Body.String(), "html/template: \"nope\" is undefined\n") }
func Test_Render_XML(t *testing.T) { m := martini.Classic() m.Use(Renderer(Options{ // nothing here to configure })) // routing m.Get("/foobar", func(r Render) { r.XML(300, GreetingXML{One: "hello", Two: "world"}) }) res := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/foobar", nil) m.ServeHTTP(res, req) expect(t, res.Code, 300) expect(t, res.Header().Get(ContentType), ContentXML+"; charset=UTF-8") expect(t, res.Body.String(), `<greeting one="hello" two="world"></greeting>`) }
func Test_Render_Charset_JSON(t *testing.T) { m := martini.Classic() m.Use(Renderer(Options{ Charset: "foobar", })) // routing m.Get("/foobar", func(r Render) { r.JSON(300, Greeting{"hello", "world"}) }) res := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/foobar", nil) m.ServeHTTP(res, req) expect(t, res.Code, 300) expect(t, res.Header().Get(ContentType), ContentJSON+"; charset=foobar") expect(t, res.Body.String(), `{"one":"hello","two":"world"}`) }
func Test_Render_BinaryData(t *testing.T) { m := martini.Classic() m.Use(Renderer(Options{ // nothing here to configure })) // routing m.Get("/foobar", func(r Render) { r.Data(200, []byte("hello there")) }) res := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/foobar", nil) m.ServeHTTP(res, req) expect(t, res.Code, 200) expect(t, res.Header().Get(ContentType), ContentBinary) expect(t, res.Body.String(), "hello there") }
func Test_Render_Nested_HTML(t *testing.T) { m := martini.Classic() m.Use(Renderer(Options{ Directory: "fixtures/basic", })) // routing m.Get("/foobar", func(r Render) { r.HTML(200, "admin/index", "jeremy") }) res := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/foobar", nil) m.ServeHTTP(res, req) expect(t, res.Code, 200) expect(t, res.Header().Get(ContentType), ContentHTML+"; charset=UTF-8") expect(t, res.Body.String(), "<h1>Admin jeremy</h1>\n") }
func Test_Render_JSON_Prefix(t *testing.T) { m := martini.Classic() prefix := ")]}',\n" m.Use(Renderer(Options{ PrefixJSON: []byte(prefix), })) // routing m.Get("/foobar", func(r Render) { r.JSON(300, Greeting{"hello", "world"}) }) res := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/foobar", nil) m.ServeHTTP(res, req) expect(t, res.Code, 300) expect(t, res.Header().Get(ContentType), ContentJSON+"; charset=UTF-8") expect(t, res.Body.String(), prefix+`{"one":"hello","two":"world"}`) }
func Test_Render_Delimiters(t *testing.T) { m := martini.Classic() m.Use(Renderer(Options{ Delims: Delims{"{[{", "}]}"}, Directory: "fixtures/basic", })) // routing m.Get("/foobar", func(r Render) { r.HTML(200, "delims", "jeremy") }) res := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/foobar", nil) m.ServeHTTP(res, req) expect(t, res.Code, 200) expect(t, res.Header().Get(ContentType), ContentHTML+"; charset=UTF-8") expect(t, res.Body.String(), "<h1>Hello jeremy</h1>") }
func Test_Render_Extensions(t *testing.T) { m := martini.Classic() m.Use(Renderer(Options{ Directory: "fixtures/basic", Extensions: []string{".tmpl", ".html"}, })) // routing m.Get("/foobar", func(r Render) { r.HTML(200, "hypertext", nil) }) res := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/foobar", nil) m.ServeHTTP(res, req) expect(t, res.Code, 200) expect(t, res.Header().Get(ContentType), ContentHTML+"; charset=UTF-8") expect(t, res.Body.String(), "Hypertext!\n") }
func Test_Render_Default_Charset_HTML(t *testing.T) { m := martini.Classic() m.Use(Renderer(Options{ Directory: "fixtures/basic", })) // routing m.Get("/foobar", func(r Render) { r.HTML(200, "hello", "jeremy") }) res := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/foobar", nil) m.ServeHTTP(res, req) expect(t, res.Code, 200) expect(t, res.Header().Get(ContentType), ContentHTML+"; charset=UTF-8") // ContentLength should be deferred to the ResponseWriter and not Render expect(t, res.Header().Get(ContentLength), "") expect(t, res.Body.String(), "<h1>Hello jeremy</h1>\n") }
func Test_Render_Override_Layout(t *testing.T) { m := martini.Classic() m.Use(Renderer(Options{ Directory: "fixtures/basic", Layout: "layout", })) // routing m.Get("/foobar", func(r Render) { r.HTML(200, "content", "jeremy", HTMLOptions{ Layout: "another_layout", }) }) res := httptest.NewRecorder() req, _ := http.NewRequest("GET", "/foobar", nil) m.ServeHTTP(res, req) expect(t, res.Code, 200) expect(t, res.Header().Get(ContentType), ContentHTML+"; charset=UTF-8") expect(t, res.Body.String(), "another head\n<h1>jeremy</h1>\n\nanother foot\n") }
func main() { // Add some configuration to our JSON logger spw = &spew.ConfigState{Indent: "\t", MaxDepth: 5} // load .env into os.Getenv err := godotenv.Load() if err != nil { log.Println("No .env, running in production mode, hope that's what you wanted") } creds := "" if os.Getenv("MGUSER") != "" && os.Getenv("MGPW") != "" { creds = fmt.Sprintf("%s:%s@", os.Getenv("MGUSER"), os.Getenv("MGPW")) } // connect to a mongodb session - local or through Docker session, err := mgo.DialWithTimeout( fmt.Sprintf("mongodb://%s%s/%s", creds, os.Getenv("MGHOST"), os.Getenv("MGDB")), time.Second, ) if err == nil { defer session.Close() session.SetMode(mgo.Monotonic, true) } else { log.Fatal(err) } db := session.Clone().DB(os.Getenv("MGDB")).C(os.Getenv("MGCOLL")) // Slack API client api := slack.New(os.Getenv("SLACK")) // Martini router and renderer app := martini.Classic() app.Use(render.Renderer()) // Open a connection to Slack Real Time Messaging API rtm := api.NewRTM() go rtm.ManageConnection() // expose Martini endpoints for our data app.Group("/", func(r martini.Router) { r.Get("reactions", func(r render.Render) { var result []bson.M pipe := db.Pipe( []bson.M{ { "$sort": bson.M{"eventtimestamp": 1}, }, { "$group": bson.M{ "_id": "$reaction", "reactions": bson.M{ "$push": "$$CURRENT", }, "count": bson.M{"$sum": 1}, }, }, { "$sort": bson.M{"count": -1}, }, }, ) iter := pipe.Iter() err := iter.All(&result) if err != nil { log.Println(err.Error()) r.JSON(400, bson.M{"error": err.Error()}) } else { r.JSON(200, result) } }) }) go app.Run() for { select { case msg := <-rtm.IncomingEvents: switch msg.Data.(type) { case *slack.ReactionAddedEvent: go insertReaction(msg.Data.(*slack.ReactionAddedEvent), db) case *slack.ReactionRemovedEvent: go deleteReaction(msg.Data.(*slack.ReactionRemovedEvent), db) default: continue } } } }