| // Copyright 2015 The Go Authors. All rights reserved. |
| // |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file or at |
| // https://developers.google.com/open-source/licenses/bsd. |
| |
| package talksapp |
| |
| import ( |
| "context" |
| "fmt" |
| "net/http" |
| "net/http/httptest" |
| "net/url" |
| "strings" |
| "testing" |
| "time" |
| |
| "google.golang.org/appengine" |
| "google.golang.org/appengine/aetest" |
| "google.golang.org/appengine/memcache" |
| |
| "github.com/golang/gddo/gosrc" |
| ) |
| |
| const importPath = "github.com/user/repo/path/to/presentation.slide" |
| |
| func TestHome(t *testing.T) { |
| do(t, "GET", "/", func(r *http.Request) { |
| w := httptest.NewRecorder() |
| handlerFunc(serveRoot).ServeHTTP(w, r) |
| |
| if w.Code != http.StatusOK { |
| t.Fatalf("expected status: %d, got: %d", http.StatusOK, w.Code) |
| } |
| |
| if !strings.Contains(w.Body.String(), "talks.godoc.org") { |
| t.Fatal("expected response to contain: talks.godoc.org") |
| } |
| }) |
| } |
| |
| func TestPresentation(t *testing.T) { |
| presentationTitle := "My awesome presentation!" |
| presentationSrc := []byte(presentationTitle + ` |
| |
| Subtitle |
| |
| * Slide 1 |
| |
| - Foo |
| - Bar |
| - Baz |
| `) |
| |
| originalGetPresentation := getPresentation |
| getPresentation = func(ctx context.Context, client *http.Client, importPath string) (*gosrc.Presentation, error) { |
| return &gosrc.Presentation{ |
| Filename: "presentation.slide", |
| Files: map[string][]byte{ |
| "presentation.slide": presentationSrc, |
| }, |
| }, nil |
| } |
| defer func() { |
| getPresentation = originalGetPresentation |
| }() |
| |
| do(t, "GET", "/"+importPath, func(r *http.Request) { |
| w := httptest.NewRecorder() |
| handlerFunc(serveRoot).ServeHTTP(w, r) |
| |
| if w.Code != http.StatusOK { |
| t.Fatalf("expected status: %d, got: %d", http.StatusOK, w.Code) |
| } |
| |
| if !strings.Contains(w.Body.String(), presentationTitle) { |
| t.Fatalf("unexpected response body: %s", w.Body) |
| } |
| |
| c := appengine.NewContext(r) |
| _, err := memcache.Get(c, importPath) |
| |
| if err == memcache.ErrCacheMiss { |
| t.Fatal("expected result to be cached") |
| } |
| |
| if err != nil { |
| t.Fatalf("expected no error, got: %s", err) |
| } |
| }) |
| } |
| |
| func TestPresentationCacheHit(t *testing.T) { |
| do(t, "GET", "/"+importPath, func(r *http.Request) { |
| cachedPresentation := "<div>My Presentation</div>" |
| |
| c := appengine.NewContext(r) |
| memcache.Add(c, &memcache.Item{ |
| Key: importPath, |
| Value: []byte(cachedPresentation), |
| Expiration: time.Hour, |
| }) |
| |
| w := httptest.NewRecorder() |
| handlerFunc(serveRoot).ServeHTTP(w, r) |
| |
| if w.Code != http.StatusOK { |
| t.Fatalf("expected status: %d, got: %d", http.StatusOK, w.Code) |
| } |
| |
| if w.Body.String() != cachedPresentation { |
| t.Fatal("response does not matched cached presentation") |
| } |
| }) |
| } |
| |
| func TestPresentationNotFound(t *testing.T) { |
| originalGetPresentation := getPresentation |
| getPresentation = func(ctx context.Context, client *http.Client, importPath string) (*gosrc.Presentation, error) { |
| return nil, gosrc.NotFoundError{} |
| } |
| defer func() { |
| getPresentation = originalGetPresentation |
| }() |
| |
| do(t, "GET", "/"+importPath, func(r *http.Request) { |
| w := httptest.NewRecorder() |
| handlerFunc(serveRoot).ServeHTTP(w, r) |
| |
| if w.Code != http.StatusBadRequest { |
| t.Fatalf("expected status: %d, got: %d", http.StatusBadRequest, w.Code) |
| } |
| }) |
| } |
| |
| func TestWrongMethod(t *testing.T) { |
| do(t, "POST", "/", func(r *http.Request) { |
| w := httptest.NewRecorder() |
| handlerFunc(serveRoot).ServeHTTP(w, r) |
| |
| if w.Code != http.StatusMethodNotAllowed { |
| t.Fatalf("expected status %d", http.StatusMethodNotAllowed) |
| } |
| }) |
| } |
| |
| func TestCompile(t *testing.T) { |
| version := "2" |
| body := ` |
| package main |
| |
| import "fmt" |
| |
| func main() { |
| fmt.fmtPrintln("Hello, playground") |
| } |
| ` |
| responseJSON := `{"Errors":"","Events":[{"Message":"Hello, playground\n","Kind":"stdout","Delay":0}]}` |
| |
| server := httptest.NewServer( |
| http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { |
| formVersion := r.FormValue("version") |
| formBody := r.FormValue("body") |
| |
| if formVersion != version { |
| t.Fatalf("expected version sent to play.golang.org to be: %s, was: %s", version, formVersion) |
| } |
| |
| if formBody != body { |
| t.Fatalf("expected body sent to play.golang.org to be: %s, was: %s", body, formBody) |
| } |
| |
| w.Header().Set("Content-Type", "application/json") |
| w.WriteHeader(200) |
| |
| fmt.Fprintln(w, responseJSON) |
| }), |
| ) |
| defer server.Close() |
| |
| defer func(old string) { playCompileURL = old }(playCompileURL) |
| playCompileURL = server.URL |
| |
| do(t, "POST", "/compile", func(r *http.Request) { |
| r.PostForm = url.Values{ |
| "version": []string{version}, |
| "body": []string{body}, |
| } |
| |
| w := httptest.NewRecorder() |
| handlerFunc(serveCompile).ServeHTTP(w, r) |
| |
| if w.Code != http.StatusOK { |
| t.Fatalf("expected status: %d, got: %d", http.StatusOK, w.Code) |
| } |
| |
| contentType := w.Header().Get("Content-Type") |
| if w.Header().Get("Content-Type") != "application/json" { |
| t.Fatalf("unexpected Content-Type: %s", contentType) |
| } |
| |
| if strings.TrimSpace(w.Body.String()) != responseJSON { |
| t.Fatalf("unexpected response body: %s", w.Body) |
| } |
| }) |
| } |
| |
| func TestBot(t *testing.T) { |
| do(t, "GET", "/bot.html", func(r *http.Request) { |
| w := httptest.NewRecorder() |
| handlerFunc(serveBot).ServeHTTP(w, r) |
| |
| if w.Code != http.StatusOK { |
| t.Fatalf("expected status: %d, got: %d", http.StatusOK, w.Code) |
| } |
| |
| if !strings.Contains(w.Body.String(), contactEmail) { |
| t.Fatalf("expected body to contain %s", contactEmail) |
| } |
| }) |
| } |
| |
| func do(t *testing.T, method, path string, f func(*http.Request)) { |
| i, err := aetest.NewInstance(nil) |
| if err != nil { |
| t.Fatal(err) |
| } |
| defer i.Close() |
| |
| r, err := i.NewRequest(method, path, nil) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| f(r) |
| } |