feat: accept browser file captures
This commit is contained in:
parent
2cbf542b13
commit
df4538532f
|
|
@ -47,6 +47,7 @@ type CapturePayload struct {
|
|||
Page CapturePage `json:"page"`
|
||||
Selection *CaptureSelection `json:"selection,omitempty"`
|
||||
Link *CaptureLink `json:"link,omitempty"`
|
||||
File *CaptureFile `json:"file,omitempty"`
|
||||
Browser *CaptureBrowser `json:"browser,omitempty"`
|
||||
Context interface{} `json:"context,omitempty"`
|
||||
}
|
||||
|
|
@ -66,6 +67,13 @@ type CaptureLink struct {
|
|||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
type CaptureFile struct {
|
||||
Name string `json:"name"`
|
||||
Mime string `json:"mime"`
|
||||
Size int64 `json:"size"`
|
||||
Text string `json:"text"`
|
||||
}
|
||||
|
||||
type CaptureBrowser struct {
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
|
@ -209,7 +217,7 @@ func (p CapturePayload) Validate() error {
|
|||
if strings.TrimSpace(p.CapturedAt) == "" {
|
||||
return fmt.Errorf("capturedAt is required")
|
||||
}
|
||||
if p.Kind != "page" && p.Kind != "selection" && p.Kind != "link" {
|
||||
if p.Kind != "page" && p.Kind != "selection" && p.Kind != "link" && p.Kind != "file" {
|
||||
return fmt.Errorf("unsupported kind")
|
||||
}
|
||||
if strings.TrimSpace(p.Page.URL) == "" {
|
||||
|
|
@ -221,6 +229,12 @@ func (p CapturePayload) Validate() error {
|
|||
if p.Kind == "link" && (p.Link == nil || strings.TrimSpace(p.Link.URL) == "") {
|
||||
return fmt.Errorf("link.url is required")
|
||||
}
|
||||
if p.Kind == "file" && (p.File == nil || strings.TrimSpace(p.File.Name) == "") {
|
||||
return fmt.Errorf("file.name is required")
|
||||
}
|
||||
if p.Kind == "file" && (p.File == nil || p.File.Text == "") {
|
||||
return fmt.Errorf("file.text is required")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -250,6 +264,11 @@ func (p CapturePayload) EventPayload() map[string]interface{} {
|
|||
result["url"] = linkURL
|
||||
result["title"] = strings.TrimSpace(p.Link.Text)
|
||||
result["domain"] = captureDomain(linkURL, "")
|
||||
case "file":
|
||||
result["fileName"] = strings.TrimSpace(p.File.Name)
|
||||
result["fileMime"] = strings.TrimSpace(p.File.Mime)
|
||||
result["fileSize"] = p.File.Size
|
||||
result["fileText"] = p.File.Text
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,6 +85,69 @@ func TestReceiverAcceptsSelectionCaptureAndPublishesEvent(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestReceiverAcceptsFileCaptureAndPublishesEvent(t *testing.T) {
|
||||
bus := events.NewBus()
|
||||
received := make(chan events.Event, 1)
|
||||
bus.Subscribe("browser.capture.file", func(event events.Event) {
|
||||
received <- event
|
||||
})
|
||||
|
||||
receiver := New(bus)
|
||||
body := `{
|
||||
"schemaVersion": 1,
|
||||
"captureId": "capture-file",
|
||||
"capturedAt": "2026-06-29T02:00:00.000Z",
|
||||
"source": "verstak-browser-extension",
|
||||
"kind": "file",
|
||||
"page": {
|
||||
"url": "https://example.com/files",
|
||||
"title": "Example Files",
|
||||
"domain": "example.com"
|
||||
},
|
||||
"file": {
|
||||
"name": "notes.txt",
|
||||
"mime": "text/plain",
|
||||
"size": 11,
|
||||
"text": "hello file"
|
||||
},
|
||||
"browser": {
|
||||
"name": "Firefox"
|
||||
}
|
||||
}`
|
||||
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/browser-inbox/v1/captures", bytes.NewBufferString(body))
|
||||
rec := httptest.NewRecorder()
|
||||
|
||||
receiver.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusAccepted {
|
||||
t.Fatalf("status = %d, want %d; body=%s", rec.Code, http.StatusAccepted, rec.Body.String())
|
||||
}
|
||||
event := <-received
|
||||
if event.Name != "browser.capture.file" {
|
||||
t.Fatalf("event name = %q, want browser.capture.file", event.Name)
|
||||
}
|
||||
payload, ok := event.Payload.(map[string]interface{})
|
||||
if !ok {
|
||||
t.Fatalf("event payload type = %T, want map[string]interface{}", event.Payload)
|
||||
}
|
||||
if payload["kind"] != "file" {
|
||||
t.Fatalf("payload kind = %v, want file", payload["kind"])
|
||||
}
|
||||
if payload["fileName"] != "notes.txt" {
|
||||
t.Fatalf("payload fileName = %v, want notes.txt", payload["fileName"])
|
||||
}
|
||||
if payload["fileMime"] != "text/plain" {
|
||||
t.Fatalf("payload fileMime = %v, want text/plain", payload["fileMime"])
|
||||
}
|
||||
if payload["fileSize"] != int64(11) {
|
||||
t.Fatalf("payload fileSize = %v, want 11", payload["fileSize"])
|
||||
}
|
||||
if payload["fileText"] != "hello file" {
|
||||
t.Fatalf("payload fileText = %v, want hello file", payload["fileText"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestReceiverAnnotatesCaptureWithCurrentWorkspace(t *testing.T) {
|
||||
bus := events.NewBus()
|
||||
received := make(chan events.Event, 1)
|
||||
|
|
|
|||
Loading…
Reference in New Issue