From 2427b02b21b3c09584b63a8e6e66d39810325f8c Mon Sep 17 00:00:00 2001 From: Milt Reder Date: Wed, 5 May 2021 15:29:44 -0400 Subject: [PATCH 1/8] Allow 2.0.x versions --- src/xapi_schema/spec/regex.cljc | 4 ++-- test/xapi_schema/spec/regex_test.cljc | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/xapi_schema/spec/regex.cljc b/src/xapi_schema/spec/regex.cljc index 5bb00ea..c1bc173 100644 --- a/src/xapi_schema/spec/regex.cljc +++ b/src/xapi_schema/spec/regex.cljc @@ -1,7 +1,7 @@ (ns xapi-schema.spec.regex (:require [clojure.string :refer [join]])) -(def LanguageTagRegEx ; RFC 5646, w/ lang subtag limitation +(def LanguageTagRegEx ; RFC 5646, w/ lang subtag limitation (let [;; Language Subtags ;; Note: we exclude 4-8 char subtags, even though they are allowed in ;; the RFC spec, since they are reserved for future (not current) use. @@ -148,7 +148,7 @@ (def xAPIVersionRegEx (let [suf-part "[0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*" suffix (str "(\\.[0-9]+(?:-" suf-part ")?(?:\\+" suf-part ")?)?") - ver-str (str "^1\\.0" suffix "$")] + ver-str (str "^[1-2]\\.0" suffix "$")] (re-pattern ver-str))) (def Base64RegEx diff --git a/test/xapi_schema/spec/regex_test.cljc b/test/xapi_schema/spec/regex_test.cljc index b9fa0cc..dfac17c 100644 --- a/test/xapi_schema/spec/regex_test.cljc +++ b/test/xapi_schema/spec/regex_test.cljc @@ -148,7 +148,12 @@ (re-matches xAPIVersionRegEx "1.0.2") (re-matches xAPIVersionRegEx "1.0") (re-matches xAPIVersionRegEx "1.0.32-abc.def+ghi.jkl"))) - (is (not (re-matches xAPIVersionRegEx "0.9.5"))))) + (is (not (re-matches xAPIVersionRegEx "0.9.5")))) + (testing "matches xAPI 2.0.x versions" + (is (and (re-matches xAPIVersionRegEx "2.0.0") + (re-matches xAPIVersionRegEx "2.0.2") + (re-matches xAPIVersionRegEx "2.0") + (re-matches xAPIVersionRegEx "2.0.32-abc.def+ghi.jkl"))))) (deftest duration-regex-test (testing "matches ISO durations" From dc64ea9fc487a09702ba81acf2c184a816e0e04e Mon Sep 17 00:00:00 2001 From: Milt Reder Date: Wed, 5 May 2021 16:36:56 -0400 Subject: [PATCH 2/8] LRS-30 naive addition of context agents, groups --- src/xapi_schema/spec.cljc | 53 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/src/xapi_schema/spec.cljc b/src/xapi_schema/spec.cljc index 226bc0b..7cdafd4 100644 --- a/src/xapi_schema/spec.cljc +++ b/src/xapi_schema/spec.cljc @@ -949,6 +949,51 @@ (s/def :context/extensions ::extensions) +;; 2.0.x compat + +;; contextAgents +(s/def :contextAgent/objectType #{"contextAgent"}) +(s/def :contextAgent/agent ::agent) +(s/def :contextAgent/relevantTypes + (s/every ::iri + :into [] + :min-count 1)) + +(s/def ::context-agent + (conform-ns "contextAgent" + (s/and + (s/keys :req [:contextAgent/objectType + :contextAgent/agent] + :opt [:contextAgent/relevantTypes]) + (restrict-keys :contextAgent/objectType + :contextAgent/agent + :contextAgent/relevantTypes)))) +(s/def :context/contextAgents + (s/every ::context-agent + :into [])) + +;; contextGroups + +(s/def :contextGroup/objectType #{"contextGroup"}) +(s/def :contextGroup/group ::group) +(s/def :contextGroup/relevantTypes + (s/every ::iri + :into [] + :min-count 1)) + +(s/def ::context-group + (conform-ns "contextGroup" + (s/and + (s/keys :req [:contextGroup/objectType + :contextGroup/group] + :opt [:contextGroup/relevantTypes]) + (restrict-keys :contextGroup/objectType + :contextGroup/group + :contextGroup/relevantTypes)))) +(s/def :context/contextGroups + (s/every ::context-group + :into [])) + (s/def ::context (conform-ns "context" (s/and @@ -960,7 +1005,9 @@ :context/platform :context/language :context/statement - :context/extensions]) + :context/extensions + :context/contextAgents + :context/contextGroups]) (restrict-keys :context/registration :context/instructor :context/team @@ -969,7 +1016,9 @@ :context/platform :context/language :context/statement - :context/extensions)))) + :context/extensions + :context/contextAgents + :context/contextGroups)))) ;; Attachments From 9a13ae68cc7b562078bf5e56bb29c8b479c11a41 Mon Sep 17 00:00:00 2001 From: Milt Reder Date: Wed, 5 May 2021 17:03:50 -0400 Subject: [PATCH 3/8] LRS-30 Allow whitespace instead of T per RFC 3339 I guess --- src/xapi_schema/spec/regex.cljc | 2 +- test/xapi_schema/spec/regex_test.cljc | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/xapi_schema/spec/regex.cljc b/src/xapi_schema/spec/regex.cljc index c1bc173..69ad89c 100644 --- a/src/xapi_schema/spec/regex.cljc +++ b/src/xapi_schema/spec/regex.cljc @@ -117,7 +117,7 @@ ;; Time time (str "(?:" hour ":" min ":" sec sec-frac "?" ")") date (str "(?:" year "-" month "-" day ")")] - (str date "T" time))) + (str date "[T\\s]" time))) (def TimestampRegEx ; RFC 3339 (let [;; Time diff --git a/test/xapi_schema/spec/regex_test.cljc b/test/xapi_schema/spec/regex_test.cljc index dfac17c..60556c4 100644 --- a/test/xapi_schema/spec/regex_test.cljc +++ b/test/xapi_schema/spec/regex_test.cljc @@ -140,7 +140,9 @@ (is (not (re-matches TimestampRegEx "20150513T15Z"))) (is (not (re-matches TimestampRegEx "20150513T15:16:00Z"))) ;; negative offset - (is (not (re-matches TimestampRegEx "2008-09-15T15:53:00.601-00:00"))))) + (is (not (re-matches TimestampRegEx "2008-09-15T15:53:00.601-00:00")))) + (testing "matches valid but terrible stamps in rfc3339 OUTSIDE of 8601" + (is (re-matches TimestampRegEx "2015-05-13 15:16:00Z")))) (deftest xapi-version-regex-test (testing "matches xAPI 1.0.X versions" From 92876f9e7c9d0df69db27c7e268d9517a880591b Mon Sep 17 00:00:00 2001 From: Milt Reder Date: Wed, 5 May 2021 19:15:02 -0400 Subject: [PATCH 4/8] LRS-30 for 2.0.0+, version is JUST 2.0.0 --- src/xapi_schema/spec.cljc | 5 +---- src/xapi_schema/spec/regex.cljc | 2 +- test/xapi_schema/spec/regex_test.cljc | 6 ++---- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/xapi_schema/spec.cljc b/src/xapi_schema/spec.cljc index 7cdafd4..8531479 100644 --- a/src/xapi_schema/spec.cljc +++ b/src/xapi_schema/spec.cljc @@ -288,10 +288,7 @@ (s/with-gen (s/and string? (partial re-matches xAPIVersionRegEx)) - #(sgen/fmap (fn [i] - (#?(:clj format - :cljs gstring/format) "1.0.%d" i)) - (sgen/int)))) + #(sgen/return "2.0.0"))) (s/def ::sha2 (s/with-gen diff --git a/src/xapi_schema/spec/regex.cljc b/src/xapi_schema/spec/regex.cljc index 69ad89c..39f0665 100644 --- a/src/xapi_schema/spec/regex.cljc +++ b/src/xapi_schema/spec/regex.cljc @@ -148,7 +148,7 @@ (def xAPIVersionRegEx (let [suf-part "[0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*" suffix (str "(\\.[0-9]+(?:-" suf-part ")?(?:\\+" suf-part ")?)?") - ver-str (str "^[1-2]\\.0" suffix "$")] + ver-str (str "^(1\\.0" suffix ")|(2\\.0\\.0)$")] (re-pattern ver-str))) (def Base64RegEx diff --git a/test/xapi_schema/spec/regex_test.cljc b/test/xapi_schema/spec/regex_test.cljc index 60556c4..493fd0b 100644 --- a/test/xapi_schema/spec/regex_test.cljc +++ b/test/xapi_schema/spec/regex_test.cljc @@ -151,11 +151,9 @@ (re-matches xAPIVersionRegEx "1.0") (re-matches xAPIVersionRegEx "1.0.32-abc.def+ghi.jkl"))) (is (not (re-matches xAPIVersionRegEx "0.9.5")))) - (testing "matches xAPI 2.0.x versions" + (testing "matches xAPI 2.0.0 version only" (is (and (re-matches xAPIVersionRegEx "2.0.0") - (re-matches xAPIVersionRegEx "2.0.2") - (re-matches xAPIVersionRegEx "2.0") - (re-matches xAPIVersionRegEx "2.0.32-abc.def+ghi.jkl"))))) + (not (re-matches xAPIVersionRegEx "2.0.2")))))) (deftest duration-regex-test (testing "matches ISO durations" From 184fbf370b434b3f3a1e36e25ebdd7b50d257bfc Mon Sep 17 00:00:00 2001 From: Milton Reder Date: Thu, 21 Aug 2025 15:43:48 -0400 Subject: [PATCH 5/8] ensure unique ids --- src/xapi_schema/spec.cljc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/xapi_schema/spec.cljc b/src/xapi_schema/spec.cljc index 9409635..8decbf9 100644 --- a/src/xapi_schema/spec.cljc +++ b/src/xapi_schema/spec.cljc @@ -1372,8 +1372,16 @@ (some-> s :statement/object :statement-ref/objectType) true))))) +(defn unique-statement-ids? + "Spec predicate to ensure that the IDs of a list of statements are unique." + [statements] + (or (distinct? (map #(get % "id") statements)) + ::s/invalid)) + (s/def ::statements - (s/coll-of ::statement :into [])) + (s/and + (s/coll-of ::statement :into []) + unique-statement-ids?)) (s/def ::lrs-statements (s/coll-of ::lrs-statement :into [])) From 822e66bb291a8821e4abc476bf2319cc218802df Mon Sep 17 00:00:00 2001 From: Milton Reder Date: Thu, 21 Aug 2025 15:53:22 -0400 Subject: [PATCH 6/8] fix arity of call to distinct? --- src/xapi_schema/spec.cljc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xapi_schema/spec.cljc b/src/xapi_schema/spec.cljc index 8decbf9..c8da52f 100644 --- a/src/xapi_schema/spec.cljc +++ b/src/xapi_schema/spec.cljc @@ -1375,7 +1375,7 @@ (defn unique-statement-ids? "Spec predicate to ensure that the IDs of a list of statements are unique." [statements] - (or (distinct? (map #(get % "id") statements)) + (or (reduce distinct? (map #(get % "id") statements)) ::s/invalid)) (s/def ::statements From 4164f959cbf844c194aa4705e41928ed89b9f9d7 Mon Sep 17 00:00:00 2001 From: Milton Reder Date: Fri, 22 Aug 2025 10:06:59 -0400 Subject: [PATCH 7/8] guard against empty list passed to distinct --- src/xapi_schema/spec.cljc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/xapi_schema/spec.cljc b/src/xapi_schema/spec.cljc index c8da52f..4a536ba 100644 --- a/src/xapi_schema/spec.cljc +++ b/src/xapi_schema/spec.cljc @@ -812,17 +812,17 @@ (-> scores (assoc :score/min raw) (assoc :score/raw min)) - + (and min max (< max min)) (-> scores (assoc :score/min max) (assoc :score/max min)) - + (and raw max (< max raw)) (-> scores (assoc :score/raw max) (assoc :score/max raw)) - + :else scores)) @@ -1375,8 +1375,11 @@ (defn unique-statement-ids? "Spec predicate to ensure that the IDs of a list of statements are unique." [statements] - (or (reduce distinct? (map #(get % "id") statements)) - ::s/invalid)) + (or + (empty? statements) + (reduce distinct? + (map #(get % "id") statements)) + ::s/invalid)) (s/def ::statements (s/and From 6e06f8591a330d981d5532224c8055b623d89eae Mon Sep 17 00:00:00 2001 From: Milton Reder Date: Fri, 22 Aug 2025 10:09:22 -0400 Subject: [PATCH 8/8] properly handle missing ids --- src/xapi_schema/spec.cljc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/xapi_schema/spec.cljc b/src/xapi_schema/spec.cljc index 4a536ba..9757d79 100644 --- a/src/xapi_schema/spec.cljc +++ b/src/xapi_schema/spec.cljc @@ -1375,11 +1375,11 @@ (defn unique-statement-ids? "Spec predicate to ensure that the IDs of a list of statements are unique." [statements] - (or - (empty? statements) - (reduce distinct? - (map #(get % "id") statements)) - ::s/invalid)) + (let [ids (keep #(get % "id") statements)] + (or + (empty? ids) + (reduce distinct? ids) + ::s/invalid))) (s/def ::statements (s/and