marky

Lightweight bookmarking + plaintext archive
Log | Files | Refs | README | LICENSE

database_test.go (4169B)


      1 package internal
      2 
      3 import (
      4 	"context"
      5 	"strings"
      6 	"testing"
      7 )
      8 
      9 func TestMigrationsCRUDAndSearch(t *testing.T) {
     10 	t.Parallel()
     11 	ctx := context.Background()
     12 	dir := t.TempDir()
     13 	path := dir + "/test.db"
     14 
     15 	db, err := OpenAtPath(ctx, path)
     16 	if err != nil {
     17 		t.Fatalf("open db: %v", err)
     18 	}
     19 	defer db.Close()
     20 
     21 	// Create user
     22 	uid := int64(1)
     23 	_, err = db.sql.ExecContext(ctx, `INSERT INTO users(id, username, encrypted_password, api_token, created_at, updated_at) VALUES(1, 'tester', 'x', 'tok', strftime('%Y-%m-%dT%H:%M:%fZ','now'), strftime('%Y-%m-%dT%H:%M:%fZ','now'))`)
     24 	if err != nil {
     25 		t.Fatalf("insert user: %v", err)
     26 	}
     27 	// Create with archive content
     28 	b, err := db.CreateBookmarkWithArchive(ctx, uid, "http://example.local/1", "Example 1", nil, false, "The city of Durham has great food.")
     29 	if err != nil {
     30 		t.Fatalf("create with archive: %v", err)
     31 	}
     32 	if b.ID == 0 {
     33 		t.Fatalf("expected id > 0")
     34 	}
     35 
     36 	// Archive present
     37 	content, _, ok, err := db.GetArchive(ctx, b.ID)
     38 	if err != nil || !ok {
     39 		t.Fatalf("get archive: ok=%v err=%v", ok, err)
     40 	}
     41 	if !strings.Contains(strings.ToLower(content), "durham") {
     42 		t.Fatalf("expected archive to contain durham, got: %q", content)
     43 	}
     44 
     45 	// Search with excerpt
     46 	hits, err := db.SearchBookmarksWithExcerpt(ctx, uid, "durham", 10, 0)
     47 	if err != nil {
     48 		t.Fatalf("search: %v", err)
     49 	}
     50 	if len(hits) != 1 {
     51 		t.Fatalf("expected 1 hit, got %d", len(hits))
     52 	}
     53 	if !hits[0].Excerpt.Valid || !strings.Contains(strings.ToLower(hits[0].Excerpt.String), "«durham»") {
     54 		t.Fatalf("expected excerpt with highlighted token, got: %q", hits[0].Excerpt.String)
     55 	}
     56 
     57 	// Delete and ensure gone from search
     58 	okDel, err := db.DeleteBookmark(ctx, b.ID)
     59 	if err != nil || !okDel {
     60 		t.Fatalf("delete: ok=%v err=%v", okDel, err)
     61 	}
     62 	hits, err = db.SearchBookmarksWithExcerpt(ctx, uid, "durham", 10, 0)
     63 	if err != nil {
     64 		t.Fatalf("search after delete: %v", err)
     65 	}
     66 	if len(hits) != 0 {
     67 		t.Fatalf("expected 0 hits after delete, got %d", len(hits))
     68 	}
     69 }
     70 
     71 func TestUniqueURL(t *testing.T) {
     72 	t.Parallel()
     73 	ctx := context.Background()
     74 	dir := t.TempDir()
     75 	path := dir + "/uniq.db"
     76 	db, err := OpenAtPath(ctx, path)
     77 	if err != nil {
     78 		t.Fatalf("open db: %v", err)
     79 	}
     80 	defer db.Close()
     81 
     82 	// Create user
     83 	uid := int64(1)
     84 	_, err = db.sql.ExecContext(ctx, `INSERT INTO users(id, username, encrypted_password, api_token, created_at, updated_at) VALUES(1, 'tester', 'x', 'tok', strftime('%Y-%m-%dT%H:%M:%fZ','now'), strftime('%Y-%m-%dT%H:%M:%fZ','now'))`)
     85 	if err != nil {
     86 		t.Fatalf("insert user: %v", err)
     87 	}
     88 	if _, err := db.CreateBookmark(ctx, uid, "http://dupe.local", "One", nil); err != nil {
     89 		t.Fatalf("first create: %v", err)
     90 	}
     91 	if _, err := db.CreateBookmark(ctx, uid, "http://dupe.local", "Two", nil); err == nil {
     92 		t.Fatalf("expected unique constraint error, got nil")
     93 	}
     94 }
     95 
     96 func TestFTSIndexUpdatesOnArchive(t *testing.T) {
     97 	t.Parallel()
     98 	ctx := context.Background()
     99 	dir := t.TempDir()
    100 	path := dir + "/fts.db"
    101 	db, err := OpenAtPath(ctx, path)
    102 	if err != nil {
    103 		t.Fatalf("open db: %v", err)
    104 	}
    105 	defer db.Close()
    106 
    107 	// Create user
    108 	uid := int64(1)
    109 	_, err = db.sql.ExecContext(ctx, `INSERT INTO users(id, username, encrypted_password, api_token, created_at, updated_at) VALUES(1, 'tester', 'x', 'tok', strftime('%Y-%m-%dT%H:%M:%fZ','now'), strftime('%Y-%m-%dT%H:%M:%fZ','now'))`)
    110 	if err != nil {
    111 		t.Fatalf("insert user: %v", err)
    112 	}
    113 	b, err := db.CreateBookmark(ctx, uid, "http://no-archive.local", "No Archive", nil)
    114 	if err != nil {
    115 		t.Fatalf("create: %v", err)
    116 	}
    117 	// Should not find term before archive content exists
    118 	hits, err := db.SearchBookmarksWithExcerpt(ctx, uid, "needle", 5, 0)
    119 	if err != nil {
    120 		t.Fatalf("search pre-archive: %v", err)
    121 	}
    122 	if len(hits) != 0 {
    123 		t.Fatalf("expected 0 hits before archiving, got %d", len(hits))
    124 	}
    125 	// Save archive and ensure search works
    126 	if err := db.SaveArchive(ctx, b.ID, "finding a needle in a haystack"); err != nil {
    127 		t.Fatalf("save archive: %v", err)
    128 	}
    129 	hits, err = db.SearchBookmarksWithExcerpt(ctx, uid, "needle", 5, 0)
    130 	if err != nil {
    131 		t.Fatalf("search post-archive: %v", err)
    132 	}
    133 	if len(hits) != 1 {
    134 		t.Fatalf("expected 1 hit after archiving, got %d", len(hits))
    135 	}
    136 }