package web_test import ( "bytes" "context" "mime/multipart" "net/http" "net/http/httptest" "net/url" "strings" "testing" "github.com/netcell-it/deklarix/internal/rules" "github.com/netcell-it/deklarix/internal/web" ) // postInsightsUpload lädt einen Insights-Screenshot für einen Beitrag hoch. func postInsightsUpload(t *testing.T, s *web.Server, cookie *http.Cookie, submissionID string, imageBytes []byte) *httptest.ResponseRecorder { t.Helper() var buf bytes.Buffer mw := multipart.NewWriter(&buf) part, err := mw.CreatePart(map[string][]string{ "Content-Disposition": {`form-data; name="insights_standbild"; filename="insights.png"`}, "Content-Type": {"image/png"}, }) if err != nil { t.Fatalf("CreatePart: %v", err) } if _, err := part.Write(imageBytes); err != nil { t.Fatalf("Write: %v", err) } if err := mw.Close(); err != nil { t.Fatalf("multipart Close: %v", err) } req := httptest.NewRequest(http.MethodPost, "/beitraege/"+submissionID+"/insights", &buf) req.Header.Set("Content-Type", mw.FormDataContentType()) req.AddCookie(cookie) w := httptest.NewRecorder() s.ServeHTTP(w, req) return w } func TestStorySubmissionShowsInsightsReminderAfterArchiving(t *testing.T) { s, fs, cookie := newAuthedTestServer(t, fakeExtractor{facts: rules.Facts{ Platform: "instagram", Jurisdiction: "DE", Consideration: rules.ConsiderationNone, }, raw: []byte(`{"gegenleistung":"keine","kennzeichnung_vorhanden":false,"kennzeichnung_wortlaut":"","kennzeichnung_vor_kuerzung":false}`)}) subID := checkAndReturnSubID2(t, s, cookie, "story") archiveResp := postForm(t, s, cookie, "/veroeffentlichen", url.Values{"submission_id": {subID}}) if archiveResp.Code != http.StatusOK { t.Fatalf("archive status = %d, body: %s", archiveResp.Code, archiveResp.Body.String()) } detailResp := getWithCookie(t, s, cookie, "/beitraege/"+subID) if detailResp.Code != http.StatusOK { t.Fatalf("detail status = %d, body: %s", detailResp.Code, detailResp.Body.String()) } body := detailResp.Body.String() if !strings.Contains(body, "Insights jetzt sichern") { t.Errorf("expected an insights reminder for a freshly archived story, got: %s", body) } _ = fs } func TestInsightsUploadClearsReminder(t *testing.T) { s, _, cookie := newAuthedTestServer(t, fakeExtractor{facts: rules.Facts{ Platform: "instagram", Jurisdiction: "DE", Consideration: rules.ConsiderationNone, }, raw: []byte(`{"gegenleistung":"keine","kennzeichnung_vorhanden":false,"kennzeichnung_wortlaut":"","kennzeichnung_vor_kuerzung":false}`)}) subID := checkAndReturnSubID2(t, s, cookie, "story") if resp := postForm(t, s, cookie, "/veroeffentlichen", url.Values{"submission_id": {subID}}); resp.Code != http.StatusOK { t.Fatalf("archive status = %d, body: %s", resp.Code, resp.Body.String()) } uploadResp := postInsightsUpload(t, s, cookie, subID, tinyPNG) if uploadResp.Code != http.StatusSeeOther { t.Fatalf("insights upload status = %d, want 303, body: %s", uploadResp.Code, uploadResp.Body.String()) } detailResp := getWithCookie(t, s, cookie, "/beitraege/"+subID) body := detailResp.Body.String() if strings.Contains(body, "Insights jetzt sichern") { t.Errorf("expected the reminder to be gone after securing insights, got: %s", body) } if !strings.Contains(body, "Gesicherte Insights-Nachweise") { t.Errorf("expected the secured insights section, got: %s", body) } } func TestInsightsUploadRejectsForeignSubmission(t *testing.T) { fs := newFakeStore() s := newServer(t, fakeExtractor{facts: rules.Facts{ Platform: "instagram", Jurisdiction: "DE", Consideration: rules.ConsiderationNone, }}, fs) cookieA := seedAccount(t, fs, "Mandant A", "a@example.com") cookieB := seedAccount(t, fs, "Mandant B", "b@example.com") subID := checkAndReturnSubID2(t, s, cookieA, "story") resp := postInsightsUpload(t, s, cookieB, subID, tinyPNG) if resp.Code != http.StatusNotFound { t.Fatalf("cross-tenant insights upload status = %d, want 404", resp.Code) } if _, err := fs.GetLatestAssetForSubmission(context.Background(), subID); err == nil { t.Fatal("expected no asset from a rejected cross-tenant upload") } } // checkAndReturnSubID2 ist checkAndReturnSubID mit ueberschreibbarem post_type. func checkAndReturnSubID2(t *testing.T, s interface { ServeHTTP(w http.ResponseWriter, r *http.Request) }, cookie *http.Cookie, postType string) string { t.Helper() form := checkForm("post_type", postType) req := httptest.NewRequest(http.MethodPost, "/pruefen", strings.NewReader(form.Encode())) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") req.AddCookie(cookie) w := httptest.NewRecorder() s.ServeHTTP(w, req) if w.Code != http.StatusOK { t.Fatalf("check status = %d, body: %s", w.Code, w.Body.String()) } body := w.Body.String() const marker = `name="submission_id" value="` idx := strings.Index(body, marker) if idx == -1 { t.Fatalf("expected a submission_id field in the result, got: %s", body) } rest := body[idx+len(marker):] return rest[:strings.Index(rest, `"`)] }