3 * _| || |_/ ___| ___ _ __ _ __ ___ | |
4 * |_ .. _\___ \ / _ \ '_ \| '_ \ / _ \| |
5 * |_ _|___) | __/ |_) | |_) | (_) |_|
6 * |_||_| |____/ \___| .__/| .__/ \___/(_)
11 * Copyright (C) The #Seppo contributors. All rights reserved.
13 * This program is free software: you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation, either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
29 let test_of_channel () =
30 let ic = "data/cgi_" ^
"2022-04-05T125146.post" |> open_in
in
31 let fv = ic |> Html.Form.of_channel
141 in
34 | [ (k0
, [ v0
]); (k1
, [ v1
]); (k2
, [ v2
]); (k3
, [ v3
]) ] ->
35 k0
|> Assrt.equals_string __LOC__
"login";
36 v0
|> Assrt.equals_string __LOC__
"demo";
37 k1
|> Assrt.equals_string __LOC__
"password";
38 v1
|> Assrt.equals_string __LOC__
"demodemodemo";
39 k2
|> Assrt.equals_string __LOC__
"token";
41 |> Assrt.equals_string __LOC__
42 "ff13e7eaf9541ca2ba30fd44e864c3ff014d2bc9";
43 k3
|> Assrt.equals_string __LOC__
"returnurl";
45 |> Assrt.equals_string __LOC__
"https://demo.mro.name/shaarligo/o/p/";
47 | _
-> failwith __LOC__
);
50 |> Http.Form.filter_sort_keys
51 [ "login"; "password"; "token"; "returnurl" ]
53 | [ (k0, [ v0 ]); (k1, [ v1 ]); (k2, [ v2 ]); (k3, [ v3 ]) ] ->
54 k0 |> Assrt.equals_string __LOC__ "login";
55 v0 |> Assrt.equals_string __LOC__ "demo";
56 k1 |> Assrt.equals_string __LOC__ "password";
57 v1 |> Assrt.equals_string __LOC__ "demodemodemo";
58 k2 |> Assrt.equals_string __LOC__ "returnurl";
60 |> Assrt.equals_string __LOC__ "https://demo.mro.name/shaarligo/o/p/";
61 k3 |> Assrt.equals_string __LOC__ "token";
63 |> Assrt.equals_string __LOC__
64 "ff13e7eaf9541ca2ba30fd44e864c3ff014d2bc9";
66 | _ -> failwith __LOC__ *);
71 ("ka", (Ok
"va", "text", [("autofocus",""); ("pattern", {|^\S
+$
|})]));
73 (match List.assoc_opt
"ka" defs with
74 | Some
(Ok v
,_
,_
) -> v
76 |> Assrt.equals_string __LOC__
"va";
79 let test_validate () =
80 Logr.info
(fun m
-> m
"%s.%s" "http" "test_validate");
81 (match Html.Form.string
82 ("uid","text",["required","required"; "pattern","^[a-z]+$"])
84 | Error
("uid", "pattern mismatch") -> ()
85 | _
-> failwith __LOC__
);
86 (match Html.Form.validate
"uid" "text" (Ok
"hu1") ("pattern","^[a-z]+$") with
87 | Error
("uid", "pattern mismatch") -> ()
88 | _
-> failwith __LOC__
);
89 (match Html.Form.validate
"uid" "text" (Ok
"abcd") ("minlength","4") with
91 | _
-> failwith __LOC__
);
92 (match Html.Form.validate
"uid" "text" (Ok
"abcd") ("minlength","5") with
93 | Error
("uid","shorter than minlength") -> ()
94 | _
-> failwith __LOC__
);
95 (match Html.Form.validate
"uid" "text" (Ok
"abcd") ("minlength","_") with
96 | Error
("uid","invalid minlength") -> ()
97 | _
-> failwith __LOC__
);
100 let test_from_html () =
101 let pred ty valu
(na
,va
) =
110 Logr.debug
(fun m
-> m
" '%s' ~ /%s/" v va
);
113 Logr.debug
(fun m
-> m
" ignored %s='%s'" na va
);
116 let string (name
,(ty
,preds
)) vals
=
118 (List.assoc_opt name vals
)
119 (fun v -> Some
(v |> String.concat
"")) in
120 List.fold_left
(pred ty
) (Ok
v) preds
in
121 let _validate defs vals
=
122 Logr.debug
(fun m
-> m
"Form.validate");
123 let field init
(name
,(ty
,preds
)) =
124 match string (name
,(ty
,preds
)) vals
with
127 | Error a
-> Error
(inp
:: a
)
128 | Ok a
-> Error
(inp
:: a
)
132 | Error a
-> Error
(inp
:: a
)
133 | Ok a
-> Ok
(inp
:: a
)
136 List.fold_left
field (Ok
[]) defs
138 let def0 = ("ka", ("text", [("autofocus",""); ("pattern", {|^\S
+$
|})])) in
139 let _defs = [ def0; ] in
143 (* match _validate defs vals with
144 | Ok res -> List.assoc_opt "ka" res
145 |> Option.value ~default:(Ok None)
148 |> Assrt.equals_string __LOC__ "vb"
149 | _ -> failwith __LOC__); *)
150 let ( let* ) = Result.bind
in
152 let* k
= string def0 vals in
155 | Ok
(Some
v) -> v |> Assrt.equals_string __LOC__
"vb"
159 let test_from_html1 () =
160 let i0 : Html.Form.input
= ("k0", "text", [
161 ("autofocus", "autofocus");
162 ("required", "required");
163 ("pattern", {|^
[a
-z
][0-9]+$
|});
165 let i1 = ("k1", "text", [
166 ("required", "required");
169 ("pattern", {|^
v.$
|});
171 let vals : Html.Form.t
= [
175 let ( let* ) = Result.bind
in
177 let* v0
= vals |> Html.Form.string i0 in
178 let* v1
= Html.Form.string i1 vals in
179 v0
|> Assrt.equals_string __LOC__
"v0";
180 v1
|> Assrt.equals_string __LOC__
"v1";
183 | Error
(_
,e
) -> e
|> Assrt.equals_string __LOC__
""
187 let test_add_class () =
190 (("","type"),"text");
192 (match "b" |> Html.add_class
l with
195 (("","type"),"text");
198 | _
-> failwith __LOC__
);
202 (("","class"),"clz");
203 (("","type"),"text");
205 (match "b" |> Html.add_class
l with
208 (("","class"),"b clz");
209 (("","type"),"text");
211 | _
-> failwith __LOC__
);
215 (("","class"),"a b clz");
216 (("","type"),"text");
218 (match "b" |> Html.add_class
l with
221 (("","class"),"a b clz");
222 (("","type"),"text");
224 | _
-> failwith __LOC__
);
228 let open Soup
in (* https://aantron.github.io/lambdasoup/ *)
230 let local = a
|> texts
|> String.concat
"" in
231 (* check txt starting with @ and not having a host *)
232 let href = R.attribute
"href" a
|> Uri.of_string
in
233 let host = href |> Uri.host_with_default ~default
:"-" in
234 let txt = local ^
"@" ^
host in
238 let p = "div" |> create_element
in
243 print_endline
(R.attribute
"href" a
);
244 a
|> mention |> replace a
248 {|Hello
, world
!|} |> parse
|> proc |> to_string
|> Assrt.equals_string __LOC__
{|<div
>Hello
, world
!</div
>|};
249 {|Hello
, <a
href="https://example.com/user/12345">@world
</a
>!|} |> parse
|> proc |> to_string
|> Assrt.equals_string __LOC__
{|<div
>Hello
, @world
@example
.com
!</div
>|};
252 let test_to_plain () =
253 Logr.info
(fun m
-> m
"%s" "test_to_plain");
255 let prt l = l |> List.iter
(fun (s
,href) -> Format.asprintf
"%s -> %a" s
Uri.pp_hum
href |> prerr_endline
) in
259 let load_note_content fn
=
260 let fn = "data/ap/inbox/create/note/" ^
fn in
264 match ic |> Ezjsonm.from_channel
|> As2_vocab.Activitypub.Decode.obj
with
265 | Error _
-> failwith
"failed to load note"
266 | Ok o
-> match o
with
267 | `Create
{ obj
= `Note obj
; _
} ->
268 let _,co
= obj
.content_map
|> List.hd
in
270 | _ -> failwith
"strange type")
272 {|Hello
, world
!|} |> Html.to_plain
|> a |> Assrt.equals_string __LOC__
{|Hello
, world
!|};
273 {|Hello
, <a href="https://example.com">@world
</a>!|} |> Html.to_plain
|> a |> Assrt.equals_string __LOC__
{|Hello
, @world
@example
.com
!|};
274 {|Hello
, <a href="https://example.com">world
</a>!|} |> Html.to_plain
|> a |> Assrt.equals_string __LOC__
{|Hello
, world
[1]!
276 [1]: https
://example
.com
|};
277 {|Hello
, <a href="https://example.com">example
.com
</a>!|} |> Html.to_plain
|> a |> Assrt.equals_string __LOC__
{|Hello
, https
://example
.com
!|};
278 "note-PZkn02gIUSk.json" |> load_note_content |> Assrt.equals_string __LOC__
{|<p><span
class="h-card" translate
="no"><a href="https://mastodon.social/@johnleonard" class="u-url mention">@<span
>johnleonard
</span
></a></span
> cat
&#
39;s out
of the bag
. Stop wasting effort
.</p>|};
279 "note-PZkn02gIUSk.json" |> load_note_content |> Html.to_plain
|> a |> Assrt.equals_string __LOC__
{|@johnleonard
@mastodon
.social cat's out
of the bag
. Stop wasting effort
.|};
280 "note-Hjcb9bqwCgk.json" |> load_note_content |> Assrt.equals_string __LOC__
{|<p><span
class="h-card" translate
="no"><a href="https://floss.social/@wschenk" class="u-url mention">@<span
>wschenk
</span
></a></span
> <span
class="h-card" translate
="no"><a href="https://mstdn.social/@geoglyphentropy" class="u-url mention">@<span
>geoglyphentropy
</span
></a></span
> <span
class="h-card" translate
="no"><a href="https://mstdn.social/@nus" class="u-url mention">@<span
>nus
</span
></a></span
> <span
class="h-card" translate
="no"><a href="https://tooot.im/@DavidKafri" class="u-url mention">@<span
>DavidKafri
</span
></a></span
> <span
class="h-card" translate
="no"><a href="https://me.dm/@thetechtutor" class="u-url mention">@<span
>thetechtutor
</span
></a></span
> After the Goat refused
to explain what military action
in response
to the
<a href="https://mastodon.social/tags/alaqsaflood" class="mention hashtag" rel
="tag">#
<span
>alaqsaflood
</span
></a> would
&#
39;ve been moral he lost all priveleges
with me
, although he eventually admitted that nothing would meet his standards
. Eventually he blocked me
, although he seems
to have somehow replied
to me
.</p><p>I
&#
39;m inferring that this has something
to with the Goat
, but have no idea
. Guess I
&#
39;ll never know what it was about
.</p>|};
281 "note-Hjcb9bqwCgk.json" |> load_note_content |> Html.to_plain
|> a |> Assrt.equals_string __LOC__
{|@wschenk
@floss
.social
@geoglyphentropy
@mstdn
.social
@nus
@mstdn
.social
@DavidKafri
@tooot
.im
@thetechtutor
@me
.dm After the Goat refused
to explain what military action
in response
to the #alaqsaflood
[1] would've been moral he lost all priveleges
with me
, although he eventually admitted that nothing would meet his standards
. Eventually he blocked me
, although he seems
to have somehow replied
to me
.
283 I'm inferring that this has something
to with the Goat
, but have no idea
. Guess I'll never know what it was about
.
285 [1]: https
://mastodon
.social
/tags
/alaqsaflood
|};
287 "note-OZcAekXDY1A.json" |> load_note_content |> Html.to_plain
|> a |> Assrt.equals_string __LOC__
{|Trotz Mücken abends draußen sitzen
: 6 Tipps gegen die Mückenplage
- Utopia.de
288 https
://utopia
.de
/ratgeber
/trotz
-muecken
-abends
-draussen
-sitzen
-6-tipps
-gegen
-die
-mueckenplage_372661
/
289 Ich weis ja nicht warum man mich mit Teebaum
-Ö
l gequält hat
. »Um #Mücke
[1] n zu vertreiben
, muss der erste Griff nicht zum #Mückenspray
[2] gehen
. Mücken sind sehr geruchsempfindlich
, weshalb du viele natürliche #Gerüche
[3] gegen sie einsetzen kannst
.«
291 https
://ripf
.de
/m
/b26xarb
293 [1]: https
://social
.wohlfarth
.name
/tags
/M%C
3%BCcke
294 [2]: https
://social
.wohlfarth
.name
/tags
/M%C
3%BCckenspray
295 [3]: https
://social
.wohlfarth
.name
/tags
/Ger%C
3%BCche
296 [4]: https
://social
.wohlfarth
.name
/tags
/Shaarli
|};
298 "note-Gyuo6v3wVRY.json" |> load_note_content |> Html.to_plain
|> a |> Assrt.equals_string __LOC__
{|@kura
@noc
.social Yeah it's fustrating
, but I also just don't care enough
to go
to iPlayer
/Pay
for something
to watch the olympics
300 Like they are cool events
, but they are just so hostile
to watch
(I assume football is like this
as well
) that it does not cross over the effort
/reward
.
302 I dunno how this is not considered
a larger existential problem
for them
. Then again
, if the overall press vibe is right they have bigger existential crisis
-es ongoing
|};
306 let test_to_plain_2 () =
307 Logr.info
(fun m
-> m
"%s" "test_to_plain_2");
309 test/data/ap/inbox/create/note/note-OZcAekXDY1A.json
314 Logr.info
(fun m
-> m
"html_test");
315 Unix.chdir
"../../../test/";
316 Form.test_of_channel ();
317 Form.test_to_html ();
318 Form.test_validate ();
319 Form.test_from_html ();
320 Form.test_from_html1 ();