Skip to content

Commit 32d24ff

Browse files
authored
First concept exercise, 4th task: compare JSON objects without ordered keys (#289)
[no important files changed]
1 parent df10448 commit 32d24ff

File tree

3 files changed

+129
-2
lines changed

3 files changed

+129
-2
lines changed

exercises/concept/shopping/bats-jq.bash

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,64 @@ jq() {
2727
echo "$output"
2828
return "$rc"
2929
}
30+
31+
#############################################################
32+
# These are extra assert functions for use in tests.
33+
34+
# Assert two JSON objects are equal.
35+
# https://jqlang.org/manual/v1.7/#==-!=
36+
#
37+
# assert_objects_equal '{"a": 1, "b": 2}' '{"b":2,"a":1}'
38+
# # => true
39+
#
40+
assert_objects_equal() {
41+
local result=$(
42+
jq -n --argjson actual "$1" \
43+
--argjson expected "$2" \
44+
'$actual == $expected'
45+
)
46+
[[ $result == "true" ]]
47+
}
48+
49+
# Assert 2 floating-point values are "close enough".
50+
#
51+
# # are they the same to 2 decimal places?
52+
# assert_float 1.993 1.995 # => true
53+
#
54+
# # are they the same to 3 decimal places?
55+
# assert_float -d 3 1.993 1.995 # => false
56+
#
57+
assert_float() {
58+
local OPTIND OPTARG
59+
local decimals=2 actual expected
60+
while getopts :d: opt; do
61+
case $opt in
62+
d) decimals=$OPTARG ;;
63+
*) return 2 ;;
64+
esac
65+
done
66+
shift $((OPTIND - 1))
67+
# bash can't do floating point: use awk
68+
read -r actual expected < <(
69+
awk -v d="$decimals" -v a="$1" -v e="$2" '
70+
BEGIN {
71+
m = 10 ^ d
72+
print int(a * m)/m, int(e * m)/m
73+
}
74+
'
75+
)
76+
# now call a bats-assert command to get the desired output
77+
assert_equal "$actual" "$expected"
78+
}
79+
80+
# Assert that an object's value of a given key is the expected value.
81+
# This uses the bats `output` variable.
82+
#
83+
# run jq -f ...
84+
# assert_key_value 'the_key' 'the_expected_value'
85+
#
86+
assert_key_value() {
87+
local key=$1 expected=$2 actual
88+
actual=$(jq -rc --arg key "$key" '.[$key]' <<< "$output")
89+
assert_equal "$actual" "$expected"
90+
}

exercises/concept/shopping/test-shopping.bats

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,11 @@ load bats-jq
2727
## task 4
2828
run jq -c -f shopping.jq shopping-list.json
2929
assert_success
30-
assert_line --index 3 '{"buttermilk":"regular milk","melted butter":"vegetable oil","blueberries":"chopped apple"}'
30+
assert_objects_equal \
31+
"${lines[3]}" \
32+
'{
33+
"buttermilk":"regular milk",
34+
"melted butter":"vegetable oil",
35+
"blueberries":"chopped apple"
36+
}'
3137
}

lib/bats-jq.bash

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
# - "Printing to the terminal", https://bats-core.readthedocs.io/en/stable/writing-tests.html#printing-to-the-terminal
1111
# - "File descriptor 3", https://bats-core.readthedocs.io/en/stable/writing-tests.html#file-descriptor-3-read-this-if-bats-hangs
1212

13-
1413
jq() {
1514
local output stderr rc line
1615
stderr=$(mktemp)
@@ -27,3 +26,64 @@ jq() {
2726
echo "$output"
2827
return "$rc"
2928
}
29+
30+
#############################################################
31+
# These are extra assert functions for use in tests.
32+
33+
# Assert two JSON objects are equal.
34+
# https://jqlang.org/manual/v1.7/#==-!=
35+
#
36+
# assert_objects_equal '{"a": 1, "b": 2}' '{"b":2,"a":1}'
37+
# # => true
38+
#
39+
assert_objects_equal() {
40+
local result=$(
41+
jq -n --argjson actual "$1" \
42+
--argjson expected "$2" \
43+
'$actual == $expected'
44+
)
45+
[[ $result == "true" ]]
46+
}
47+
48+
# Assert 2 floating-point values are "close enough".
49+
#
50+
# # are they the same to 2 decimal places?
51+
# assert_float 1.993 1.995 # => true
52+
#
53+
# # are they the same to 3 decimal places?
54+
# assert_float -d 3 1.993 1.995 # => false
55+
#
56+
assert_float() {
57+
local OPTIND OPTARG
58+
local decimals=2 actual expected
59+
while getopts :d: opt; do
60+
case $opt in
61+
d) decimals=$OPTARG ;;
62+
*) return 2 ;;
63+
esac
64+
done
65+
shift $((OPTIND - 1))
66+
# bash can't do floating point: use awk
67+
read -r actual expected < <(
68+
awk -v d="$decimals" -v a="$1" -v e="$2" '
69+
BEGIN {
70+
m = 10 ^ d
71+
print int(a * m)/m, int(e * m)/m
72+
}
73+
'
74+
)
75+
# now call a bats-assert command to get the desired output
76+
assert_equal "$actual" "$expected"
77+
}
78+
79+
# Assert that an object's value of a given key is the expected value.
80+
# This uses the bats `output` variable.
81+
#
82+
# run jq -f ...
83+
# assert_key_value 'the_key' 'the_expected_value'
84+
#
85+
assert_key_value() {
86+
local key=$1 expected=$2 actual
87+
actual=$(jq -rc --arg key "$key" '.[$key]' <<< "$output")
88+
assert_equal "$actual" "$expected"
89+
}

0 commit comments

Comments
 (0)