ความคืบหน้างาน ไฟล์ต้นฉบับ

tracker/diagram_history_test.go

package main

import (
	"encoding/json"
	"net/http/httptest"
	"os"
	"path/filepath"
	"strings"
	"testing"
)

func TestDiagramRevisionHistoryAndRestore(t *testing.T) {
	c, _ := loadUseCases("..")
	ds := &diagramStore{dir: t.TempDir()}
	first := draftDiagram(c.UC["W-49"])
	first.Nodes[0].Title = "version one"
	first, err := ds.save("W-49", first)
	if err != nil {
		t.Fatal(err)
	}
	second := first
	second.Nodes = append([]DiagramNode{}, first.Nodes...)
	second.Nodes[0].Title = "version two"
	second, err = ds.save("W-49", second)
	if err != nil {
		t.Fatal(err)
	}
	list, err := ds.revisions("W-49")
	if err != nil || len(list) != 2 {
		t.Fatal("missing history", err)
	}
	restarted := &diagramStore{dir: ds.dir}
	restored, err := restarted.restore("W-49", second.Revision, first.Revision)
	if err != nil || restored.Revision != 3 || restored.Nodes[0].Title != "version one" {
		t.Fatal("restore must create new revision", err)
	}
	list, err = restarted.revisions("W-49")
	if err != nil || len(list) != 3 || list[2].RestoredFrom != 1 {
		t.Fatal("restore lost history", err)
	}
	if _, err = restarted.restore("W-49", 2, 1); err != errDiagramConflict {
		t.Fatal("stale restore accepted")
	}
	if _, err = restarted.restore("W-49", 3, 999); err != errDiagramRevisionNotFound {
		t.Fatal("unknown revision accepted")
	}
	snapshot, err := restarted.revision("W-49", 2)
	if err != nil || snapshot.Nodes[0].Title != "version two" {
		t.Fatal("old snapshot changed", err)
	}
}

func TestDiagramHistoryPreservesExistingFile(t *testing.T) {
	c, _ := loadUseCases("..")
	d := draftDiagram(c.UC["W-49"])
	d.Revision = 7
	dir := t.TempDir()
	os.MkdirAll(filepath.Join(dir, "diagrams"), 0755)
	b, _ := json.Marshal(d)
	os.WriteFile(filepath.Join(dir, "diagrams", "W-49.json"), b, 0600)
	ds := &diagramStore{dir: dir}
	list, err := ds.revisions("W-49")
	if err != nil || len(list) != 1 || list[0].Revision != 7 {
		t.Fatal("existing revision missing", err)
	}
	d.Nodes[0].Title = "next"
	if _, err = ds.save("W-49", d); err != nil {
		t.Fatal(err)
	}
	list, err = ds.revisions("W-49")
	if err != nil || len(list) != 2 || list[0].Revision != 7 {
		t.Fatal("existing revision was overwritten", err)
	}
}

func TestDiagramHistoryHTTP(t *testing.T) {
	old := repoRoot
	repoRoot = ".."
	defer func() { repoRoot = old }()
	mux := newMux(NewStore(t.TempDir()), NewHub())
	c, _ := loadUseCases("..")
	b, _ := json.Marshal(draftDiagram(c.UC["W-49"]))
	req := httptest.NewRequest("PUT", "/api/use-cases/W-49/diagram", strings.NewReader(string(b)))
	req.Header.Set("Origin", "http://example.com")
	w := httptest.NewRecorder()
	mux.ServeHTTP(w, req)
	if w.Code != 200 {
		t.Fatal(w.Code)
	}
	for _, path := range []string{"/api/use-cases/W-49/revisions", "/api/use-cases/W-49/revisions/1"} {
		w = httptest.NewRecorder()
		mux.ServeHTTP(w, httptest.NewRequest("GET", path, nil))
		if w.Code != 200 {
			t.Fatal(path, w.Code)
		}
	}
	for _, tc := range []struct {
		origin, body string
		code         int
	}{{"http://evil.test", `{"revision":1,"target_revision":1}`, 403}, {"http://example.com", `{"revision":1,"target_revision":1}`, 200}, {"http://example.com", `{"revision":1,"target_revision":1}`, 409}, {"http://example.com", `{"revision":2,"target_revision":999}`, 404}, {"http://example.com", `{} {}`, 400}} {
		req = httptest.NewRequest("POST", "/api/use-cases/W-49/restore", strings.NewReader(tc.body))
		req.Header.Set("Origin", tc.origin)
		w = httptest.NewRecorder()
		mux.ServeHTTP(w, req)
		if w.Code != tc.code {
			t.Fatalf("restore %d expected %d: %s", w.Code, tc.code, w.Body.String())
		}
	}
}