1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
2//
3// SPDX-License-Identifier: AGPL-3.0-or-later
4
5package deeplink_test
6
7import (
8 "errors"
9 "testing"
10
11 "git.secluded.site/lune/internal/deeplink"
12)
13
14func TestParseID_Valid(t *testing.T) {
15 t.Parallel()
16
17 const (
18 uuidLower = "123e4567-e89b-12d3-a456-426614174000"
19 uuidArea = "3bbf1923-64ae-4bcf-96a9-9bb86c799dab"
20 uuidGoal = "9d79e922-9ca8-4b8c-9aa5-dd98bb2492b2"
21 )
22
23 tests := []struct {
24 name string
25 input string
26 wantID string
27 }{
28 {"UUID lowercase", uuidLower, uuidLower},
29 {"UUID uppercase", "123E4567-E89B-12D3-A456-426614174000", uuidLower},
30 {"deep link areas", "lunatask://areas/" + uuidArea, uuidArea},
31 {"deep link goals", "lunatask://goals/" + uuidGoal, uuidGoal},
32 {"deep link tasks", "lunatask://tasks/" + uuidArea, uuidArea},
33 {"deep link notes", "lunatask://notes/" + uuidArea, uuidArea},
34 {"deep link people", "lunatask://people/" + uuidArea, uuidArea},
35 {"deep link notebooks", "lunatask://notebooks/" + uuidArea, uuidArea},
36 {"with whitespace", " " + uuidLower + " ", uuidLower},
37 }
38
39 for _, testCase := range tests {
40 t.Run(testCase.name, func(t *testing.T) {
41 t.Parallel()
42
43 id, err := deeplink.ParseID(testCase.input)
44 if err != nil {
45 t.Errorf("ParseID(%q) error = %v, want nil", testCase.input, err)
46 }
47
48 if id != testCase.wantID {
49 t.Errorf("ParseID(%q) = %q, want %q", testCase.input, id, testCase.wantID)
50 }
51 })
52 }
53}
54
55func TestParseID_Invalid(t *testing.T) {
56 t.Parallel()
57
58 tests := []struct {
59 name string
60 input string
61 wantErr error
62 }{
63 {"empty", "", deeplink.ErrInvalidReference},
64 {"random text", "not-a-uuid", deeplink.ErrInvalidReference},
65 {"invalid UUID", "123e4567-e89b-12d3-a456-42661417zzzz", deeplink.ErrInvalidReference},
66 {"wrong scheme", "http://areas/123e4567-e89b-12d3-a456-426614174000", deeplink.ErrInvalidReference},
67 {"invalid resource", "lunatask://habits/123e4567-e89b-12d3-a456-426614174000", deeplink.ErrUnsupportedResource},
68 {"missing path", "lunatask://", deeplink.ErrInvalidReference},
69 {"extra path", "lunatask://areas/foo/bar", deeplink.ErrInvalidReference},
70 }
71
72 for _, testCase := range tests {
73 t.Run(testCase.name, func(t *testing.T) {
74 t.Parallel()
75
76 _, err := deeplink.ParseID(testCase.input)
77 if !errors.Is(err, testCase.wantErr) {
78 t.Errorf("ParseID(%q) error = %v, want %v", testCase.input, err, testCase.wantErr)
79 }
80 })
81 }
82}
83
84func TestBuild(t *testing.T) {
85 t.Parallel()
86
87 const uuid = "3bbf1923-64ae-4bcf-96a9-9bb86c799dab"
88
89 tests := []struct {
90 name string
91 resource deeplink.Resource
92 id string
93 want string
94 }{
95 {"area", deeplink.Area, uuid, "lunatask://areas/" + uuid},
96 {"goal", deeplink.Goal, uuid, "lunatask://goals/" + uuid},
97 {"task", deeplink.Task, uuid, "lunatask://tasks/" + uuid},
98 {"note", deeplink.Note, uuid, "lunatask://notes/" + uuid},
99 {"person", deeplink.Person, uuid, "lunatask://people/" + uuid},
100 {"notebook", deeplink.Notebook, uuid, "lunatask://notebooks/" + uuid},
101 }
102
103 for _, testCase := range tests {
104 t.Run(testCase.name, func(t *testing.T) {
105 t.Parallel()
106
107 got, err := deeplink.Build(testCase.resource, testCase.id)
108 if err != nil {
109 t.Errorf("Build(%v, %q) error = %v, want nil",
110 testCase.resource, testCase.id, err)
111 }
112
113 if got != testCase.want {
114 t.Errorf("Build(%v, %q) = %q, want %q",
115 testCase.resource, testCase.id, got, testCase.want)
116 }
117 })
118 }
119}
120
121func TestBuild_InvalidID(t *testing.T) {
122 t.Parallel()
123
124 _, err := deeplink.Build(deeplink.Area, "not-a-uuid")
125 if !errors.Is(err, deeplink.ErrInvalidReference) {
126 t.Errorf("Build(Area, \"not-a-uuid\") error = %v, want %v", err, deeplink.ErrInvalidReference)
127 }
128}