570 lines
34 KiB
HTML
570 lines
34 KiB
HTML
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<link rel="stylesheet" href="../../coverage.css"/> <title> dog_and_duck/quack/quack.clj </title>
|
|
</head>
|
|
<body>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
001 (ns dog-and-duck.quack.quack
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
002 "Validator for ActivityPub objects: if it walks like a duck, and it quacks like a duck..."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
003 ;;(:require [clojure.spec.alpha as s])
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
004 (:import [java.net URI URISyntaxException]))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
005
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
006 ;;; Copyright (C) Simon Brooke, 2022
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
007
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
008 ;;; This program is free software; you can redistribute it and/or
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
009 ;;; modify it under the terms of the GNU General Public License
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
010 ;;; as published by the Free Software Foundation; either version 2
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
011 ;;; of the License, or (at your option) any later version.
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
012
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
013 ;;; This program is distributed in the hope that it will be useful,
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
014 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
015 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
016 ;;; GNU General Public License for more details.
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
017
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
018 ;;; You should have received a copy of the GNU General Public License
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
019 ;;; along with this program; if not, write to the Free Software
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
020 ;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
021
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
022 (defn object?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
023 "Returns `true` iff `x` is recognisably an ActivityStreams object.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
024
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
025 **NOTE THAT** The ActivityStreams spec
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
026 [says](https://www.w3.org/TR/activitystreams-core/#object):
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
027
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
028 > All properties are optional (including the id and type)
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
029
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
030 But we are *just not having that*, because otherwise we're flying blind.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
031 We *shall* reject objects lacking at least `:type`. Missing `:id` keys are
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
032 tolerable because they represent transient objects, which we expect to
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
033 handle."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
034 [x]
|
|
</span><br/>
|
|
<span class="covered" title="15 out of 15 forms covered">
|
|
035 (and (map? x) (:type x) true))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
036
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
037 (defn persistent-object?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
038 "`true` iff `x` is a persistent object.
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
039
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
040 Transient objects in ActivityPub are not required to have an `id` key, but persistent
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
041 ones must have a key, and it must be an IRI (but normally a URI)."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
042 [x]
|
|
</span><br/>
|
|
<span class="partial" title="1 out of 2 forms covered">
|
|
043 (try
|
|
</span><br/>
|
|
<span class="covered" title="13 out of 13 forms covered">
|
|
044 (and (object? x) (uri? (URI. (:id x))))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
045 (catch URISyntaxException _ false)))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
046
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
047 (persistent-object? {:type "test" :id "https://mastodon.scot/@barfilfarm"})
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
048
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
049 (def ^:const actor-types
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
050 "The set of types we will accept as actors.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
051
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
052 There's an [explicit set of allowed actor types]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
053 (https://www.w3.org/TR/activitystreams-vocabulary/#actor-types)."
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
054 #{"Application"
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
055 "Group"
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
056 "Organization"
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
057 "Person"
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
058 "Service"})
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
059
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
060 (defn actor-type?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
061 ;; TODO: better as a macro
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
062 [x]
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
063 (if (actor-types x) true false))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
064
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
065 (def ^:const verb-types
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
066 "The set of types we will accept as verbs.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
067
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
068 There's an [explicit set of allowed verb types]
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
069 (https://www.w3.org/TR/activitystreams-vocabulary/#activity-types)."
|
|
</span><br/>
|
|
<span class="covered" title="29 out of 29 forms covered">
|
|
070 #{"Accept" "Add" "Announce" "Arrive" "Block" "Create" "Delete" "Dislike"
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
071 "Flag" "Follow" "Ignore" "Invite" "Join" "Leave" "Like" "Listen" "Move"
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
072 "Offer" "Question" "Reject" "Read" "Remove" "TentativeAccept"
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
073 "TentativeReject" "Travel" "Undo" "Update" "View"})
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
074
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
075 (defn verb-type?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
076 ;; TODO: better as a macro
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
077 [x]
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
078 (if (verb-types x) true false))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
079
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
080 (def ^:const activitystreams-context-uri
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
081 "The URI of the context of an ActivityStreams object is expected to be this
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
082 literal string."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
083 "https://www.w3.org/ns/activitystreams")
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
084
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
085 (defn context?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
086 "Returns `true` iff `x` quacks like an ActivityStreams context, else false.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
087
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
088 A context is either
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
089 1. the URI (actually an IRI) `activitystreams-context-uri`, or
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
090 2. a collection comprising that URI and a map."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
091 [x]
|
|
</span><br/>
|
|
<span class="partial" title="4 out of 6 forms covered">
|
|
092 (cond
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
093 (nil? x) false
|
|
</span><br/>
|
|
<span class="covered" title="11 out of 11 forms covered">
|
|
094 (string? x) (and (= x activitystreams-context-uri) true)
|
|
</span><br/>
|
|
<span class="partial" title="19 out of 20 forms covered">
|
|
095 (coll? x) (and (context? (first (remove map? x)))
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
096 (= (count x) 2)
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
097 true)
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
098 :else false))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
099
|
|
</span><br/>
|
|
<span class="partial" title="40 out of 42 forms covered">
|
|
100 (defmacro has-context? [x]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
101 `(context? ((keyword "@context") ~x)))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
102
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
103 (defn actor?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
104 "Returns `true` if `x` quacks like an actor, else false."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
105 [x]
|
|
</span><br/>
|
|
<span class="partial" title="7 out of 21 forms covered">
|
|
106 (and
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
107 (object? x)
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
108 (has-context? x)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 6 forms covered">
|
|
109 (uri? (URI. (:inbox x)))
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 6 forms covered">
|
|
110 (uri? (URI. (:outbox x)))
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 5 forms covered">
|
|
111 (actor-type? (:type x))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
112 true))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
113
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
114 (defn activity?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
115 "`true` iff `x` quacks like an activity, else false."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
116 [x]
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 2 forms covered">
|
|
117 (try
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 28 forms covered">
|
|
118 (and (object? x)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 5 forms covered">
|
|
119 (has-context? x)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 5 forms covered">
|
|
120 (string? (:summary x))
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 5 forms covered">
|
|
121 (actor? (:actor x))
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 5 forms covered">
|
|
122 (verb-type? (:type x))
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 15 forms covered">
|
|
123 (or (object? (:object x)) (uri? (URI. (:object x))))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
124 true)
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
125 (catch URISyntaxException _ false)))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
126
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
127 (defn link?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
128 "`true` iff `x` quacks like a link, else false."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
129 [x]
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 16 forms covered">
|
|
130 (and (object? x)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 5 forms covered">
|
|
131 (= (:type x) "Link")
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 6 forms covered">
|
|
132 (uri? (URI. (:href x)))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
133 true))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
134
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
135 (defn link-or-uri?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
136 "`true` iff `x` is either a URI or a link, else false.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
137
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
138 There are several points in the specification where e.g. the `:image`
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
139 property (if present) may be either a link or a URI."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
140 [x]
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 5 forms covered">
|
|
141 (and
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 9 forms covered">
|
|
142 (cond (string? x) (uri? (URI. x))
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
143 :else (link? x))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
144 true))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
145
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
146 (defn collection?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
147 "`true` iff `x` quacks like a collection of type `type`, else `false`.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
148
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
149 With one argument, will recognise plain collections and ordered collections,
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
150 but (currently) not collection pages."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
151 ([x type]
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 11 forms covered">
|
|
152 (let [items (or (:items x) (:orderedItems x))]
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 25 forms covered">
|
|
153 (and
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
154 (cond
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 8 forms covered">
|
|
155 (:items x) (nil? (:orderedItems x))
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 8 forms covered">
|
|
156 (:orderedItems x) (nil? (:items x))) ;; can't have both properties
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
157 (object? x)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 5 forms covered">
|
|
158 (= (:type x) type)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
159 (coll? items)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 4 forms covered">
|
|
160 (every? object? items)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 5 forms covered">
|
|
161 (integer? (:totalItems x))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
162 true)))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
163 ([x]
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 10 forms covered">
|
|
164 (or (collection? x "Collection")
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 2 forms covered">
|
|
165 (collection? x "OrderedCollection"))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
166
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
167 (defn unordered-collection?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
168 "`true` iff `x` quacks like an unordered collection, else `false`."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
169 [x]
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 4 forms covered">
|
|
170 (collection? x "Collection"))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
171
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
172 (defn ordered-collection?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
173 "`true` iff `x` quacks like an ordered collection, else `false`."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
174 [x]
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 4 forms covered">
|
|
175 (collection? x "OrderedCollection"))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
176
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
177 (defn collection-page?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
178 "`true` iff `x` quacks like a page in a paged collection, else `false`."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
179 [x]
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 4 forms covered">
|
|
180 (collection? x "CollectionPage"))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
181
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
182 (defn ordered-collection-page?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
183 "`true` iff `x` quacks like a page in an ordered paged collection, else `false`."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
184 [x]
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 4 forms covered">
|
|
185 (collection? x "OrderedCollectionPage"))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
186
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
187
|
|
</span><br/>
|
|
</body>
|
|
</html>
|