feat: implémentation complete v0.1.0 — daemon de sync clipboard bidirectionnel
CI / Lint (push) Failing after 14m46s
CI / Test (push) Failing after 4m23s
CI / Build (darwin/amd64) (push) Skipped
CI / Build (linux/amd64) (push) Skipped
CI / Build (windows/amd64) (push) Skipped
CI / Build (darwin/arm64) (push) Skipped
CI / Build (linux/arm64) (push) Skipped
CI / Build (windows/arm64) (push) Skipped
CI / Release (push) Skipped
CI / Lint (push) Failing after 14m46s
CI / Test (push) Failing after 4m23s
CI / Build (darwin/amd64) (push) Skipped
CI / Build (linux/amd64) (push) Skipped
CI / Build (windows/amd64) (push) Skipped
CI / Build (darwin/arm64) (push) Skipped
CI / Build (linux/arm64) (push) Skipped
CI / Build (windows/arm64) (push) Skipped
CI / Release (push) Skipped
This commit is contained in:
@@ -0,0 +1,133 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"git.dracodev.net/Projets/clip-sync/internal/dedup"
|
||||
)
|
||||
|
||||
// mockClipboard is an in-memory clipboard for testing.
|
||||
type mockClipboard struct {
|
||||
text string
|
||||
}
|
||||
|
||||
func (m *mockClipboard) Read() (string, error) { return m.text, nil }
|
||||
func (m *mockClipboard) Write(s string) error { m.text = s; return nil }
|
||||
|
||||
func TestHandleClipAcceptsValidPayload(t *testing.T) {
|
||||
cb := &mockClipboard{}
|
||||
filter := dedup.NewFilter("my-machine")
|
||||
srv := New(":0", cb, filter)
|
||||
|
||||
payload := dedup.Payload{
|
||||
Text: "test text",
|
||||
Ts: 1690000000000000000,
|
||||
Origin: "other-machine",
|
||||
}
|
||||
body, _ := json.Marshal(payload)
|
||||
|
||||
req := httptest.NewRequest(http.MethodPost, "/clip", bytes.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
srv.handleClip(w, req)
|
||||
|
||||
if w.Code != http.StatusNoContent {
|
||||
t.Errorf("status = %d, want %d", w.Code, http.StatusNoContent)
|
||||
}
|
||||
if cb.text != "test text" {
|
||||
t.Errorf("clipboard = %q, want \"test text\"", cb.text)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleClipIgnoresEcho(t *testing.T) {
|
||||
cb := &mockClipboard{text: "existing"}
|
||||
filter := dedup.NewFilter("my-machine")
|
||||
|
||||
// Simulate we just wrote "echo text" locally.
|
||||
filter.MarkWritten("echo text")
|
||||
|
||||
srv := New(":0", cb, filter)
|
||||
|
||||
payload := dedup.Payload{
|
||||
Text: "echo text", // same text we just wrote
|
||||
Ts: 1690000000000000000,
|
||||
Origin: "other-machine",
|
||||
}
|
||||
body, _ := json.Marshal(payload)
|
||||
|
||||
req := httptest.NewRequest(http.MethodPost, "/clip", bytes.NewReader(body))
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
srv.handleClip(w, req)
|
||||
|
||||
if w.Code != http.StatusNoContent {
|
||||
t.Errorf("status = %d, want %d", w.Code, http.StatusNoContent)
|
||||
}
|
||||
// Clipboard should NOT be overwritten.
|
||||
if cb.text != "existing" {
|
||||
t.Errorf("clipboard = %q, want \"existing\" (should not be overwritten)", cb.text)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleClipRejectsInvalidMethod(t *testing.T) {
|
||||
cb := &mockClipboard{}
|
||||
filter := dedup.NewFilter("my-machine")
|
||||
srv := New(":0", cb, filter)
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/clip", nil)
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
srv.handleClip(w, req)
|
||||
|
||||
if w.Code != http.StatusMethodNotAllowed {
|
||||
t.Errorf("status = %d, want %d", w.Code, http.StatusMethodNotAllowed)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleClipRejectsEmptyText(t *testing.T) {
|
||||
cb := &mockClipboard{}
|
||||
filter := dedup.NewFilter("my-machine")
|
||||
srv := New(":0", cb, filter)
|
||||
|
||||
payload := dedup.Payload{
|
||||
Text: "",
|
||||
Ts: 1690000000000000000,
|
||||
Origin: "other-machine",
|
||||
}
|
||||
body, _ := json.Marshal(payload)
|
||||
|
||||
req := httptest.NewRequest(http.MethodPost, "/clip", bytes.NewReader(body))
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
srv.handleClip(w, req)
|
||||
|
||||
if w.Code != http.StatusBadRequest {
|
||||
t.Errorf("status = %d, want %d", w.Code, http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleClipRejectsInvalidJSON(t *testing.T) {
|
||||
cb := &mockClipboard{}
|
||||
filter := dedup.NewFilter("my-machine")
|
||||
srv := New(":0", cb, filter)
|
||||
|
||||
req := httptest.NewRequest(http.MethodPost, "/clip", bytes.NewReader([]byte("not json")))
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
srv.handleClip(w, req)
|
||||
|
||||
if w.Code != http.StatusBadRequest {
|
||||
t.Errorf("status = %d, want %d", w.Code, http.StatusBadRequest)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
// Ensure clipboard.New() won't be called in test (mock is used directly).
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
Reference in New Issue
Block a user