File size: 4,002 Bytes
c9c49ab
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
defmodule Plausible.Segments.SegmentTest do
  use ExUnit.Case
  alias Plausible.Segments.Segment
  doctest Segment, import: true

  setup do
    segment = %Segment{
      name: "any name",
      type: :personal,
      segment_data: %{"filters" => ["is", "visit:page", ["/blog"]]},
      owner_id: 1,
      site_id: 100
    }

    {:ok, segment: segment}
  end

  test "changeset has required fields" do
    assert Segment.changeset(%Segment{}, %{}).errors == [
             segment_data: {"property \"filters\" must be an array with at least one member", []},
             name: {"can't be blank", [validation: :required]},
             segment_data: {"can't be blank", [validation: :required]},
             site_id: {"can't be blank", [validation: :required]},
             type: {"can't be blank", [validation: :required]},
             owner_id: {"can't be blank", [validation: :required]}
           ]
  end

  test "changeset does not allow setting owner_id to nil (setting to nil happens with database triggers)",
       %{segment: valid_segment} do
    assert Segment.changeset(
             valid_segment,
             %{
               owner_id: nil
             }
           ).errors == [
             owner_id: {"can't be blank", [validation: :required]}
           ]
  end

  test "changeset forbids too long name", %{segment: valid_segment} do
    assert Segment.changeset(
             valid_segment,
             %{
               name: String.duplicate("a", 256)
             }
           ).errors == [
             name:
               {"should be at most %{count} byte(s)",
                [{:count, 255}, {:validation, :length}, {:kind, :max}, {:type, :binary}]}
           ]
  end

  test "changeset forbids too large segment_data", %{segment: valid_segment} do
    assert Segment.changeset(
             valid_segment,
             %{
               segment_data:
                 Jason.decode!(
                   ~s({"filters": ["is", "visit:exit_page", [#{Enum.map_join(1..(5 * 1024), ",", fn i -> "#{i}" end)}]]})
                 )
             }
           ).errors == [
             segment_data: {"should be at most %{count} byte(s)", [{:count, 5120}]}
           ]
  end

  test "changeset allows setting nil owner_id to a user id (to be able to recover dangling site segments)",
       %{segment: valid_segment = %Segment{}} do
    assert Segment.changeset(
             %Segment{
               valid_segment
               | owner_id: nil
             },
             %{
               owner_id: 100_100
             }
           ).valid? == true
  end

  test "changeset requires segment_data to be structured as expected", %{segment: valid_segment} do
    assert Segment.changeset(
             valid_segment,
             %{
               segment_data: %{"filters" => 1, "labels" => true, "other" => []}
             }
           ).errors == [
             {:segment_data, {"property \"labels\" must be map or nil", []}},
             {:segment_data,
              {"property \"filters\" must be an array with at least one member", []}},
             {:segment_data,
              {"must not contain any other property except \"filters\" and \"labels\"", []}}
           ]
  end

  test "changeset forbids empty filters list", %{segment: valid_segment} do
    assert Segment.changeset(
             valid_segment,
             %{
               segment_data: %{
                 "filters" => []
               }
             }
           ).errors == [
             {:segment_data,
              {"property \"filters\" must be an array with at least one member", []}}
           ]
  end

  test "changeset permits well-structured segment data", %{segment: valid_segment} do
    assert Segment.changeset(
             valid_segment,
             %{
               segment_data: %{
                 "filters" => [["is", "visit:country", ["DE"]]],
                 "labels" => %{"DE" => "Germany"}
               }
             }
           ).valid? == true
  end
end