diff --git a/go.mod b/go.mod index ade3dcbbf7..2dbd9f0324 100644 --- a/go.mod +++ b/go.mod @@ -5,13 +5,13 @@ go 1.21.3 require ( github.com/bits-and-blooms/bitset v1.13.0 github.com/bxcodec/faker v2.0.1+incompatible - github.com/cosmos/cosmos-sdk v0.50.6 + github.com/cosmos/cosmos-sdk v0.50.8 github.com/cosmos/gogoproto v1.5.0 github.com/cyware/ssi-sdk v0.0.0-20231229164914-f93f3006379f github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 github.com/evanphx/json-patch/v5 v5.9.0 github.com/fxamacker/cbor/v2 v2.7.0 - github.com/getkin/kin-openapi v0.125.0 + github.com/getkin/kin-openapi v0.127.0 github.com/go-chi/chi/v5 v5.1.0 github.com/go-chi/cors v1.2.1 github.com/go-errors/errors v1.5.1 @@ -28,7 +28,7 @@ require ( github.com/ipld/go-ipld-prime/storage/bsrvadapter v0.0.0-20240322071758-198d7dba8fb8 github.com/jbenet/goprocess v0.1.4 github.com/lens-vm/lens/host-go v0.0.0-20231127204031-8d858ed2926c - github.com/lestrrat-go/jwx/v2 v2.1.0 + github.com/lestrrat-go/jwx/v2 v2.1.1 github.com/libp2p/go-libp2p v0.35.1 github.com/libp2p/go-libp2p-gostream v0.6.0 github.com/libp2p/go-libp2p-kad-dht v0.25.2 @@ -54,13 +54,13 @@ require ( github.com/stretchr/testify v1.9.0 github.com/tidwall/btree v1.7.0 github.com/valyala/fastjson v1.6.4 - github.com/vito/go-sse v1.0.0 + github.com/vito/go-sse v1.1.1 github.com/zalando/go-keyring v0.2.5 go.opentelemetry.io/otel/metric v1.28.0 go.opentelemetry.io/otel/sdk/metric v1.28.0 go.uber.org/zap v1.27.0 golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 - golang.org/x/term v0.21.0 + golang.org/x/term v0.23.0 google.golang.org/grpc v1.65.0 google.golang.org/protobuf v1.34.2 ) @@ -71,7 +71,7 @@ require ( cloud.google.com/go/compute/metadata v0.3.0 // indirect cloud.google.com/go/iam v1.1.6 // indirect cloud.google.com/go/storage v1.38.0 // indirect - cosmossdk.io/api v0.7.4 // indirect + cosmossdk.io/api v0.7.5 // indirect cosmossdk.io/collections v0.4.0 // indirect cosmossdk.io/core v0.11.0 // indirect cosmossdk.io/depinject v1.0.0-alpha.4 // indirect @@ -82,7 +82,7 @@ require ( cosmossdk.io/x/circuit v0.1.0 // indirect cosmossdk.io/x/evidence v0.1.0 // indirect cosmossdk.io/x/feegrant v0.1.0 // indirect - cosmossdk.io/x/tx v0.13.2 // indirect + cosmossdk.io/x/tx v0.13.3 // indirect cosmossdk.io/x/upgrade v0.1.1 // indirect filippo.io/edwards25519 v1.1.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect @@ -115,7 +115,7 @@ require ( github.com/cockroachdb/pebble v1.1.0 // indirect github.com/cockroachdb/redact v1.1.5 // indirect github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 // indirect - github.com/cometbft/cometbft v0.38.8 // indirect + github.com/cometbft/cometbft v0.38.9 // indirect github.com/cometbft/cometbft-db v0.9.1 // indirect github.com/containerd/cgroups v1.1.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect @@ -156,8 +156,8 @@ require ( github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-openapi/jsonpointer v0.20.2 // indirect - github.com/go-openapi/swag v0.22.8 // indirect + github.com/go-openapi/jsonpointer v0.21.0 // indirect + github.com/go-openapi/swag v0.23.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.15.1 // indirect @@ -215,7 +215,7 @@ require ( github.com/ignite/cli/v28 v28.4.0 // indirect github.com/improbable-eng/grpc-web v0.15.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/invopop/yaml v0.2.0 // indirect + github.com/invopop/yaml v0.3.1 // indirect github.com/ipfs/bbloom v0.0.4 // indirect github.com/ipfs/go-ipfs-delay v0.0.1 // indirect github.com/ipfs/go-ipfs-pq v0.0.3 // indirect @@ -239,7 +239,7 @@ require ( github.com/leodido/go-urn v1.2.4 // indirect github.com/lestrrat-go/blackmagic v1.0.2 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect - github.com/lestrrat-go/httprc v1.0.5 // indirect + github.com/lestrrat-go/httprc v1.0.6 // indirect github.com/lestrrat-go/iter v1.0.2 // indirect github.com/lestrrat-go/option v1.0.1 // indirect github.com/lib/pq v1.10.9 // indirect @@ -356,12 +356,12 @@ require ( go.uber.org/fx v1.22.0 // indirect go.uber.org/mock v0.4.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.24.0 // indirect + golang.org/x/crypto v0.25.0 // indirect golang.org/x/mod v0.18.0 // indirect golang.org/x/net v0.26.0 // indirect golang.org/x/oauth2 v0.21.0 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.21.0 // indirect + golang.org/x/sys v0.23.0 // indirect golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.22.0 // indirect diff --git a/go.sum b/go.sum index bdf710542e..bad0d6308c 100644 --- a/go.sum +++ b/go.sum @@ -186,8 +186,8 @@ cloud.google.com/go/webrisk v1.4.0/go.mod h1:Hn8X6Zr+ziE2aNd8SliSDWpEnSS1u4R9+xX cloud.google.com/go/webrisk v1.5.0/go.mod h1:iPG6fr52Tv7sGk0H6qUFzmL3HHZev1htXuWDEEsqMTg= cloud.google.com/go/workflows v1.6.0/go.mod h1:6t9F5h/unJz41YqfBmqSASJSXccBLtD1Vwf+KmJENM0= cloud.google.com/go/workflows v1.7.0/go.mod h1:JhSrZuVZWuiDfKEFxU0/F1PQjmpnpcoISEXH2bcHC3M= -cosmossdk.io/api v0.7.4 h1:sPo8wKwCty1lht8kgL3J7YL1voJywP3YWuA5JKkBz30= -cosmossdk.io/api v0.7.4/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= +cosmossdk.io/api v0.7.5 h1:eMPTReoNmGUm8DeiQL9DyM8sYDjEhWzL1+nLbI9DqtQ= +cosmossdk.io/api v0.7.5/go.mod h1:IcxpYS5fMemZGqyYtErK7OqvdM0C8kdW3dq8Q/XIG38= cosmossdk.io/client/v2 v2.0.0-beta.1 h1:XkHh1lhrLYIT9zKl7cIOXUXg2hdhtjTPBUfqERNA1/Q= cosmossdk.io/client/v2 v2.0.0-beta.1/go.mod h1:JEUSu9moNZQ4kU3ir1DKD5eU4bllmAexrGWjmb9k8qU= cosmossdk.io/collections v0.4.0 h1:PFmwj2W8szgpD5nOd8GWH6AbYNi1f2J6akWXJ7P5t9s= @@ -210,8 +210,8 @@ cosmossdk.io/x/evidence v0.1.0 h1:J6OEyDl1rbykksdGynzPKG5R/zm6TacwW2fbLTW4nCk= cosmossdk.io/x/evidence v0.1.0/go.mod h1:hTaiiXsoiJ3InMz1uptgF0BnGqROllAN8mwisOMMsfw= cosmossdk.io/x/feegrant v0.1.0 h1:c7s3oAq/8/UO0EiN1H5BIjwVntujVTkYs35YPvvrdQk= cosmossdk.io/x/feegrant v0.1.0/go.mod h1:4r+FsViJRpcZif/yhTn+E0E6OFfg4n0Lx+6cCtnZElU= -cosmossdk.io/x/tx v0.13.2 h1:Kh90UH30bhnnUdJH+CmWLyaH8IKdY6BBGY3EkdOk82o= -cosmossdk.io/x/tx v0.13.2/go.mod h1:yhPokDCfXVIuAtyp49IFlWB5YAXUgD7Zek+ZHwsHzvU= +cosmossdk.io/x/tx v0.13.3 h1:Ha4mNaHmxBc6RMun9aKuqul8yHiL78EKJQ8g23Zf73g= +cosmossdk.io/x/tx v0.13.3/go.mod h1:I8xaHv0rhUdIvIdptKIqzYy27+n2+zBVaxO6fscFhys= cosmossdk.io/x/upgrade v0.1.1 h1:aoPe2gNvH+Gwt/Pgq3dOxxQVU3j5P6Xf+DaUJTDZATc= cosmossdk.io/x/upgrade v0.1.1/go.mod h1:MNLptLPcIFK9CWt7Ra//8WUZAxweyRDNcbs5nkOcQy0= dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU= @@ -373,8 +373,8 @@ github.com/cockroachdb/redact v1.1.5/go.mod h1:BVNblN9mBWFyMyqK1k3AAiSxhvhfK2oOZ github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06 h1:zuQyyAKVxetITBuuhv3BI9cMrmStnpT18zmgmTxunpo= github.com/cockroachdb/tokenbucket v0.0.0-20230807174530-cc333fc44b06/go.mod h1:7nc4anLGjupUW/PeY5qiNYsdNXj7zopG+eqsS7To5IQ= github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= -github.com/cometbft/cometbft v0.38.8 h1:XyJ9Cu3xqap6xtNxiemrO8roXZ+KS2Zlu7qQ0w1trvU= -github.com/cometbft/cometbft v0.38.8/go.mod h1:xOoGZrtUT+A5izWfHSJgl0gYZUE7lu7Z2XIS1vWG/QQ= +github.com/cometbft/cometbft v0.38.9 h1:cJBJBG0mPKz+sqelCi/hlfZjadZQGdDNnu6YQ1ZsUHQ= +github.com/cometbft/cometbft v0.38.9/go.mod h1:xOoGZrtUT+A5izWfHSJgl0gYZUE7lu7Z2XIS1vWG/QQ= github.com/cometbft/cometbft-db v0.9.1 h1:MIhVX5ja5bXNHF8EYrThkG9F7r9kSfv8BX4LWaxWJ4M= github.com/cometbft/cometbft-db v0.9.1/go.mod h1:iliyWaoV0mRwBJoizElCwwRA9Tf7jZJOURcRZF9m60U= github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= @@ -397,8 +397,8 @@ github.com/cosmos/cosmos-db v1.0.2 h1:hwMjozuY1OlJs/uh6vddqnk9j7VamLv+0DBlbEXbAK github.com/cosmos/cosmos-db v1.0.2/go.mod h1:Z8IXcFJ9PqKK6BIsVOB3QXtkKoqUOp1vRvPT39kOXEA= github.com/cosmos/cosmos-proto v1.0.0-beta.5 h1:eNcayDLpip+zVLRLYafhzLvQlSmyab+RC5W7ZfmxJLA= github.com/cosmos/cosmos-proto v1.0.0-beta.5/go.mod h1:hQGLpiIUloJBMdQMMWb/4wRApmI9hjHH05nefC0Ojec= -github.com/cosmos/cosmos-sdk v0.50.6 h1:efR3MsvMHX5sxS3be+hOobGk87IzlZbSpsI2x/Vw3hk= -github.com/cosmos/cosmos-sdk v0.50.6/go.mod h1:lVkRY6cdMJ0fG3gp8y4hFrsKZqF4z7y0M2UXFb9Yt40= +github.com/cosmos/cosmos-sdk v0.50.8 h1:2UJHssUaGHTl4/dFp8xyREKAnfiRU6VVfqtKG9n8w5g= +github.com/cosmos/cosmos-sdk v0.50.8/go.mod h1:Zb+DgHtiByNwgj71IlJBXwOq6dLhtyAq3AgqpXm/jHo= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= github.com/cosmos/gogogateway v1.2.0 h1:Ae/OivNhp8DqBi/sh2A8a1D0y638GpL3tkmLQAiKxTE= @@ -515,8 +515,8 @@ github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/gabriel-vasile/mimetype v1.4.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy+R0LnH8I= github.com/gabriel-vasile/mimetype v1.4.4/go.mod h1:JwLei5XPtWdGiMFB5Pjle1oEeoSeEuJfJE+TtfvdB/s= -github.com/getkin/kin-openapi v0.125.0 h1:jyQCyf2qXS1qvs2U00xQzkGCqYPhEhZDmSmVt65fXno= -github.com/getkin/kin-openapi v0.125.0/go.mod h1:wb1aSZA/iWmorQP9KTAS/phLj/t17B5jT7+fS8ed9NM= +github.com/getkin/kin-openapi v0.127.0 h1:Mghqi3Dhryf3F8vR370nN67pAERW+3a95vomb3MAREY= +github.com/getkin/kin-openapi v0.127.0/go.mod h1:OZrfXzUfGrNbsKj+xmFBx6E5c6yH3At/tAKSc2UszXM= github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps= github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -556,10 +556,10 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= -github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= -github.com/go-openapi/swag v0.22.8 h1:/9RjDSQ0vbFR+NyjGMkFTsA1IA0fmhKSThmfGZjicbw= -github.com/go-openapi/swag v0.22.8/go.mod h1:6QT22icPLEqAM/z/TChgb4WAveCHF92+2gF0CNjHpPI= +github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= +github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= +github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= +github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= @@ -853,8 +853,8 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= -github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY= -github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q= +github.com/invopop/yaml v0.3.1 h1:f0+ZpmhfBSS4MhG+4HYseMdJhoeeopbSKbq5Rpeelso= +github.com/invopop/yaml v0.3.1/go.mod h1:PMOp3nn4/12yEZUFfmOuNHJsZToEEOwoWsT+D81KkeA= github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs= github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0= github.com/ipfs/boxo v0.21.0 h1:XpGXb+TQQ0IUdYaeAxGzWjSs6ow/Lce148A/2IbRDVE= @@ -979,12 +979,12 @@ github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU= github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E= -github.com/lestrrat-go/httprc v1.0.5 h1:bsTfiH8xaKOJPrg1R+E3iE/AWZr/x0Phj9PBTG/OLUk= -github.com/lestrrat-go/httprc v1.0.5/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo= +github.com/lestrrat-go/httprc v1.0.6 h1:qgmgIRhpvBqexMJjA/PmwSvhNk679oqD1RbovdCGW8k= +github.com/lestrrat-go/httprc v1.0.6/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo= github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI= github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4= -github.com/lestrrat-go/jwx/v2 v2.1.0 h1:0zs7Ya6+39qoit7gwAf+cYm1zzgS3fceIdo7RmQ5lkw= -github.com/lestrrat-go/jwx/v2 v2.1.0/go.mod h1:Xpw9QIaUGiIUD1Wx0NcY1sIHwFf8lDuZn/cmxtXYRys= +github.com/lestrrat-go/jwx/v2 v2.1.1 h1:Y2ltVl8J6izLYFs54BVcpXLv5msSW4o8eXwnzZLI32E= +github.com/lestrrat-go/jwx/v2 v2.1.1/go.mod h1:4LvZg7oxu6Q5VJwn7Mk/UwooNRnTHUpXBj2C4j3HNx0= github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU= github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= @@ -1492,8 +1492,8 @@ github.com/valyala/fastjson v1.6.4 h1:uAUNq9Z6ymTgGhcm0UynUAB6tlbakBrz6CQFax3BXV github.com/valyala/fastjson v1.6.4/go.mod h1:CLCAqky6SMuOcxStkYQvblddUtoRxhYMGLrsQns1aXY= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= -github.com/vito/go-sse v1.0.0 h1:e6/iTrrvy8BRrOwJwmQmlndlil+TLdxXvHi55ZDzH6M= -github.com/vito/go-sse v1.0.0/go.mod h1:2wkcaQ+jtlZ94Uve8gYZjFpL68luAjssTINA2hpgcZs= +github.com/vito/go-sse v1.1.1 h1:9TlsS/xk9++g+W61ZR8dusNq2BAsqR1Kq8NhMfqpzGI= +github.com/vito/go-sse v1.1.1/go.mod h1:2wkcaQ+jtlZ94Uve8gYZjFpL68luAjssTINA2hpgcZs= github.com/warpfork/go-testmark v0.12.1 h1:rMgCpJfwy1sJ50x0M0NgyphxYYPMOODIJHhsXyEHU0s= github.com/warpfork/go-testmark v0.12.1/go.mod h1:kHwy7wfvGSPh1rQJYKayD4AbtNaeyZdcGi9tNJTaa5Y= github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ= @@ -1608,8 +1608,8 @@ golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98y golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= -golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= -golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= +golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= +golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1884,8 +1884,8 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= -golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= +golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1897,8 +1897,8 @@ golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= -golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= -golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= +golang.org/x/term v0.23.0 h1:F6D4vR+EHoL9/sWAWgAR1H2DcHr4PareCbAaCo1RpuU= +golang.org/x/term v0.23.0/go.mod h1:DgV24QBUrK6jhZXl+20l6UWznPlwAHm1Q1mGHtydmSk= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -2274,7 +2274,6 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= diff --git a/playground/package-lock.json b/playground/package-lock.json index 127c51617e..ebf9541943 100644 --- a/playground/package-lock.json +++ b/playground/package-lock.json @@ -18,14 +18,14 @@ "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@types/swagger-ui-react": "^4.18.3", - "@typescript-eslint/eslint-plugin": "^7.16.1", - "@typescript-eslint/parser": "^7.16.1", + "@typescript-eslint/eslint-plugin": "^8.0.1", + "@typescript-eslint/parser": "^8.0.1", "@vitejs/plugin-react-swc": "^3.7.0", "eslint": "^8.57.0", "eslint-plugin-react-hooks": "^4.6.2", - "eslint-plugin-react-refresh": "^0.4.7", - "typescript": "^5.5.3", - "vite": "^5.3.4" + "eslint-plugin-react-refresh": "^0.4.9", + "typescript": "^5.5.4", + "vite": "^5.3.5" } }, "node_modules/@babel/runtime": { @@ -102,262 +102,6 @@ "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", "optional": true }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@esbuild/linux-x64": { "version": "0.21.5", "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", @@ -374,102 +118,6 @@ "node": ">=12" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -1404,149 +1052,6 @@ "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz", "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==" }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.1.tgz", - "integrity": "sha512-lncuC4aHicncmbORnx+dUaAgzee9cm/PbIqgWz1PpXuwc+sa1Ct83tnqUDy/GFKleLiN7ZIeytM6KJ4cAn1SxA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.1.tgz", - "integrity": "sha512-F/tkdw0WSs4ojqz5Ovrw5r9odqzFjb5LIgHdHZG65dFI1lWTWRVy32KDJLKRISHgJvqUeUhdIvy43fX41znyDg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.1.tgz", - "integrity": "sha512-vk+ma8iC1ebje/ahpxpnrfVQJibTMyHdWpOGZ3JpQ7Mgn/3QNHmPq7YwjZbIE7km73dH5M1e6MRRsnEBW7v5CQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.1.tgz", - "integrity": "sha512-IgpzXKauRe1Tafcej9STjSSuG0Ghu/xGYH+qG6JwsAUxXrnkvNHcq/NL6nz1+jzvWAnQkuAJ4uIwGB48K9OCGA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.1.tgz", - "integrity": "sha512-P9bSiAUnSSM7EmyRK+e5wgpqai86QOSv8BwvkGjLwYuOpaeomiZWifEos517CwbG+aZl1T4clSE1YqqH2JRs+g==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.1.tgz", - "integrity": "sha512-5RnjpACoxtS+aWOI1dURKno11d7krfpGDEn19jI8BuWmSBbUC4ytIADfROM1FZrFhQPSoP+KEa3NlEScznBTyQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.1.tgz", - "integrity": "sha512-8mwmGD668m8WaGbthrEYZ9CBmPug2QPGWxhJxh/vCgBjro5o96gL04WLlg5BA233OCWLqERy4YUzX3bJGXaJgQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.1.tgz", - "integrity": "sha512-dJX9u4r4bqInMGOAQoGYdwDP8lQiisWb9et+T84l2WXk41yEej8v2iGKodmdKimT8cTAYt0jFb+UEBxnPkbXEQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.1.tgz", - "integrity": "sha512-V72cXdTl4EI0x6FNmho4D502sy7ed+LuVW6Ym8aI6DRQ9hQZdp5sj0a2usYOlqvFBNKQnLQGwmYnujo2HvjCxQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.1.tgz", - "integrity": "sha512-f+pJih7sxoKmbjghrM2RkWo2WHUW8UbfxIQiWo5yeCaCM0TveMEuAzKJte4QskBp1TIinpnRcxkquY+4WuY/tg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.1.tgz", - "integrity": "sha512-qb1hMMT3Fr/Qz1OKovCuUM11MUNLUuHeBC2DPPAWUYYUAOFWaxInaTwTQmc7Fl5La7DShTEpmYwgdt2hG+4TEg==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, "node_modules/@rollup/rollup-linux-x64-gnu": { "version": "4.18.1", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.1.tgz", @@ -1573,45 +1078,6 @@ "linux" ] }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.1.tgz", - "integrity": "sha512-W2ZNI323O/8pJdBGil1oCauuCzmVd9lDmWBBqxYZcOqWD6aWqJtVBQ1dFrF4dYpZPks6F+xCZHfzG5hYlSHZ6g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.1.tgz", - "integrity": "sha512-ELfEX1/+eGZYMaCIbK4jqLxO1gyTSOIlZr6pbC4SRYFaSIDVKOnZNMdoZ+ON0mrFDp4+H5MhwNC1H/AhE3zQLg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.18.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.1.tgz", - "integrity": "sha512-yjk2MAkQmoaPYCSu35RLJ62+dz358nE83VfTePJRp8CG7aMg25mEJYpXFiD+NcevhX8LxD5OP5tktPXnXN7GDw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, "node_modules/@swagger-api/apidom-ast": { "version": "1.0.0-alpha.6", "resolved": "https://registry.npmjs.org/@swagger-api/apidom-ast/-/apidom-ast-1.0.0-alpha.6.tgz", @@ -2107,86 +1573,6 @@ } } }, - "node_modules/@swc/core-darwin-arm64": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.0.tgz", - "integrity": "sha512-2ylhM7f0HwUwLrFYZAe/dse8PCbPsYcJS3Dt7Q8NT3PUn7vy6QOMxNcOPPuDrnmaXqQQO3oxdmRapguTxaat9g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-darwin-x64": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.0.tgz", - "integrity": "sha512-SgVnN4gT1Rb9YfTkp4FCUITqSs7Yj0uB2SUciu5CV3HuGvS5YXCUzh+KrwpLFtx8NIgivISKcNnb41mJi98X8Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.0.tgz", - "integrity": "sha512-+Z9Dayart1iKJQEJJ9N/KS4z5EdXJE3WPFikY0jonKTo4Dd8RuyVz5yLvqcIMeVdz/SwximATaL6iJXw7hZS9A==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.0.tgz", - "integrity": "sha512-UnLrCiZ1EI4shznJn0xP6DLgsXUSwtfsdgHhGYCrvbgVBBve3S9iFgVFEB3SPl7Q/TdowNbrN4zHU0oChfiNfw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.0.tgz", - "integrity": "sha512-H724UANA+ptsfwKRr9mnaDa9cb5fw0oFysiGKTgb3DMYcgk3Od0jMTnXVPFSVpo7FlmyxeC9K8ueUPBOoOK6XA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=10" - } - }, "node_modules/@swc/core-linux-x64-gnu": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.0.tgz", @@ -2219,54 +1605,6 @@ "node": ">=10" } }, - "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.0.tgz", - "integrity": "sha512-ecQOOmzEssz+m0pR4xDYCGuvn3E/l0nQ3tk5jp1NA1lsAy4bMV0YbYCHjptYvWL/UjhIerIp3IlCJ8x5DodSog==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.0.tgz", - "integrity": "sha512-gz81seZkRn3zMnVOc7L5k6F4vQC82gIxmHiL+GedK+A37XI/X26AASU3zxvORnqQbwQYXQ+AEVckxBmFlz3v2g==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, - "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.0.tgz", - "integrity": "sha512-b5Fd1xEOw9uqBpj2lqsaR4Iq9UhiL84hNDcEsi6DQA7Y1l85waQAslTbS0E4/pJ1PISAs0jW0zIGLco1eaWBOg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=10" - } - }, "node_modules/@swc/counter": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", @@ -2389,31 +1727,31 @@ "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==" }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.1.tgz", - "integrity": "sha512-SxdPak/5bO0EnGktV05+Hq8oatjAYVY3Zh2bye9pGZy6+jwyR3LG3YKkV4YatlsgqXP28BTeVm9pqwJM96vf2A==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.0.1.tgz", + "integrity": "sha512-5g3Y7GDFsJAnY4Yhvk8sZtFfV6YNF2caLzjrRPUBzewjPCaj0yokePB4LJSobyCzGMzjZZYFbwuzbfDHlimXbQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.16.1", - "@typescript-eslint/type-utils": "7.16.1", - "@typescript-eslint/utils": "7.16.1", - "@typescript-eslint/visitor-keys": "7.16.1", + "@typescript-eslint/scope-manager": "8.0.1", + "@typescript-eslint/type-utils": "8.0.1", + "@typescript-eslint/utils": "8.0.1", + "@typescript-eslint/visitor-keys": "8.0.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -2422,26 +1760,26 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.1.tgz", - "integrity": "sha512-u+1Qx86jfGQ5i4JjK33/FnawZRpsLxRnKzGE6EABZ40KxVT/vWsiZFEBBHjFOljmmV3MBYOHEKi0Jm9hbAOClA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.0.1.tgz", + "integrity": "sha512-5IgYJ9EO/12pOUwiBKFkpU7rS3IU21mtXzB81TNwq2xEybcmAZrE9qwDtsb5uQd9aVO9o0fdabFyAmKveXyujg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.16.1", - "@typescript-eslint/types": "7.16.1", - "@typescript-eslint/typescript-estree": "7.16.1", - "@typescript-eslint/visitor-keys": "7.16.1", + "@typescript-eslint/scope-manager": "8.0.1", + "@typescript-eslint/types": "8.0.1", + "@typescript-eslint/typescript-estree": "8.0.1", + "@typescript-eslint/visitor-keys": "8.0.1", "debug": "^4.3.4" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0" }, "peerDependenciesMeta": { "typescript": { @@ -2450,16 +1788,16 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.1.tgz", - "integrity": "sha512-nYpyv6ALte18gbMz323RM+vpFpTjfNdyakbf3nsLvF43uF9KeNC289SUEW3QLZ1xPtyINJ1dIsZOuWuSRIWygw==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.0.1.tgz", + "integrity": "sha512-NpixInP5dm7uukMiRyiHjRKkom5RIFA4dfiHvalanD2cF0CLUuQqxfg8PtEUo9yqJI2bBhF+pcSafqnG3UBnRQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.1", - "@typescript-eslint/visitor-keys": "7.16.1" + "@typescript-eslint/types": "8.0.1", + "@typescript-eslint/visitor-keys": "8.0.1" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -2467,26 +1805,23 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.1.tgz", - "integrity": "sha512-rbu/H2MWXN4SkjIIyWcmYBjlp55VT+1G3duFOIukTNFxr9PI35pLc2ydwAfejCEitCv4uztA07q0QWanOHC7dA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.0.1.tgz", + "integrity": "sha512-+/UT25MWvXeDX9YaHv1IS6KI1fiuTto43WprE7pgSMswHbn1Jm9GEM4Txp+X74ifOWV8emu2AWcbLhpJAvD5Ng==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.16.1", - "@typescript-eslint/utils": "7.16.1", + "@typescript-eslint/typescript-estree": "8.0.1", + "@typescript-eslint/utils": "8.0.1", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependencies": { - "eslint": "^8.56.0" - }, "peerDependenciesMeta": { "typescript": { "optional": true @@ -2494,12 +1829,12 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.1.tgz", - "integrity": "sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.0.1.tgz", + "integrity": "sha512-PpqTVT3yCA/bIgJ12czBuE3iBlM3g4inRSC5J0QOdQFAn07TYrYEQBBKgXH1lQpglup+Zy6c1fxuwTk4MTNKIw==", "dev": true, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -2507,13 +1842,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.1.tgz", - "integrity": "sha512-0vFPk8tMjj6apaAZ1HlwM8w7jbghC8jc1aRNJG5vN8Ym5miyhTQGMqU++kuBFDNKe9NcPeZ6x0zfSzV8xC1UlQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.0.1.tgz", + "integrity": "sha512-8V9hriRvZQXPWU3bbiUV4Epo7EvgM6RTs+sUmxp5G//dBGy402S7Fx0W0QkB2fb4obCF8SInoUzvTYtc3bkb5w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.1", - "@typescript-eslint/visitor-keys": "7.16.1", + "@typescript-eslint/types": "8.0.1", + "@typescript-eslint/visitor-keys": "8.0.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2522,7 +1857,7 @@ "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -2535,38 +1870,38 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.1.tgz", - "integrity": "sha512-WrFM8nzCowV0he0RlkotGDujx78xudsxnGMBHI88l5J8wEhED6yBwaSLP99ygfrzAjsQvcYQ94quDwI0d7E1fA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.0.1.tgz", + "integrity": "sha512-CBFR0G0sCt0+fzfnKaciu9IBsKvEKYwN9UZ+eeogK1fYHg4Qxk1yf/wLQkLXlq8wbU2dFlgAesxt8Gi76E8RTA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.16.1", - "@typescript-eslint/types": "7.16.1", - "@typescript-eslint/typescript-estree": "7.16.1" + "@typescript-eslint/scope-manager": "8.0.1", + "@typescript-eslint/types": "8.0.1", + "@typescript-eslint/typescript-estree": "8.0.1" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.16.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.1.tgz", - "integrity": "sha512-Qlzzx4sE4u3FsHTPQAAQFJFNOuqtuY0LFrZHwQ8IHK705XxBiWOFkfKRWu6niB7hwfgnwIpO4jTC75ozW1PHWg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.0.1.tgz", + "integrity": "sha512-W5E+o0UfUcK5EgchLZsyVWqARmsM7v54/qEq6PY3YI5arkgmCzHiuk0zKSJJbm71V0xdRna4BGomkCTXz2/LkQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.1", + "@typescript-eslint/types": "8.0.1", "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -3286,9 +2621,9 @@ } }, "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.8", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.8.tgz", - "integrity": "sha512-MIKAclwaDFIiYtVBLzDdm16E+Ty4GwhB6wZlCAG1R3Ur+F9Qbo6PRxpA5DK7XtDgm+WlCoAY2WxAwqhmIDHg6Q==", + "version": "0.4.9", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.9.tgz", + "integrity": "sha512-QK49YrBAo5CLNLseZ7sZgvgTy21E6NEw22eZqc4teZfH8pxV3yXc9XXOYfUI6JNpw7mfHNkAeWtBxrTyykB6HA==", "dev": true, "peerDependencies": { "eslint": ">=7" @@ -3624,20 +2959,6 @@ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -5797,9 +5118,9 @@ } }, "node_modules/typescript": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", - "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", + "version": "5.5.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", + "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -5893,9 +5214,9 @@ "optional": true }, "node_modules/vite": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.4.tgz", - "integrity": "sha512-Cw+7zL3ZG9/NZBB8C+8QbQZmR54GwqIz+WMI4b3JgdYJvX+ny9AjJXqkGQlDXSXRP9rP0B4tbciRMOVEKulVOA==", + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.3.5.tgz", + "integrity": "sha512-MdjglKR6AQXQb9JGiS7Rc2wC6uMjcm7Go/NHNO63EwiJXfuk9PgqiP/n5IDJCziMkfw9n4Ubp7lttNwz+8ZVKA==", "dev": true, "dependencies": { "esbuild": "^0.21.3", diff --git a/playground/package.json b/playground/package.json index b8b263a9a3..0e44c066ed 100644 --- a/playground/package.json +++ b/playground/package.json @@ -20,13 +20,13 @@ "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", "@types/swagger-ui-react": "^4.18.3", - "@typescript-eslint/eslint-plugin": "^7.16.1", - "@typescript-eslint/parser": "^7.16.1", + "@typescript-eslint/eslint-plugin": "^8.0.1", + "@typescript-eslint/parser": "^8.0.1", "@vitejs/plugin-react-swc": "^3.7.0", "eslint": "^8.57.0", "eslint-plugin-react-hooks": "^4.6.2", - "eslint-plugin-react-refresh": "^0.4.7", - "typescript": "^5.5.3", - "vite": "^5.3.4" + "eslint-plugin-react-refresh": "^0.4.9", + "typescript": "^5.5.4", + "vite": "^5.3.5" } } diff --git a/tests/integration/query/inline_array/simple_test.go b/tests/integration/query/inline_array/simple_test.go index f266b114ba..7b2435e5fe 100644 --- a/tests/integration/query/inline_array/simple_test.go +++ b/tests/integration/query/inline_array/simple_test.go @@ -19,78 +19,84 @@ import ( ) func TestQueryInlineArrayWithBooleans(t *testing.T) { - tests := []testUtils.RequestTestCase{ + tests := []testUtils.TestCase{ { Description: "Simple inline array with no filter, nil boolean array", - Request: `query { - Users { - name - likedIndexes - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "name": "John", "likedIndexes": null }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "likedIndexes": nil, + testUtils.Request{ + Request: `query { + Users { + name + likedIndexes + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "likedIndexes": nil, + }, + }, }, }, }, }, { Description: "Simple inline array with no filter, empty boolean array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "likedIndexes": [] + }`, + }, + testUtils.Request{ + Request: `query { Users { name likedIndexes } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "likedIndexes": [] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "likedIndexes": []bool{}, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "likedIndexes": []bool{}, + }, + }, }, }, }, }, { Description: "Simple inline array with no filter, booleans", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "likedIndexes": [true, true, false, true] + }`, + }, + testUtils.Request{ + Request: `query { Users { name likedIndexes } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "likedIndexes": [true, true, false, true] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "likedIndexes": []bool{true, true, false, true}, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "likedIndexes": []bool{true, true, false, true}, + }, + }, }, }, }, @@ -103,31 +109,33 @@ func TestQueryInlineArrayWithBooleans(t *testing.T) { } func TestQueryInlineArrayWithNillableBooleans(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, booleans", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "indexLikesDislikes": [true, true, false, null] + }`, + }, + testUtils.Request{ + Request: `query { Users { name indexLikesDislikes } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "indexLikesDislikes": [true, true, false, null] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "indexLikesDislikes": []immutable.Option[bool]{ - immutable.Some(true), - immutable.Some(true), - immutable.Some(false), - immutable.None[bool](), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "indexLikesDislikes": []immutable.Option[bool]{ + immutable.Some(true), + immutable.Some(true), + immutable.Some(false), + immutable.None[bool](), + }, + }, }, }, }, @@ -138,152 +146,164 @@ func TestQueryInlineArrayWithNillableBooleans(t *testing.T) { } func TestQueryInlineArrayWithIntegers(t *testing.T) { - tests := []testUtils.RequestTestCase{ + tests := []testUtils.TestCase{ { Description: "Simple inline array with no filter, default integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John" + }`, + }, + testUtils.Request{ + Request: `query { Users { name favouriteIntegers } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John" - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "favouriteIntegers": nil, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "favouriteIntegers": nil, + }, + }, }, }, }, }, { Description: "Simple inline array with no filter, nil integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteIntegers": null + }`, + }, + testUtils.Request{ + Request: `query { Users { name favouriteIntegers } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteIntegers": null - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "favouriteIntegers": nil, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "favouriteIntegers": nil, + }, + }, }, }, }, }, { Description: "Simple inline array with no filter, empty integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteIntegers": [] + }`, + }, + testUtils.Request{ + Request: `query { Users { name favouriteIntegers } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteIntegers": [] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "favouriteIntegers": []int64{}, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "favouriteIntegers": []int64{}, + }, + }, }, }, }, }, { Description: "Simple inline array with no filter, positive integers", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteIntegers": [1, 2, 3, 5, 8] + }`, + }, + testUtils.Request{ + Request: `query { Users { name favouriteIntegers } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteIntegers": [1, 2, 3, 5, 8] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "favouriteIntegers": []int64{1, 2, 3, 5, 8}, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "favouriteIntegers": []int64{1, 2, 3, 5, 8}, + }, + }, }, }, }, }, { Description: "Simple inline array with no filter, negative integers", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Andy", + "favouriteIntegers": [-1, -2, -3, -5, -8] + }`, + }, + testUtils.Request{ + Request: `query { Users { name favouriteIntegers } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Andy", - "favouriteIntegers": [-1, -2, -3, -5, -8] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Andy", - "favouriteIntegers": []int64{-1, -2, -3, -5, -8}, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Andy", + "favouriteIntegers": []int64{-1, -2, -3, -5, -8}, + }, + }, }, }, }, }, { Description: "Simple inline array with no filter, mixed integers", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "favouriteIntegers": [-1, 2, -1, 1, 0] + }`, + }, + testUtils.Request{ + Request: `query { Users { name favouriteIntegers } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "favouriteIntegers": [-1, 2, -1, 1, 0] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "favouriteIntegers": []int64{-1, 2, -1, 1, 0}, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "favouriteIntegers": []int64{-1, 2, -1, 1, 0}, + }, + }, }, }, }, @@ -296,32 +316,34 @@ func TestQueryInlineArrayWithIntegers(t *testing.T) { } func TestQueryInlineArrayWithNillableInts(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, nillable ints", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "testScores": [-1, null, -1, 2, 0] + }`, + }, + testUtils.Request{ + Request: `query { Users { name testScores } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "testScores": [-1, null, -1, 2, 0] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "testScores": []immutable.Option[int64]{ - immutable.Some[int64](-1), - immutable.None[int64](), - immutable.Some[int64](-1), - immutable.Some[int64](2), - immutable.Some[int64](0), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "testScores": []immutable.Option[int64]{ + immutable.Some[int64](-1), + immutable.None[int64](), + immutable.Some[int64](-1), + immutable.Some[int64](2), + immutable.Some[int64](0), + }, + }, }, }, }, @@ -332,78 +354,84 @@ func TestQueryInlineArrayWithNillableInts(t *testing.T) { } func TestQueryInlineArrayWithFloats(t *testing.T) { - tests := []testUtils.RequestTestCase{ + tests := []testUtils.TestCase{ { Description: "Simple inline array with no filter, nil float array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteFloats": null + }`, + }, + testUtils.Request{ + Request: `query { Users { name favouriteFloats } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteFloats": null - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "favouriteFloats": nil, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "favouriteFloats": nil, + }, + }, }, }, }, }, { Description: "Simple inline array with no filter, empty float array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteFloats": [] + }`, + }, + testUtils.Request{ + Request: `query { Users { name favouriteFloats } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteFloats": [] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "favouriteFloats": []float64{}, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "favouriteFloats": []float64{}, + }, + }, }, }, }, }, { Description: "Simple inline array with no filter, positive floats", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteFloats": [3.1425, 0.00000000001, 10] + }`, + }, + testUtils.Request{ + Request: `query { Users { name favouriteFloats } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteFloats": [3.1425, 0.00000000001, 10] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "favouriteFloats": []float64{3.1425, 0.00000000001, 10}, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "favouriteFloats": []float64{3.1425, 0.00000000001, 10}, + }, + }, }, }, }, @@ -416,31 +444,33 @@ func TestQueryInlineArrayWithFloats(t *testing.T) { } func TestQueryInlineArrayWithNillableFloats(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, nillable floats", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "pageRatings": [3.1425, null, -0.00000000001, 10] + }`, + }, + testUtils.Request{ + Request: `query { Users { name pageRatings } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "pageRatings": [3.1425, null, -0.00000000001, 10] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "pageRatings": []immutable.Option[float64]{ - immutable.Some(3.1425), - immutable.None[float64](), - immutable.Some(-0.00000000001), - immutable.Some[float64](10), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "pageRatings": []immutable.Option[float64]{ + immutable.Some(3.1425), + immutable.None[float64](), + immutable.Some(-0.00000000001), + immutable.Some[float64](10), + }, + }, }, }, }, @@ -451,78 +481,84 @@ func TestQueryInlineArrayWithNillableFloats(t *testing.T) { } func TestQueryInlineArrayWithStrings(t *testing.T) { - tests := []testUtils.RequestTestCase{ + tests := []testUtils.TestCase{ { Description: "Simple inline array with no filter, nil string array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "preferredStrings": null + }`, + }, + testUtils.Request{ + Request: `query { Users { name preferredStrings } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "preferredStrings": null - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "preferredStrings": nil, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "preferredStrings": nil, + }, + }, }, }, }, }, { Description: "Simple inline array with no filter, empty string array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "preferredStrings": [] + }`, + }, + testUtils.Request{ + Request: `query { Users { name preferredStrings } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "preferredStrings": [] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "preferredStrings": []string{}, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "preferredStrings": []string{}, + }, + }, }, }, }, }, { Description: "Simple inline array with no filter, strings", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "preferredStrings": ["", "the previous", "the first", "empty string"] + }`, + }, + testUtils.Request{ + Request: `query { Users { name preferredStrings } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "preferredStrings": ["", "the previous", "the first", "empty string"] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "preferredStrings": []string{"", "the previous", "the first", "empty string"}, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "preferredStrings": []string{"", "the previous", "the first", "empty string"}, + }, + }, }, }, }, @@ -535,32 +571,34 @@ func TestQueryInlineArrayWithStrings(t *testing.T) { } func TestQueryInlineArrayWithNillableString(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, nillable strings", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "pageHeaders": ["", "the previous", "the first", "empty string", null] + }`, + }, + testUtils.Request{ + Request: `query { Users { name pageHeaders } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "pageHeaders": ["", "the previous", "the first", "empty string", null] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "pageHeaders": []immutable.Option[string]{ - immutable.Some(""), - immutable.Some("the previous"), - immutable.Some("the first"), - immutable.Some("empty string"), - immutable.None[string](), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "pageHeaders": []immutable.Option[string]{ + immutable.Some(""), + immutable.Some("the previous"), + immutable.Some("the first"), + immutable.Some("empty string"), + immutable.None[string](), + }, + }, }, }, }, diff --git a/tests/integration/query/inline_array/utils.go b/tests/integration/query/inline_array/utils.go index 924cc45577..90f359b6d2 100644 --- a/tests/integration/query/inline_array/utils.go +++ b/tests/integration/query/inline_array/utils.go @@ -30,6 +30,19 @@ var userCollectionGQLSchema = (` } `) -func executeTestCase(t *testing.T, test testUtils.RequestTestCase) { - testUtils.ExecuteRequestTestCase(t, userCollectionGQLSchema, []string{"Users"}, test) +func executeTestCase(t *testing.T, test testUtils.TestCase) { + testUtils.ExecuteTestCase( + t, + testUtils.TestCase{ + Description: test.Description, + Actions: append( + []any{ + testUtils.SchemaUpdate{ + Schema: userCollectionGQLSchema, + }, + }, + test.Actions..., + ), + }, + ) } diff --git a/tests/integration/query/inline_array/with_average_filter_test.go b/tests/integration/query/inline_array/with_average_filter_test.go index cac50ea81c..f89b7e7835 100644 --- a/tests/integration/query/inline_array/with_average_filter_test.go +++ b/tests/integration/query/inline_array/with_average_filter_test.go @@ -17,27 +17,29 @@ import ( ) func TestQueryInlineIntegerArrayWithAverageWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, filtered average of integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "favouriteIntegers": [-1, 2, -1, 1, 0] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _avg(favouriteIntegers: {filter: {_gt: 0}}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "favouriteIntegers": [-1, 2, -1, 1, 0] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_avg": float64(1.5), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_avg": float64(1.5), + }, + }, }, }, }, @@ -47,27 +49,29 @@ func TestQueryInlineIntegerArrayWithAverageWithFilter(t *testing.T) { } func TestQueryInlineNillableIntegerArrayWithAverageWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with filter, average of populated nillable integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "testScores": [-1, null, 13, 0] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _avg(testScores: {filter: {_gt: -1}}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "testScores": [-1, null, 13, 0] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "_avg": float64(6.5), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "_avg": float64(6.5), + }, + }, }, }, }, @@ -77,27 +81,29 @@ func TestQueryInlineNillableIntegerArrayWithAverageWithFilter(t *testing.T) { } func TestQueryInlineFloatArrayWithAverageWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, filtered average of float array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "favouriteFloats": [3.4, 3.6, 10] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _avg(favouriteFloats: {filter: {_lt: 9}}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "favouriteFloats": [3.4, 3.6, 10] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_avg": 3.5, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_avg": 3.5, + }, + }, }, }, }, @@ -107,27 +113,29 @@ func TestQueryInlineFloatArrayWithAverageWithFilter(t *testing.T) { } func TestQueryInlineNillableFloatArrayWithAverageWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, filtered average of nillable float array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "pageRatings": [3.4, 3.6, 10, null] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _avg(pageRatings: {filter: {_lt: 9}}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "pageRatings": [3.4, 3.6, 10, null] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_avg": 3.5, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_avg": 3.5, + }, + }, }, }, }, diff --git a/tests/integration/query/inline_array/with_average_sum_test.go b/tests/integration/query/inline_array/with_average_sum_test.go index a6474d8f03..b9d2098c9f 100644 --- a/tests/integration/query/inline_array/with_average_sum_test.go +++ b/tests/integration/query/inline_array/with_average_sum_test.go @@ -21,29 +21,31 @@ import ( // verify that that code path is taken, but it does verfiy that the correct result // is returned to the consumer in case the more efficient code path is taken. func TestQueryInlineIntegerArrayWithAverageAndSum(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, average and sum of populated integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteIntegers": [-1, 0, 9, 0] + }`, + }, + testUtils.Request{ + Request: `query { Users(groupBy: [name]) { name _avg(favouriteIntegers: {}) _sum(favouriteIntegers: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteIntegers": [-1, 0, 9, 0] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "_avg": float64(2), - "_sum": int64(8), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "_avg": float64(2), + "_sum": int64(8), + }, + }, }, }, }, diff --git a/tests/integration/query/inline_array/with_average_test.go b/tests/integration/query/inline_array/with_average_test.go index bd5eeec041..376d6efd5b 100644 --- a/tests/integration/query/inline_array/with_average_test.go +++ b/tests/integration/query/inline_array/with_average_test.go @@ -17,27 +17,29 @@ import ( ) func TestQueryInlineIntegerArrayWithAverageAndNullArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, average of nil integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteIntegers": null + }`, + }, + testUtils.Request{ + Request: `query { Users { name _avg(favouriteIntegers: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteIntegers": null - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "_avg": float64(0), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "_avg": float64(0), + }, + }, }, }, }, @@ -47,27 +49,29 @@ func TestQueryInlineIntegerArrayWithAverageAndNullArray(t *testing.T) { } func TestQueryInlineIntegerArrayWithAverageAndEmptyArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, average of empty integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteIntegers": [] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _avg(favouriteIntegers: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteIntegers": [] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "_avg": float64(0), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "_avg": float64(0), + }, + }, }, }, }, @@ -77,27 +81,29 @@ func TestQueryInlineIntegerArrayWithAverageAndEmptyArray(t *testing.T) { } func TestQueryInlineIntegerArrayWithAverageAndZeroArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, average of zero integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteIntegers": [0, 0, 0] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _avg(favouriteIntegers: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteIntegers": [0, 0, 0] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "_avg": float64(0), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "_avg": float64(0), + }, + }, }, }, }, @@ -107,27 +113,29 @@ func TestQueryInlineIntegerArrayWithAverageAndZeroArray(t *testing.T) { } func TestQueryInlineIntegerArrayWithAverageAndPopulatedArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, average of populated integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteIntegers": [-1, 0, 9, 0] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _avg(favouriteIntegers: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteIntegers": [-1, 0, 9, 0] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "_avg": float64(2), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "_avg": float64(2), + }, + }, }, }, }, @@ -137,27 +145,29 @@ func TestQueryInlineIntegerArrayWithAverageAndPopulatedArray(t *testing.T) { } func TestQueryInlineNillableIntegerArrayWithAverageAndPopulatedArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, average of populated nillable integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "testScores": [-1, null, 13, 0] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _avg(testScores: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "testScores": [-1, null, 13, 0] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "_avg": float64(4), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "_avg": float64(4), + }, + }, }, }, }, @@ -167,27 +177,29 @@ func TestQueryInlineNillableIntegerArrayWithAverageAndPopulatedArray(t *testing. } func TestQueryInlineFloatArrayWithAverageAndNullArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, average of nil float array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteFloats": null + }`, + }, + testUtils.Request{ + Request: `query { Users { name _avg(favouriteFloats: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteFloats": null - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "_avg": float64(0), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "_avg": float64(0), + }, + }, }, }, }, @@ -197,27 +209,29 @@ func TestQueryInlineFloatArrayWithAverageAndNullArray(t *testing.T) { } func TestQueryInlineFloatArrayWithAverageAndEmptyArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, average of empty float array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteFloats": [] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _avg(favouriteFloats: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteFloats": [] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "_avg": float64(0), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "_avg": float64(0), + }, + }, }, }, }, @@ -227,28 +241,30 @@ func TestQueryInlineFloatArrayWithAverageAndEmptyArray(t *testing.T) { } func TestQueryInlineFloatArrayWithAverageAndZeroArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, average of zero float array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteFloats": [0, 0, 0] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _avg(favouriteFloats: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteFloats": [0, 0, 0] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { + Results: map[string]any{ + "Users": []map[string]any{ + { - "name": "John", - "_avg": float64(0), + "name": "John", + "_avg": float64(0), + }, + }, }, }, }, @@ -258,27 +274,29 @@ func TestQueryInlineFloatArrayWithAverageAndZeroArray(t *testing.T) { } func TestQueryInlineFloatArrayWithAverageAndPopulatedArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, average of populated float array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteFloats": [-0.1, 0, 0.9, 0] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _avg(favouriteFloats: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteFloats": [-0.1, 0, 0.9, 0] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "_avg": float64(0.2), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "_avg": float64(0.2), + }, + }, }, }, }, @@ -288,27 +306,29 @@ func TestQueryInlineFloatArrayWithAverageAndPopulatedArray(t *testing.T) { } func TestQueryInlineNillableFloatArrayWithAverageAndPopulatedArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, average of populated nillable float array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "pageRatings": [-0.1, 0, 0.9, 0, null] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _avg(pageRatings: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "pageRatings": [-0.1, 0, 0.9, 0, null] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "_avg": float64(0.2), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "_avg": float64(0.2), + }, + }, }, }, }, diff --git a/tests/integration/query/inline_array/with_count_filter_test.go b/tests/integration/query/inline_array/with_count_filter_test.go index c8c81f82e2..c35fd6f1c0 100644 --- a/tests/integration/query/inline_array/with_count_filter_test.go +++ b/tests/integration/query/inline_array/with_count_filter_test.go @@ -17,27 +17,29 @@ import ( ) func TestQueryInlineBoolArrayWithCountWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, filtered count of bool array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "likedIndexes": [true, true, false, true] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _count(likedIndexes: {filter: {_eq: true}}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "likedIndexes": [true, true, false, true] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_count": 3, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_count": 3, + }, + }, }, }, }, @@ -47,27 +49,29 @@ func TestQueryInlineBoolArrayWithCountWithFilter(t *testing.T) { } func TestQueryInlineNillableBoolArrayWithCountWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with filter, count of nillable bool array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "indexLikesDislikes": [true, true, false, null] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _count(indexLikesDislikes: {filter: {_eq: true}}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "indexLikesDislikes": [true, true, false, null] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "_count": 2, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "_count": 2, + }, + }, }, }, }, @@ -77,27 +81,29 @@ func TestQueryInlineNillableBoolArrayWithCountWithFilter(t *testing.T) { } func TestQueryInlineIntegerArrayWithCountWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, filtered count of integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "favouriteIntegers": [-1, 2, -1, 1, 0] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _count(favouriteIntegers: {filter: {_gt: 0}}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "favouriteIntegers": [-1, 2, -1, 1, 0] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_count": 2, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_count": 2, + }, + }, }, }, }, @@ -107,27 +113,29 @@ func TestQueryInlineIntegerArrayWithCountWithFilter(t *testing.T) { } func TestQueryInlineNillableIntegerArrayWithCountWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, filtered count of integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "testScores": [-1, 2, 1, null, 0] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _count(testScores: {filter: {_gt: 0}}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "testScores": [-1, 2, 1, null, 0] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_count": 2, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_count": 2, + }, + }, }, }, }, @@ -137,26 +145,29 @@ func TestQueryInlineNillableIntegerArrayWithCountWithFilter(t *testing.T) { } func TestQueryInlineIntegerArrayWithsWithCountWithAndFilterAndPopulatedArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, filtered count of integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "favouriteIntegers": [-1, 2, -1, 1, 0, -2] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _count(favouriteIntegers: {filter: {_and: [{_gt: -2}, {_lt: 2}]}}) } }`, - Docs: map[int][]string{ - 0: { - (`{ - "name": "Shahzad", - "favouriteIntegers": [-1, 2, -1, 1, 0, -2] - }`)}, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_count": 4, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_count": 4, + }, + }, }, }, }, @@ -166,27 +177,29 @@ func TestQueryInlineIntegerArrayWithsWithCountWithAndFilterAndPopulatedArray(t * } func TestQueryInlineFloatArrayWithCountWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, filtered count of float array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "favouriteFloats": [3.1425, 0.00000000001, 10] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _count(favouriteFloats: {filter: {_lt: 9}}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "favouriteFloats": [3.1425, 0.00000000001, 10] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_count": 2, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_count": 2, + }, + }, }, }, }, @@ -196,27 +209,29 @@ func TestQueryInlineFloatArrayWithCountWithFilter(t *testing.T) { } func TestQueryInlineNillableFloatArrayWithCountWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, filtered count of nillable float array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "pageRatings": [3.1425, 0.00000000001, 10, null] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _count(pageRatings: {filter: {_lt: 9}}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "pageRatings": [3.1425, 0.00000000001, 10, null] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_count": 2, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_count": 2, + }, + }, }, }, }, @@ -226,27 +241,29 @@ func TestQueryInlineNillableFloatArrayWithCountWithFilter(t *testing.T) { } func TestQueryInlineStringArrayWithCountWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, filtered count of string array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "preferredStrings": ["", "the previous", "the first", "empty string"] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _count(preferredStrings: {filter: {_in: ["", "the first"]}}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "preferredStrings": ["", "the previous", "the first", "empty string"] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_count": 2, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_count": 2, + }, + }, }, }, }, @@ -256,27 +273,29 @@ func TestQueryInlineStringArrayWithCountWithFilter(t *testing.T) { } func TestQueryInlineNillableStringArrayWithCountWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, filtered count of string array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "pageHeaders": ["", "the previous", null, "empty string"] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _count(pageHeaders: {filter: {_in: ["", "the first", "empty string"]}}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "pageHeaders": ["", "the previous", null, "empty string"] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_count": 2, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_count": 2, + }, + }, }, }, }, diff --git a/tests/integration/query/inline_array/with_count_limit_offset_test.go b/tests/integration/query/inline_array/with_count_limit_offset_test.go index d1e04b43ed..ebf3ee52b6 100644 --- a/tests/integration/query/inline_array/with_count_limit_offset_test.go +++ b/tests/integration/query/inline_array/with_count_limit_offset_test.go @@ -17,27 +17,29 @@ import ( ) func TestQueryInlineIntegerArrayWithCountWithOffsetWithLimitGreaterThanLength(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, offsetted limited count of integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "favouriteIntegers": [-1, 2, 3] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _count(favouriteIntegers: {offset: 1, limit: 3}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "favouriteIntegers": [-1, 2, 3] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_count": 2, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_count": 2, + }, + }, }, }, }, @@ -47,27 +49,29 @@ func TestQueryInlineIntegerArrayWithCountWithOffsetWithLimitGreaterThanLength(t } func TestQueryInlineIntegerArrayWithCountWithOffsetWithLimit(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, offsetted limited count of integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "favouriteIntegers": [-1, 2, -1, 1, 0] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _count(favouriteIntegers: {offset: 1, limit: 3}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "favouriteIntegers": [-1, 2, -1, 1, 0] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_count": 3, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_count": 3, + }, + }, }, }, }, diff --git a/tests/integration/query/inline_array/with_count_limit_test.go b/tests/integration/query/inline_array/with_count_limit_test.go index 09354ecc8c..11aab3e99a 100644 --- a/tests/integration/query/inline_array/with_count_limit_test.go +++ b/tests/integration/query/inline_array/with_count_limit_test.go @@ -17,27 +17,29 @@ import ( ) func TestQueryInlineIntegerArrayWithCountWithLimitGreaterThanLength(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, limited count of integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "favouriteIntegers": [-1, 2] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _count(favouriteIntegers: {limit: 3}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "favouriteIntegers": [-1, 2] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_count": 2, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_count": 2, + }, + }, }, }, }, @@ -47,27 +49,29 @@ func TestQueryInlineIntegerArrayWithCountWithLimitGreaterThanLength(t *testing.T } func TestQueryInlineIntegerArrayWithCountWithLimit(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, limited count of integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "favouriteIntegers": [-1, 2, -1, 1, 0] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _count(favouriteIntegers: {limit: 3}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "favouriteIntegers": [-1, 2, -1, 1, 0] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_count": 3, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_count": 3, + }, + }, }, }, }, diff --git a/tests/integration/query/inline_array/with_count_test.go b/tests/integration/query/inline_array/with_count_test.go index 40401e1cce..d0c13d2886 100644 --- a/tests/integration/query/inline_array/with_count_test.go +++ b/tests/integration/query/inline_array/with_count_test.go @@ -17,27 +17,29 @@ import ( ) func TestQueryInlineIntegerArrayWithCountAndNullArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, count of nil integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteIntegers": null + }`, + }, + testUtils.Request{ + Request: `query { Users { name _count(favouriteIntegers: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteIntegers": null - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "_count": 0, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "_count": 0, + }, + }, }, }, }, @@ -47,27 +49,29 @@ func TestQueryInlineIntegerArrayWithCountAndNullArray(t *testing.T) { } func TestQueryInlineIntegerArrayWithCountAndEmptyArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, count of empty integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteIntegers": [] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _count(favouriteIntegers: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteIntegers": [] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "_count": 0, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "_count": 0, + }, + }, }, }, }, @@ -77,27 +81,29 @@ func TestQueryInlineIntegerArrayWithCountAndEmptyArray(t *testing.T) { } func TestQueryInlineIntegerArrayWithCountAndPopulatedArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, count of integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "favouriteIntegers": [-1, 2, -1, 1, 0] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _count(favouriteIntegers: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "favouriteIntegers": [-1, 2, -1, 1, 0] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_count": 5, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_count": 5, + }, + }, }, }, }, @@ -107,27 +113,29 @@ func TestQueryInlineIntegerArrayWithCountAndPopulatedArray(t *testing.T) { } func TestQueryInlineNillableBoolArrayWithCountAndPopulatedArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, count of nillable bool array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "indexLikesDislikes": [true, true, false, null] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _count(indexLikesDislikes: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "indexLikesDislikes": [true, true, false, null] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "_count": 4, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "_count": 4, + }, + }, }, }, }, diff --git a/tests/integration/query/inline_array/with_group_test.go b/tests/integration/query/inline_array/with_group_test.go index 7706b9250b..f893a54171 100644 --- a/tests/integration/query/inline_array/with_group_test.go +++ b/tests/integration/query/inline_array/with_group_test.go @@ -17,38 +17,42 @@ import ( ) func TestQueryInlineArrayWithGroupByString(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, mixed integers, group by string", - Request: `query { - Users (groupBy: [name]) { - name - _group { - favouriteIntegers - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "name": "Shahzad", "favouriteIntegers": [-1, 2, -1, 1, 0] }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "name": "Shahzad", "favouriteIntegers": [1, -2, 1, -1, 0] }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_group": []map[string]any{ - { - "favouriteIntegers": []int64{1, -2, 1, -1, 0}, - }, + testUtils.Request{ + Request: `query { + Users (groupBy: [name]) { + name + _group { + favouriteIntegers + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "favouriteIntegers": []int64{-1, 2, -1, 1, 0}, + "name": "Shahzad", + "_group": []map[string]any{ + { + "favouriteIntegers": []int64{1, -2, 1, -1, 0}, + }, + { + "favouriteIntegers": []int64{-1, 2, -1, 1, 0}, + }, + }, }, }, }, @@ -60,51 +64,57 @@ func TestQueryInlineArrayWithGroupByString(t *testing.T) { } func TestQueryInlineArrayWithGroupByArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, mixed integers, group by array", - Request: `query { - Users (groupBy: [favouriteIntegers]) { - favouriteIntegers - _group { - name - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "name": "Andy", "favouriteIntegers": [-1, 2, -1, 1, 0] }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "name": "Shahzad", "favouriteIntegers": [-1, 2, -1, 1, 0] }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "name": "John", "favouriteIntegers": [1, 2, 3] }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "favouriteIntegers": []int64{1, 2, 3}, - "_group": []map[string]any{ - { - "name": "John", - }, - }, - }, - { - "favouriteIntegers": []int64{-1, 2, -1, 1, 0}, - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users (groupBy: [favouriteIntegers]) { + favouriteIntegers + _group { + name + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "name": "Andy", + "favouriteIntegers": []int64{1, 2, 3}, + "_group": []map[string]any{ + { + "name": "John", + }, + }, }, { + "favouriteIntegers": []int64{-1, 2, -1, 1, 0}, + "_group": []map[string]any{ + { + "name": "Andy", + }, + { - "name": "Shahzad", + "name": "Shahzad", + }, + }, }, }, }, diff --git a/tests/integration/query/inline_array/with_sum_filter_test.go b/tests/integration/query/inline_array/with_sum_filter_test.go index 075411e06a..c43a961002 100644 --- a/tests/integration/query/inline_array/with_sum_filter_test.go +++ b/tests/integration/query/inline_array/with_sum_filter_test.go @@ -17,27 +17,29 @@ import ( ) func TestQueryInlineIntegerArrayWithSumWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, filtered sum of integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "favouriteIntegers": [-1, 2, -1, 1, 0] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(favouriteIntegers: {filter: {_gt: 0}}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "favouriteIntegers": [-1, 2, -1, 1, 0] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_sum": int64(3), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_sum": int64(3), + }, + }, }, }, }, @@ -47,27 +49,29 @@ func TestQueryInlineIntegerArrayWithSumWithFilter(t *testing.T) { } func TestQueryInlineNillableIntegerArrayWithSumWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with filter, sum of nillable integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "testScores": [-1, 2, null, 1, 0] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(testScores: {filter: {_gt: 0}}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "testScores": [-1, 2, null, 1, 0] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_sum": int64(3), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_sum": int64(3), + }, + }, }, }, }, @@ -77,27 +81,29 @@ func TestQueryInlineNillableIntegerArrayWithSumWithFilter(t *testing.T) { } func TestQueryInlineFloatArrayWithSumWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, filtered sum of float array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "favouriteFloats": [3.1425, 0.00000000001, 10] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(favouriteFloats: {filter: {_lt: 9}}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "favouriteFloats": [3.1425, 0.00000000001, 10] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_sum": 3.14250000001, + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_sum": 3.14250000001, + }, + }, }, }, }, @@ -107,27 +113,29 @@ func TestQueryInlineFloatArrayWithSumWithFilter(t *testing.T) { } func TestQueryInlineNillableFloatArrayWithSumWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with filter, sum of nillable float array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "pageRatings": [3.1425, 0.00000000001, 10, null] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(pageRatings: {filter: {_lt: 9}}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "pageRatings": [3.1425, 0.00000000001, 10, null] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_sum": float64(3.14250000001), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_sum": float64(3.14250000001), + }, + }, }, }, }, diff --git a/tests/integration/query/inline_array/with_sum_limit_offset_order_test.go b/tests/integration/query/inline_array/with_sum_limit_offset_order_test.go index 59e4ddc7fd..502fd4683f 100644 --- a/tests/integration/query/inline_array/with_sum_limit_offset_order_test.go +++ b/tests/integration/query/inline_array/with_sum_limit_offset_order_test.go @@ -17,28 +17,30 @@ import ( ) func TestQueryInlineIntegerArrayWithSumWithOffsetWithLimitWithOrderAsc(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, ordered offsetted limited sum of integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "favouriteIntegers": [-1, 2, 5, 1, 0, 7] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(favouriteIntegers: {offset: 1, limit: 3, order: ASC}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "favouriteIntegers": [-1, 2, 5, 1, 0, 7] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - // 0 + 1 + 2 - "_sum": int64(3), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + // 0 + 1 + 2 + "_sum": int64(3), + }, + }, }, }, }, @@ -48,28 +50,30 @@ func TestQueryInlineIntegerArrayWithSumWithOffsetWithLimitWithOrderAsc(t *testin } func TestQueryInlineIntegerArrayWithSumWithOffsetWithLimitWithOrderDesc(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, ordered offsetted limited sum of integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "favouriteIntegers": [-1, 2, 5, 1, 0, 7] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(favouriteIntegers: {offset: 1, limit: 3, order: DESC}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "favouriteIntegers": [-1, 2, 5, 1, 0, 7] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - // 5 + 2 + 1 - "_sum": int64(8), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + // 5 + 2 + 1 + "_sum": int64(8), + }, + }, }, }, }, @@ -79,28 +83,30 @@ func TestQueryInlineIntegerArrayWithSumWithOffsetWithLimitWithOrderDesc(t *testi } func TestQueryInlineNillableIntegerArrayWithSumWithOffsetWithLimitWithOrderAsc(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, ordered offsetted limited sum of integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "testScores": [2, null, 5, 1, 0, 7] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(testScores: {offset: 1, limit: 3, order: ASC}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "testScores": [2, null, 5, 1, 0, 7] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - // 0 + 1 + 2 - "_sum": int64(3), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + // 0 + 1 + 2 + "_sum": int64(3), + }, + }, }, }, }, @@ -110,28 +116,30 @@ func TestQueryInlineNillableIntegerArrayWithSumWithOffsetWithLimitWithOrderAsc(t } func TestQueryInlineNillableIntegerArrayWithSumWithOffsetWithLimitWithOrderDesc(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, ordered offsetted limited sum of integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "testScores": [null, 2, 5, 1, 0, 7] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(testScores: {offset: 1, limit: 3, order: DESC}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "testScores": [null, 2, 5, 1, 0, 7] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - // 5 + 2 + 1 - "_sum": int64(8), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + // 5 + 2 + 1 + "_sum": int64(8), + }, + }, }, }, }, @@ -141,28 +149,30 @@ func TestQueryInlineNillableIntegerArrayWithSumWithOffsetWithLimitWithOrderDesc( } func TestQueryInlineFloatArrayWithSumWithOffsetWithLimitWithOrderAsc(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, ordered offsetted limited sum of integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "favouriteFloats": [3.1425, 0.00000000001, 10, 2.718, 0.577, 6.283] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(favouriteFloats: {offset: 1, limit: 3, order: ASC}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "favouriteFloats": [3.1425, 0.00000000001, 10, 2.718, 0.577, 6.283] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - // 0.577 + 2.718 + 3.1425 - "_sum": float64(6.4375), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + // 0.577 + 2.718 + 3.1425 + "_sum": float64(6.4375), + }, + }, }, }, }, @@ -172,28 +182,30 @@ func TestQueryInlineFloatArrayWithSumWithOffsetWithLimitWithOrderAsc(t *testing. } func TestQueryInlineFloatArrayWithSumWithOffsetWithLimitWithOrderDesc(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, ordered offsetted limited sum of integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "favouriteFloats": [3.1425, 0.00000000001, 10, 2.718, 0.577, 6.283] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(favouriteFloats: {offset: 1, limit: 3, order: DESC}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "favouriteFloats": [3.1425, 0.00000000001, 10, 2.718, 0.577, 6.283] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - // 6.283 + 3.1425 + 2.718 - "_sum": float64(12.1435), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + // 6.283 + 3.1425 + 2.718 + "_sum": float64(12.1435), + }, + }, }, }, }, @@ -203,28 +215,30 @@ func TestQueryInlineFloatArrayWithSumWithOffsetWithLimitWithOrderDesc(t *testing } func TestQueryInlineNillableFloatArrayWithSumWithOffsetWithLimitWithOrderAsc(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, ordered offsetted limited sum of integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "pageRatings": [3.1425, null, 10, 2.718, 0.577, 6.283] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(pageRatings: {offset: 1, limit: 3, order: ASC}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "pageRatings": [3.1425, null, 10, 2.718, 0.577, 6.283] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - // 0.577 + 2.718 + 3.1425 - "_sum": float64(6.4375), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + // 0.577 + 2.718 + 3.1425 + "_sum": float64(6.4375), + }, + }, }, }, }, @@ -234,28 +248,30 @@ func TestQueryInlineNillableFloatArrayWithSumWithOffsetWithLimitWithOrderAsc(t * } func TestQueryInlineNillableFloatArrayWithSumWithOffsetWithLimitWithOrderDesc(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, ordered offsetted limited sum of integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "pageRatings": [3.1425, null, 10, 2.718, 0.577, 6.283] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(pageRatings: {offset: 1, limit: 3, order: DESC}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "pageRatings": [3.1425, null, 10, 2.718, 0.577, 6.283] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - // 6.283 + 3.1425 + 2.718 - "_sum": float64(12.1435), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + // 6.283 + 3.1425 + 2.718 + "_sum": float64(12.1435), + }, + }, }, }, }, diff --git a/tests/integration/query/inline_array/with_sum_limit_offset_test.go b/tests/integration/query/inline_array/with_sum_limit_offset_test.go index 357dbbde7e..621417ffc3 100644 --- a/tests/integration/query/inline_array/with_sum_limit_offset_test.go +++ b/tests/integration/query/inline_array/with_sum_limit_offset_test.go @@ -17,27 +17,29 @@ import ( ) func TestQueryInlineIntegerArrayWithSumWithOffsetWithLimit(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, offsetted limited sum of integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "favouriteIntegers": [-1, 2, 5, 1, 0] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(favouriteIntegers: {offset: 1, limit: 2}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "favouriteIntegers": [-1, 2, 5, 1, 0] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_sum": int64(7), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_sum": int64(7), + }, + }, }, }, }, diff --git a/tests/integration/query/inline_array/with_sum_limit_test.go b/tests/integration/query/inline_array/with_sum_limit_test.go index 79ebd60f36..171c389823 100644 --- a/tests/integration/query/inline_array/with_sum_limit_test.go +++ b/tests/integration/query/inline_array/with_sum_limit_test.go @@ -17,27 +17,29 @@ import ( ) func TestQueryInlineIntegerArrayWithSumWithLimit(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array, limited sum of integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "favouriteIntegers": [-1, 2, -1, 1, 0] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(favouriteIntegers: {limit: 2}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "favouriteIntegers": [-1, 2, -1, 1, 0] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_sum": int64(1), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_sum": int64(1), + }, + }, }, }, }, diff --git a/tests/integration/query/inline_array/with_sum_test.go b/tests/integration/query/inline_array/with_sum_test.go index 28f63bb6b3..d65fde5d7b 100644 --- a/tests/integration/query/inline_array/with_sum_test.go +++ b/tests/integration/query/inline_array/with_sum_test.go @@ -17,27 +17,29 @@ import ( ) func TestQueryInlineIntegerArrayWithSumAndNullArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, sum of nil integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteIntegers": null + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(favouriteIntegers: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteIntegers": null - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "_sum": int64(0), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "_sum": int64(0), + }, + }, }, }, }, @@ -47,27 +49,29 @@ func TestQueryInlineIntegerArrayWithSumAndNullArray(t *testing.T) { } func TestQueryInlineIntegerArrayWithSumAndEmptyArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, sum of empty integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteIntegers": [] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(favouriteIntegers: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteIntegers": [] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "_sum": int64(0), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "_sum": int64(0), + }, + }, }, }, }, @@ -77,27 +81,29 @@ func TestQueryInlineIntegerArrayWithSumAndEmptyArray(t *testing.T) { } func TestQueryInlineIntegerArrayWithSumAndPopulatedArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, sum of integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "favouriteIntegers": [-1, 2, -1, 1, 0] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(favouriteIntegers: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "favouriteIntegers": [-1, 2, -1, 1, 0] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_sum": int64(1), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_sum": int64(1), + }, + }, }, }, }, @@ -107,27 +113,29 @@ func TestQueryInlineIntegerArrayWithSumAndPopulatedArray(t *testing.T) { } func TestQueryInlineNillableIntegerArrayWithSumAndPopulatedArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, sum of nillable integer array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "testScores": [-1, 2, null, 1, 0] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(testScores: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "testScores": [-1, 2, null, 1, 0] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_sum": int64(2), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_sum": int64(2), + }, + }, }, }, }, @@ -137,27 +145,29 @@ func TestQueryInlineNillableIntegerArrayWithSumAndPopulatedArray(t *testing.T) { } func TestQueryInlineFloatArrayWithSumAndNullArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, sum of nil float array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteFloats": null + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(favouriteFloats: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteFloats": null - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "_sum": float64(0), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "_sum": float64(0), + }, + }, }, }, }, @@ -167,27 +177,29 @@ func TestQueryInlineFloatArrayWithSumAndNullArray(t *testing.T) { } func TestQueryInlineFloatArrayWithSumAndEmptyArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, sum of empty float array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteFloats": [] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(favouriteFloats: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteFloats": [] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "_sum": float64(0), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "_sum": float64(0), + }, + }, }, }, }, @@ -197,27 +209,29 @@ func TestQueryInlineFloatArrayWithSumAndEmptyArray(t *testing.T) { } func TestQueryInlineFloatArrayWithSumAndPopulatedArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, sum of float array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "favouriteFloats": [3.1425, 0.00000000001, 10] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(favouriteFloats: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "favouriteFloats": [3.1425, 0.00000000001, 10] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "John", - "_sum": float64(13.14250000001), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "John", + "_sum": float64(13.14250000001), + }, + }, }, }, }, @@ -227,27 +241,29 @@ func TestQueryInlineFloatArrayWithSumAndPopulatedArray(t *testing.T) { } func TestQueryInlineNillableFloatArrayWithSumAndPopulatedArray(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple inline array with no filter, sum of nillable float array", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "Shahzad", + "pageRatings": [3.1425, 0.00000000001, 10, null] + }`, + }, + testUtils.Request{ + Request: `query { Users { name _sum(pageRatings: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "Shahzad", - "pageRatings": [3.1425, 0.00000000001, 10, null] - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "name": "Shahzad", - "_sum": float64(13.14250000001), + Results: map[string]any{ + "Users": []map[string]any{ + { + "name": "Shahzad", + "_sum": float64(13.14250000001), + }, + }, }, }, }, diff --git a/tests/integration/query/latest_commits/simple_test.go b/tests/integration/query/latest_commits/simple_test.go index e31ee22da8..e71772d90d 100644 --- a/tests/integration/query/latest_commits/simple_test.go +++ b/tests/integration/query/latest_commits/simple_test.go @@ -19,9 +19,17 @@ import ( // This test is for documentation reasons only. This is not // desired behaviour (should return all latest commits). func TestQueryLatestCommits(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple latest commits query", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "age": 21 + }`, + }, + testUtils.Request{ + Request: `query { latestCommits { cid links { @@ -30,15 +38,9 @@ func TestQueryLatestCommits(t *testing.T) { } } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "age": 21 - }`, + ExpectedError: "Field \"latestCommits\" argument \"docID\" of type \"ID!\" is required but not provided.", }, }, - ExpectedError: "Field \"latestCommits\" argument \"docID\" of type \"ID!\" is required but not provided.", } executeTestCase(t, test) diff --git a/tests/integration/query/latest_commits/utils.go b/tests/integration/query/latest_commits/utils.go index 8c6b344f7e..b4ef3a8fbb 100644 --- a/tests/integration/query/latest_commits/utils.go +++ b/tests/integration/query/latest_commits/utils.go @@ -24,24 +24,19 @@ var userCollectionGQLSchema = (` } `) -const companiesCollectionGQLSchema = (` - type Companies { - name: String - } -`) - -func updateUserCollectionSchema() testUtils.SchemaUpdate { - return testUtils.SchemaUpdate{ - Schema: userCollectionGQLSchema, - } -} - -func updateCompaniesCollectionSchema() testUtils.SchemaUpdate { - return testUtils.SchemaUpdate{ - Schema: companiesCollectionGQLSchema, - } -} - -func executeTestCase(t *testing.T, test testUtils.RequestTestCase) { - testUtils.ExecuteRequestTestCase(t, userCollectionGQLSchema, []string{"Users"}, test) +func executeTestCase(t *testing.T, test testUtils.TestCase) { + testUtils.ExecuteTestCase( + t, + testUtils.TestCase{ + Description: test.Description, + Actions: append( + []any{ + testUtils.SchemaUpdate{ + Schema: userCollectionGQLSchema, + }, + }, + test.Actions..., + ), + }, + ) } diff --git a/tests/integration/query/latest_commits/with_collectionid_prop_test.go b/tests/integration/query/latest_commits/with_collectionid_prop_test.go index ae0758f6c2..70d4296bbe 100644 --- a/tests/integration/query/latest_commits/with_collectionid_prop_test.go +++ b/tests/integration/query/latest_commits/with_collectionid_prop_test.go @@ -20,8 +20,13 @@ func TestQueryLastCommitsWithCollectionIdProperty(t *testing.T) { test := testUtils.TestCase{ Description: "Simple latest commits query with collectionID property", Actions: []any{ - updateUserCollectionSchema(), - updateCompaniesCollectionSchema(), + testUtils.SchemaUpdate{ + Schema: ` + type Companies { + name: String + } + `, + }, testUtils.CreateDoc{ CollectionID: 0, Doc: `{ @@ -66,5 +71,5 @@ func TestQueryLastCommitsWithCollectionIdProperty(t *testing.T) { }, } - testUtils.ExecuteTestCase(t, test) + executeTestCase(t, test) } diff --git a/tests/integration/query/latest_commits/with_doc_id_field_test.go b/tests/integration/query/latest_commits/with_doc_id_field_test.go index bdaf4d5562..e96c2d2604 100644 --- a/tests/integration/query/latest_commits/with_doc_id_field_test.go +++ b/tests/integration/query/latest_commits/with_doc_id_field_test.go @@ -19,9 +19,17 @@ import ( // This test is for documentation reasons only. This is not // desired behaviour (it looks totally broken to me). func TestQueryLatestCommitsWithDocIDAndFieldName(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple latest commits query with docID and field name", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "age": 21 + }`, + }, + testUtils.Request{ + Request: `query { latestCommits(docID: "bae-c9fb0fa4-1195-589c-aa54-e68333fb90b3", fieldId: "age") { cid links { @@ -30,17 +38,11 @@ func TestQueryLatestCommitsWithDocIDAndFieldName(t *testing.T) { } } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "age": 21 - }`, + Results: map[string]any{ + "latestCommits": []map[string]any{}, + }, }, }, - Results: map[string]any{ - "latestCommits": []map[string]any{}, - }, } executeTestCase(t, test) @@ -49,9 +51,17 @@ func TestQueryLatestCommitsWithDocIDAndFieldName(t *testing.T) { // This test is for documentation reasons only. This is not // desired behaviour (Users should not be specifying field ids). func TestQueryLatestCommitsWithDocIDAndFieldId(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple latest commits query with docID and field id", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "age": 21 + }`, + }, + testUtils.Request{ + Request: `query { latestCommits(docID: "bae-c9fb0fa4-1195-589c-aa54-e68333fb90b3", fieldId: "1") { cid links { @@ -60,19 +70,13 @@ func TestQueryLatestCommitsWithDocIDAndFieldId(t *testing.T) { } } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "age": 21 - }`, - }, - }, - Results: map[string]any{ - "latestCommits": []map[string]any{ - { - "cid": "bafyreifzyy7bmpx2eywj4lznxzrzrvh6vrz6l7bhthkpexdq3wtho3vz6i", - "links": []map[string]any{}, + Results: map[string]any{ + "latestCommits": []map[string]any{ + { + "cid": "bafyreifzyy7bmpx2eywj4lznxzrzrvh6vrz6l7bhthkpexdq3wtho3vz6i", + "links": []map[string]any{}, + }, + }, }, }, }, @@ -84,9 +88,17 @@ func TestQueryLatestCommitsWithDocIDAndFieldId(t *testing.T) { // This test is for documentation reasons only. This is not // desired behaviour (Users should not be specifying field ids). func TestQueryLatestCommitsWithDocIDAndCompositeFieldId(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple latest commits query with docID and composite field id", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "age": 21 + }`, + }, + testUtils.Request{ + Request: `query { latestCommits(docID: "bae-c9fb0fa4-1195-589c-aa54-e68333fb90b3", fieldId: "C") { cid links { @@ -95,26 +107,20 @@ func TestQueryLatestCommitsWithDocIDAndCompositeFieldId(t *testing.T) { } } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "age": 21 - }`, - }, - }, - Results: map[string]any{ - "latestCommits": []map[string]any{ - { - "cid": "bafyreihv7jqe32wsuff5vwzlp7izoo6pqg6kgqf5edknp3mqm3344gu35q", - "links": []map[string]any{ - { - "cid": "bafyreic2sba5sffkfnt32wfeoaw4qsqozjb5acwwtouxuzllb3aymjwute", - "name": "name", - }, + Results: map[string]any{ + "latestCommits": []map[string]any{ { - "cid": "bafyreifzyy7bmpx2eywj4lznxzrzrvh6vrz6l7bhthkpexdq3wtho3vz6i", - "name": "age", + "cid": "bafyreihv7jqe32wsuff5vwzlp7izoo6pqg6kgqf5edknp3mqm3344gu35q", + "links": []map[string]any{ + { + "cid": "bafyreic2sba5sffkfnt32wfeoaw4qsqozjb5acwwtouxuzllb3aymjwute", + "name": "name", + }, + { + "cid": "bafyreifzyy7bmpx2eywj4lznxzrzrvh6vrz6l7bhthkpexdq3wtho3vz6i", + "name": "age", + }, + }, }, }, }, diff --git a/tests/integration/query/latest_commits/with_doc_id_prop_test.go b/tests/integration/query/latest_commits/with_doc_id_prop_test.go index 652d321973..9b978d89c0 100644 --- a/tests/integration/query/latest_commits/with_doc_id_prop_test.go +++ b/tests/integration/query/latest_commits/with_doc_id_prop_test.go @@ -20,13 +20,12 @@ func TestQueryLastCommitsWithDocIDProperty(t *testing.T) { test := testUtils.TestCase{ Description: "Simple latest commits query with docID property", Actions: []any{ - updateUserCollectionSchema(), testUtils.CreateDoc{ CollectionID: 0, Doc: `{ - "name": "John", - "age": 21 - }`, + "name": "John", + "age": 21 + }`, }, testUtils.Request{ Request: `query { @@ -45,5 +44,5 @@ func TestQueryLastCommitsWithDocIDProperty(t *testing.T) { }, } - testUtils.ExecuteTestCase(t, test) + executeTestCase(t, test) } diff --git a/tests/integration/query/latest_commits/with_doc_id_test.go b/tests/integration/query/latest_commits/with_doc_id_test.go index 4bd51d546d..9db8206b2e 100644 --- a/tests/integration/query/latest_commits/with_doc_id_test.go +++ b/tests/integration/query/latest_commits/with_doc_id_test.go @@ -17,9 +17,17 @@ import ( ) func TestQueryLatestCommitsWithDocID(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple latest commits query with docID", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "age": 21 + }`, + }, + testUtils.Request{ + Request: `query { latestCommits(docID: "bae-c9fb0fa4-1195-589c-aa54-e68333fb90b3") { cid links { @@ -28,26 +36,20 @@ func TestQueryLatestCommitsWithDocID(t *testing.T) { } } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "age": 21 - }`, - }, - }, - Results: map[string]any{ - "latestCommits": []map[string]any{ - { - "cid": "bafyreihv7jqe32wsuff5vwzlp7izoo6pqg6kgqf5edknp3mqm3344gu35q", - "links": []map[string]any{ + Results: map[string]any{ + "latestCommits": []map[string]any{ { - "cid": "bafyreic2sba5sffkfnt32wfeoaw4qsqozjb5acwwtouxuzllb3aymjwute", - "name": "name", - }, - { - "cid": "bafyreifzyy7bmpx2eywj4lznxzrzrvh6vrz6l7bhthkpexdq3wtho3vz6i", - "name": "age", + "cid": "bafyreihv7jqe32wsuff5vwzlp7izoo6pqg6kgqf5edknp3mqm3344gu35q", + "links": []map[string]any{ + { + "cid": "bafyreic2sba5sffkfnt32wfeoaw4qsqozjb5acwwtouxuzllb3aymjwute", + "name": "name", + }, + { + "cid": "bafyreifzyy7bmpx2eywj4lznxzrzrvh6vrz6l7bhthkpexdq3wtho3vz6i", + "name": "age", + }, + }, }, }, }, @@ -59,27 +61,29 @@ func TestQueryLatestCommitsWithDocID(t *testing.T) { } func TestQueryLatestCommitsWithDocIDWithSchemaVersionIDField(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple latest commits query with docID and schema versiion id field", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "age": 21 + }`, + }, + testUtils.Request{ + Request: `query { latestCommits(docID: "bae-c9fb0fa4-1195-589c-aa54-e68333fb90b3") { cid schemaVersionId } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "age": 21 - }`, - }, - }, - Results: map[string]any{ - "latestCommits": []map[string]any{ - { - "cid": "bafyreihv7jqe32wsuff5vwzlp7izoo6pqg6kgqf5edknp3mqm3344gu35q", - "schemaVersionId": "bafkreicprhqxzlw3akyssz2v6pifwfueavp7jq2yj3dghapi3qcq6achs4", + Results: map[string]any{ + "latestCommits": []map[string]any{ + { + "cid": "bafyreihv7jqe32wsuff5vwzlp7izoo6pqg6kgqf5edknp3mqm3344gu35q", + "schemaVersionId": "bafkreicprhqxzlw3akyssz2v6pifwfueavp7jq2yj3dghapi3qcq6achs4", + }, + }, }, }, }, diff --git a/tests/integration/query/latest_commits/with_field_test.go b/tests/integration/query/latest_commits/with_field_test.go index 67ae607c47..2440e7b4af 100644 --- a/tests/integration/query/latest_commits/with_field_test.go +++ b/tests/integration/query/latest_commits/with_field_test.go @@ -20,9 +20,17 @@ import ( // desired behaviour (should return all latest commits for given // field in the collection). func TestQueryLatestCommitsWithField(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple latest commits query with field", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "age": 21 + }`, + }, + testUtils.Request{ + Request: `query { latestCommits (fieldId: "Age") { cid links { @@ -31,15 +39,9 @@ func TestQueryLatestCommitsWithField(t *testing.T) { } } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "age": 21 - }`, + ExpectedError: "Field \"latestCommits\" argument \"docID\" of type \"ID!\" is required but not provided.", }, }, - ExpectedError: "Field \"latestCommits\" argument \"docID\" of type \"ID!\" is required but not provided.", } executeTestCase(t, test) @@ -49,9 +51,17 @@ func TestQueryLatestCommitsWithField(t *testing.T) { // desired behaviour (should return all latest commits for given // field in the collection). func TestQueryLatestCommitsWithFieldId(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple latest commits query with field", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "name": "John", + "age": 21 + }`, + }, + testUtils.Request{ + Request: `query { latestCommits (fieldId: "1") { cid links { @@ -60,15 +70,9 @@ func TestQueryLatestCommitsWithFieldId(t *testing.T) { } } }`, - Docs: map[int][]string{ - 0: { - `{ - "name": "John", - "age": 21 - }`, + ExpectedError: "Field \"latestCommits\" argument \"docID\" of type \"ID!\" is required but not provided.", }, }, - ExpectedError: "Field \"latestCommits\" argument \"docID\" of type \"ID!\" is required but not provided.", } executeTestCase(t, test) diff --git a/tests/integration/query/one_to_many/simple_test.go b/tests/integration/query/one_to_many/simple_test.go index 44ee5f8cf5..6c0a73c7e8 100644 --- a/tests/integration/query/one_to_many/simple_test.go +++ b/tests/integration/query/one_to_many/simple_test.go @@ -17,45 +17,47 @@ import ( ) func TestQueryOneToMany(t *testing.T) { - tests := []testUtils.RequestTestCase{ + tests := []testUtils.TestCase{ { Description: "One-to-many relation query from one side", - Request: `query { - Book { - name - rating - author { - name - age - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, }, - //authors - 1: { // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, }, - }, - Results: map[string]any{ - "Book": []map[string]any{ - { - "name": "Painted House", - "rating": 4.9, - "author": map[string]any{ - "name": "John Grisham", - "age": int64(65), + testUtils.Request{ + Request: `query { + Book { + name + rating + author { + name + age + } + } + }`, + Results: map[string]any{ + "Book": []map[string]any{ + { + "name": "Painted House", + "rating": 4.9, + "author": map[string]any{ + "name": "John Grisham", + "age": int64(65), + }, + }, }, }, }, @@ -63,74 +65,83 @@ func TestQueryOneToMany(t *testing.T) { }, { Description: "One-to-many relation query from many side", - Request: `query { - Author { - name - age - published { - name - rating - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" - }`, - `{ + }`, + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "Cornelia Funke", - "age": int64(62), - "published": []map[string]any{ - { - "name": "Theif Lord", - "rating": 4.8, - }, - }, - }, - { - "name": "John Grisham", - "age": int64(65), - "published": []map[string]any{ + testUtils.Request{ + Request: `query { + Author { + name + age + published { + name + rating + } + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ { - "name": "Painted House", - "rating": 4.9, + "name": "Cornelia Funke", + "age": int64(62), + "published": []map[string]any{ + { + "name": "Theif Lord", + "rating": 4.8, + }, + }, }, { - "name": "A Time for Mercy", - "rating": 4.5, + "name": "John Grisham", + "age": int64(65), + "published": []map[string]any{ + { + "name": "Painted House", + "rating": 4.9, + }, + { + "name": "A Time for Mercy", + "rating": 4.5, + }, + }, }, }, }, @@ -145,34 +156,35 @@ func TestQueryOneToMany(t *testing.T) { } func TestQueryOneToManyWithNonExistantParent(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from one side with non-existant parent", - Request: `query { - Book { - name - rating - author { - name - age - } - } - }`, - Docs: map[int][]string{ - //books - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, }, - }, - Results: map[string]any{ - "Book": []map[string]any{ - { - "name": "Painted House", - "rating": 4.9, - "author": nil, + testUtils.Request{ + Request: `query { + Book { + name + rating + author { + name + age + } + } + }`, + Results: map[string]any{ + "Book": []map[string]any{ + { + "name": "Painted House", + "rating": 4.9, + "author": nil, + }, + }, }, }, }, diff --git a/tests/integration/query/one_to_many/utils.go b/tests/integration/query/one_to_many/utils.go index d1e25df661..df37e5990c 100644 --- a/tests/integration/query/one_to_many/utils.go +++ b/tests/integration/query/one_to_many/utils.go @@ -31,6 +31,19 @@ var bookAuthorGQLSchema = (` } `) -func executeTestCase(t *testing.T, test testUtils.RequestTestCase) { - testUtils.ExecuteRequestTestCase(t, bookAuthorGQLSchema, []string{"Book", "Author"}, test) +func executeTestCase(t *testing.T, test testUtils.TestCase) { + testUtils.ExecuteTestCase( + t, + testUtils.TestCase{ + Description: test.Description, + Actions: append( + []any{ + testUtils.SchemaUpdate{ + Schema: bookAuthorGQLSchema, + }, + }, + test.Actions..., + ), + }, + ) } diff --git a/tests/integration/query/one_to_many/with_count_filter_test.go b/tests/integration/query/one_to_many/with_count_filter_test.go index 261e5993e9..74d4cd6e29 100644 --- a/tests/integration/query/one_to_many/with_count_filter_test.go +++ b/tests/integration/query/one_to_many/with_count_filter_test.go @@ -17,58 +17,67 @@ import ( ) func TestQueryOneToManyWithCountWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from many side with count with filter", - Request: `query { - Author { - name - _count(published: {filter: {rating: {_gt: 4.8}}}) - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "Cornelia Funke", - "_count": 0, - }, - { - "name": "John Grisham", - "_count": 1, + testUtils.Request{ + Request: `query { + Author { + name + _count(published: {filter: {rating: {_gt: 4.8}}}) + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ + { + "name": "Cornelia Funke", + "_count": 0, + }, + { + "name": "John Grisham", + "_count": 1, + }, + }, }, }, }, @@ -78,76 +87,88 @@ func TestQueryOneToManyWithCountWithFilter(t *testing.T) { } func TestQueryOneToManyWithCountWithFilterAndChildFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from many side with count with filter", - Request: `query { - Author { - name - _count(published: {filter: {rating: {_ne: null}}}) - published(filter: {rating: {_ne: null}}){ - name - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Associate", "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "Cornelia Funke", - "_count": 1, - "published": []map[string]any{ - { - "name": "Theif Lord", - }, - }, - }, - { - "name": "John Grisham", - "_count": 2, - "published": []map[string]any{ + testUtils.Request{ + Request: `query { + Author { + name + _count(published: {filter: {rating: {_ne: null}}}) + published(filter: {rating: {_ne: null}}){ + name + } + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ { - "name": "Painted House", + "name": "Cornelia Funke", + "_count": 1, + "published": []map[string]any{ + { + "name": "Theif Lord", + }, + }, }, { - "name": "A Time for Mercy", + "name": "John Grisham", + "_count": 2, + "published": []map[string]any{ + { + "name": "Painted House", + }, + { + "name": "A Time for Mercy", + }, + }, }, }, }, diff --git a/tests/integration/query/one_to_many/with_count_limit_offset_test.go b/tests/integration/query/one_to_many/with_count_limit_offset_test.go index eea8a504c7..ee0dc26e61 100644 --- a/tests/integration/query/one_to_many/with_count_limit_offset_test.go +++ b/tests/integration/query/one_to_many/with_count_limit_offset_test.go @@ -17,78 +17,93 @@ import ( ) func TestQueryOneToManyWithCountAndLimitAndOffset(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from many side with count and limit and offset", - Request: `query { - Author { - name - _count(published: {}) - published(limit: 2, offset: 1) { - name - } - } - }`, - Docs: map[int][]string{ - //books - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" - }`, - `{ + }`, + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Firm", "rating": 4.1, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" - }`, - `{ + }`, + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Pelican Brief", "rating": 4.0, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" - }`, - `{ + }`, + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "Cornelia Funke", - "_count": 1, - "published": []map[string]any{}, - }, - { - "name": "John Grisham", - "_count": 4, - "published": []map[string]any{ + testUtils.Request{ + Request: `query { + Author { + name + _count(published: {}) + published(limit: 2, offset: 1) { + name + } + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ { - "name": "Painted House", + "name": "Cornelia Funke", + "_count": 1, + "published": []map[string]any{}, }, { - "name": "The Pelican Brief", + "name": "John Grisham", + "_count": 4, + "published": []map[string]any{ + { + "name": "Painted House", + }, + { + "name": "The Pelican Brief", + }, + }, }, }, }, @@ -100,77 +115,89 @@ func TestQueryOneToManyWithCountAndLimitAndOffset(t *testing.T) { } func TestQueryOneToManyWithCountAndDifferentOffsets(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from many side with count and limit and offset", - Request: `query { - Author { - name - _count(published: {offset: 1, limit: 2}) - published(limit: 2) { - name - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Associate", "rating": 4.2, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "Cornelia Funke", - "_count": 0, - "published": []map[string]any{ - { - "name": "Theif Lord", - }, - }, - }, - { - "name": "John Grisham", - "_count": 2, - "published": []map[string]any{ + testUtils.Request{ + Request: `query { + Author { + name + _count(published: {offset: 1, limit: 2}) + published(limit: 2) { + name + } + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ { - "name": "The Associate", + "name": "Cornelia Funke", + "_count": 0, + "published": []map[string]any{ + { + "name": "Theif Lord", + }, + }, }, { - "name": "Painted House", + "name": "John Grisham", + "_count": 2, + "published": []map[string]any{ + { + "name": "The Associate", + }, + { + "name": "Painted House", + }, + }, }, }, }, @@ -182,58 +209,67 @@ func TestQueryOneToManyWithCountAndDifferentOffsets(t *testing.T) { } func TestQueryOneToManyWithCountWithLimitWithOffset(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from many side with count with limit with offset", - Request: `query { - Author { - name - _count(published: {offset: 1, limit: 1}) - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" - }`, - `{ + }`, + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "Cornelia Funke", - "_count": 0, - }, - { - "name": "John Grisham", - "_count": 1, + testUtils.Request{ + Request: `query { + Author { + name + _count(published: {offset: 1, limit: 1}) + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ + { + "name": "Cornelia Funke", + "_count": 0, + }, + { + "name": "John Grisham", + "_count": 1, + }, + }, }, }, }, diff --git a/tests/integration/query/one_to_many/with_count_limit_test.go b/tests/integration/query/one_to_many/with_count_limit_test.go index 3f7006d074..0b1cdaae96 100644 --- a/tests/integration/query/one_to_many/with_count_limit_test.go +++ b/tests/integration/query/one_to_many/with_count_limit_test.go @@ -17,69 +17,78 @@ import ( ) func TestQueryOneToManyWithCountAndLimit(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from many side with count and limit", - Request: `query { - Author { - name - _count(published: {}) - published(limit: 1) { - name - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" - }`, - `{ + }`, + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "Cornelia Funke", - "_count": 1, - "published": []map[string]any{ + testUtils.Request{ + Request: `query { + Author { + name + _count(published: {}) + published(limit: 1) { + name + } + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ { - "name": "Theif Lord", + "name": "Cornelia Funke", + "_count": 1, + "published": []map[string]any{ + { + "name": "Theif Lord", + }, + }, }, - }, - }, - { - "name": "John Grisham", - "_count": 2, - "published": []map[string]any{ { - "name": "Painted House", + "name": "John Grisham", + "_count": 2, + "published": []map[string]any{ + { + "name": "Painted House", + }, + }, }, }, }, @@ -91,74 +100,86 @@ func TestQueryOneToManyWithCountAndLimit(t *testing.T) { } func TestQueryOneToManyWithCountAndDifferentLimits(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from many side with count and limit", - Request: `query { - Author { - name - _count(published: {limit: 2}) - published(limit: 1) { - name - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Associate", "rating": 4.2, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "Cornelia Funke", - "_count": 1, - "published": []map[string]any{ + testUtils.Request{ + Request: `query { + Author { + name + _count(published: {limit: 2}) + published(limit: 1) { + name + } + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ { - "name": "Theif Lord", + "name": "Cornelia Funke", + "_count": 1, + "published": []map[string]any{ + { + "name": "Theif Lord", + }, + }, }, - }, - }, - { - "name": "John Grisham", - "_count": 2, - "published": []map[string]any{ { - "name": "The Associate", + "name": "John Grisham", + "_count": 2, + "published": []map[string]any{ + { + "name": "The Associate", + }, + }, }, }, }, @@ -170,58 +191,67 @@ func TestQueryOneToManyWithCountAndDifferentLimits(t *testing.T) { } func TestQueryOneToManyWithCountWithLimit(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from many side with count with limit", - Request: `query { - Author { - name - _count(published: {limit: 1}) - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "Cornelia Funke", - "_count": 1, - }, - { - "name": "John Grisham", - "_count": 1, + testUtils.Request{ + Request: `query { + Author { + name + _count(published: {limit: 1}) + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ + { + "name": "Cornelia Funke", + "_count": 1, + }, + { + "name": "John Grisham", + "_count": 1, + }, + }, }, }, }, diff --git a/tests/integration/query/one_to_many/with_count_test.go b/tests/integration/query/one_to_many/with_count_test.go index dba62fbf05..2b4e8a5fbe 100644 --- a/tests/integration/query/one_to_many/with_count_test.go +++ b/tests/integration/query/one_to_many/with_count_test.go @@ -17,86 +17,97 @@ import ( ) func TestQueryOneToManyWithCount(t *testing.T) { - tests := []testUtils.RequestTestCase{ + tests := []testUtils.TestCase{ { Description: "One-to-many relation query from many side with count, no child records", - Request: `query { - Author { - name - _count(published: {}) - } - }`, - Docs: map[int][]string{ - //authors - 1: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "John Grisham", - "_count": 0, + testUtils.Request{ + Request: `query { + Author { + name + _count(published: {}) + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ + { + "name": "John Grisham", + "_count": 0, + }, + }, }, }, }, }, { Description: "One-to-many relation query from many side with count", - Request: `query { - Author { - name - _count(published: {}) - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "Cornelia Funke", - "_count": 1, - }, - { - "name": "John Grisham", - "_count": 2, + testUtils.Request{ + Request: `query { + Author { + name + _count(published: {}) + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ + { + "name": "Cornelia Funke", + "_count": 1, + }, + { + "name": "John Grisham", + "_count": 2, + }, + }, }, }, }, diff --git a/tests/integration/query/one_to_many/with_doc_id_test.go b/tests/integration/query/one_to_many/with_doc_id_test.go index b00fd0a549..86551c5934 100644 --- a/tests/integration/query/one_to_many/with_doc_id_test.go +++ b/tests/integration/query/one_to_many/with_doc_id_test.go @@ -17,48 +17,53 @@ import ( ) func TestQueryOneToManyWithChildDocID(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from one side with child docID", - Request: `query { - Author { - name - published ( - docID: "bae-5366ba09-54e8-5381-8169-a770aa9282ae" - ) { - name - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-5366ba09-54e8-5381-8169-a770aa9282ae - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, }, - //authors - 1: { // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "John Grisham", - "published": []map[string]any{ + testUtils.Request{ + Request: `query { + Author { + name + published ( + docID: "bae-5366ba09-54e8-5381-8169-a770aa9282ae" + ) { + name + } + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ { - "name": "Painted House", + "name": "John Grisham", + "published": []map[string]any{ + { + "name": "Painted House", + }, + }, }, }, }, diff --git a/tests/integration/query/one_to_many/with_doc_ids_test.go b/tests/integration/query/one_to_many/with_doc_ids_test.go index 998c926909..b704cd0ddd 100644 --- a/tests/integration/query/one_to_many/with_doc_ids_test.go +++ b/tests/integration/query/one_to_many/with_doc_ids_test.go @@ -17,63 +17,72 @@ import ( ) func TestQueryOneToManyWithChildDocIDs(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from one side with child docIDs", - Request: `query { - Author { - name - published ( - docIDs: ["bae-5366ba09-54e8-5381-8169-a770aa9282ae", "bae-1ccf3043-d760-543e-be1b-6691fa6aa7a8"] - ) { - name - } - } - }`, - Docs: map[int][]string{ - //books - 0: { - // bae-5366ba09-54e8-5381-8169-a770aa9282ae - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - // bae-1ccf3043-d760-543e-be1b-6691fa6aa7a8 - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Associate", "rating": 4.2, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Firm", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, }, - //authors - 1: { // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "John Grisham", - "published": []map[string]any{ - { - "name": "The Associate", - }, + testUtils.Request{ + Request: `query { + Author { + name + published ( + docIDs: ["bae-5366ba09-54e8-5381-8169-a770aa9282ae", "bae-1ccf3043-d760-543e-be1b-6691fa6aa7a8"] + ) { + name + } + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ { - "name": "Painted House", + "name": "John Grisham", + "published": []map[string]any{ + { + "name": "The Associate", + }, + { + "name": "Painted House", + }, + }, }, }, }, diff --git a/tests/integration/query/one_to_many/with_filter_related_id_test.go b/tests/integration/query/one_to_many/with_filter_related_id_test.go index 6d8508e3c3..4f9bffaffb 100644 --- a/tests/integration/query/one_to_many/with_filter_related_id_test.go +++ b/tests/integration/query/one_to_many/with_filter_related_id_test.go @@ -17,77 +17,94 @@ import ( ) func TestQueryFromManySideWithEqFilterOnRelatedType(t *testing.T) { - test := testUtils.RequestTestCase{ - + test := testUtils.TestCase{ Description: "One-to-many query from many side with _eq filter on related field type.", - - Request: `query { - Book(filter: {author: {_docID: {_eq: "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b"}}}) { - name - } - }`, - - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Client", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Candide", "rating": 4.95, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Zadig", "rating": 4.91, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", "rating": 2, "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Voltaire", "age": 327, "verified": true }`, - // bae-34a9bd41-1f0d-5748-8446-48fc36ef2614 - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Simon Pelloutier", "age": 327, "verified": true }`, }, - }, - Results: map[string]any{ - "Book": []map[string]any{ - {"name": "The Client"}, - {"name": "Painted House"}, - {"name": "A Time for Mercy"}, + testUtils.Request{ + Request: `query { + Book(filter: {author: {_docID: {_eq: "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b"}}}) { + name + } + }`, + Results: map[string]any{ + "Book": []map[string]any{ + {"name": "The Client"}, + {"name": "Painted House"}, + {"name": "A Time for Mercy"}, + }, + }, }, }, } @@ -96,77 +113,94 @@ func TestQueryFromManySideWithEqFilterOnRelatedType(t *testing.T) { } func TestQueryFromManySideWithFilterOnRelatedObjectID(t *testing.T) { - test := testUtils.RequestTestCase{ - + test := testUtils.TestCase{ Description: "One-to-many query from many side with filter on related field.", - - Request: `query { - Book(filter: {author_id: {_eq: "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b"}}) { - name - } - }`, - - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Client", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Candide", "rating": 4.95, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Zadig", "rating": 4.91, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", "rating": 2, "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Voltaire", "age": 327, "verified": true }`, - // bae-34a9bd41-1f0d-5748-8446-48fc36ef2614 - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Simon Pelloutier", "age": 327, "verified": true }`, }, - }, - Results: map[string]any{ - "Book": []map[string]any{ - {"name": "The Client"}, - {"name": "Painted House"}, - {"name": "A Time for Mercy"}, + testUtils.Request{ + Request: `query { + Book(filter: {author_id: {_eq: "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b"}}) { + name + } + }`, + Results: map[string]any{ + "Book": []map[string]any{ + {"name": "The Client"}, + {"name": "Painted House"}, + {"name": "A Time for Mercy"}, + }, + }, }, }, } @@ -175,82 +209,99 @@ func TestQueryFromManySideWithFilterOnRelatedObjectID(t *testing.T) { } func TestQueryFromManySideWithSameFiltersInDifferentWayOnRelatedType(t *testing.T) { - test := testUtils.RequestTestCase{ - + test := testUtils.TestCase{ Description: "One-to-many query from many side with same filters in different way on related type.", - - Request: `query { - Book( - filter: { - author: {_docID: {_eq: "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b"}}, - author_id: {_eq: "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b"} - } - ) { - name - } - }`, - - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Client", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Candide", "rating": 4.95, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Zadig", "rating": 4.91, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", "rating": 2, "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Voltaire", "age": 327, "verified": true }`, - // bae-34a9bd41-1f0d-5748-8446-48fc36ef2614 - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Simon Pelloutier", "age": 327, "verified": true }`, }, - }, - Results: map[string]any{ - "Book": []map[string]any{ - {"name": "The Client"}, - {"name": "Painted House"}, - {"name": "A Time for Mercy"}, + testUtils.Request{ + Request: `query { + Book( + filter: { + author: {_docID: {_eq: "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b"}}, + author_id: {_eq: "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b"} + } + ) { + name + } + }`, + Results: map[string]any{ + "Book": []map[string]any{ + {"name": "The Client"}, + {"name": "Painted House"}, + {"name": "A Time for Mercy"}, + }, + }, }, }, } @@ -259,76 +310,93 @@ func TestQueryFromManySideWithSameFiltersInDifferentWayOnRelatedType(t *testing. } func TestQueryFromSingleSideWithEqFilterOnRelatedType(t *testing.T) { - test := testUtils.RequestTestCase{ - + test := testUtils.TestCase{ Description: "One-to-many query from single side with _eq filter on related field type.", - - Request: `query { - Author(filter: {published: {_docID: {_eq: "bae-96c9de0f-2903-5589-9604-b42882afde8c"}}}) { - name - } - }`, - - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Client", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Candide", "rating": 4.95, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Zadig", "rating": 4.91, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", "rating": 2, "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Voltaire", "age": 327, "verified": true }`, - // bae-34a9bd41-1f0d-5748-8446-48fc36ef2614 - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Simon Pelloutier", "age": 327, "verified": true }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "John Grisham", + testUtils.Request{ + Request: `query { + Author(filter: {published: {_docID: {_eq: "bae-96c9de0f-2903-5589-9604-b42882afde8c"}}}) { + name + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ + { + "name": "John Grisham", + }, + }, }, }, }, @@ -338,74 +406,90 @@ func TestQueryFromSingleSideWithEqFilterOnRelatedType(t *testing.T) { } func TestQueryFromSingleSideWithFilterOnRelatedObjectID_Error(t *testing.T) { - test := testUtils.RequestTestCase{ - + test := testUtils.TestCase{ Description: "One-to-many query from single side with filter on related field.", - - Request: `query { - Author(filter: {published_id: {_eq: "bae-5366ba09-54e8-5381-8169-a770aa9282ae"}}) { - name - } - }`, - - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Client", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Candide", "rating": 4.95, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Zadig", "rating": 4.91, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", "rating": 2, "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Voltaire", "age": 327, "verified": true }`, - // bae-34a9bd41-1f0d-5748-8446-48fc36ef2614 - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Simon Pelloutier", "age": 327, "verified": true }`, }, + testUtils.Request{ + Request: `query { + Author(filter: {published_id: {_eq: "bae-5366ba09-54e8-5381-8169-a770aa9282ae"}}) { + name + } + }`, + ExpectedError: "Argument \"filter\" has invalid value {published_id: {_eq: \"bae-5366ba09-54e8-5381-8169-a770aa9282ae\"}}.\nIn field \"published_id\": Unknown field.", + }, }, - - ExpectedError: "Argument \"filter\" has invalid value {published_id: {_eq: \"bae-5366ba09-54e8-5381-8169-a770aa9282ae\"}}.\nIn field \"published_id\": Unknown field.", } executeTestCase(t, test) diff --git a/tests/integration/query/one_to_many/with_group_filter_test.go b/tests/integration/query/one_to_many/with_group_filter_test.go index 38deb0cc20..5071b963cf 100644 --- a/tests/integration/query/one_to_many/with_group_filter_test.go +++ b/tests/integration/query/one_to_many/with_group_filter_test.go @@ -17,110 +17,131 @@ import ( ) func TestQueryOneToManyWithParentJoinGroupNumberAndNumberFilterOnJoin(t *testing.T) { - tests := []testUtils.RequestTestCase{ + tests := []testUtils.TestCase{ { Description: "One-to-many relation query from many side with parent level group and filter on join", - Request: `query { - Author (groupBy: [age]) { - age - _group { - name - published (filter: {rating: {_gt: 4.6}}) { - name - rating - } - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Client", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Candide", "rating": 4.95, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Zadig", "rating": 4.91, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", "rating": 2, "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Voltaire", "age": 327, "verified": true }`, - // bae-34a9bd41-1f0d-5748-8446-48fc36ef2614 - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Simon Pelloutier", "age": 327, "verified": true }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "age": int64(327), - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Author (groupBy: [age]) { + age + _group { + name + published (filter: {rating: {_gt: 4.6}}) { + name + rating + } + } + } + }`, + + Results: map[string]any{ + "Author": []map[string]any{ { - "name": "Voltaire", - "published": []map[string]any{ + "age": int64(327), + "_group": []map[string]any{ { - "name": "Candide", - "rating": 4.95, + "name": "Voltaire", + "published": []map[string]any{ + { + "name": "Candide", + "rating": 4.95, + }, + { + "name": "Zadig", + "rating": 4.91, + }, + }, }, { - "name": "Zadig", - "rating": 4.91, + "name": "Simon Pelloutier", + "published": []map[string]any{}, }, }, }, { - "name": "Simon Pelloutier", - "published": []map[string]any{}, - }, - }, - }, - { - "age": int64(65), - "_group": []map[string]any{ - { - "name": "John Grisham", - "published": []map[string]any{ + "age": int64(65), + "_group": []map[string]any{ { - "name": "Painted House", - "rating": 4.9, + "name": "John Grisham", + "published": []map[string]any{ + { + "name": "Painted House", + "rating": 4.9, + }, + }, }, }, }, @@ -137,114 +158,134 @@ func TestQueryOneToManyWithParentJoinGroupNumberAndNumberFilterOnJoin(t *testing } func TestQueryOneToManyWithParentJoinGroupNumberAndNumberFilterOnGroup(t *testing.T) { - tests := []testUtils.RequestTestCase{ + tests := []testUtils.TestCase{ { Description: "One-to-many relation query from many side with parent level group and group filter", - Request: `query { - Author (groupBy: [age]) { - age - _group (filter: {published: {rating: {_gt: 4.6}}}) { - name - published { - name - rating - } - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Client", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Candide", "rating": 4.95, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Zadig", "rating": 4.91, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", "rating": 2, "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Voltaire", "age": 327, "verified": true }`, - // bae-34a9bd41-1f0d-5748-8446-48fc36ef2614 - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Simon Pelloutier", "age": 327, "verified": true }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "age": int64(327), - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Author (groupBy: [age]) { + age + _group (filter: {published: {rating: {_gt: 4.6}}}) { + name + published { + name + rating + } + } + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ { - "name": "Voltaire", - "published": []map[string]any{ - { - "name": "Candide", - "rating": 4.95, - }, + "age": int64(327), + "_group": []map[string]any{ { - "name": "Zadig", - "rating": 4.91, + "name": "Voltaire", + "published": []map[string]any{ + { + "name": "Candide", + "rating": 4.95, + }, + { + "name": "Zadig", + "rating": 4.91, + }, + }, }, }, }, - }, - }, - { - "age": int64(65), - "_group": []map[string]any{ { - "name": "John Grisham", - "published": []map[string]any{ + "age": int64(65), + "_group": []map[string]any{ { - "name": "The Client", - "rating": 4.5, - }, - { - "name": "Painted House", - "rating": 4.9, - }, - { - "name": "A Time for Mercy", - "rating": 4.5, + "name": "John Grisham", + "published": []map[string]any{ + { + "name": "The Client", + "rating": 4.5, + }, + { + "name": "Painted House", + "rating": 4.9, + }, + { + "name": "A Time for Mercy", + "rating": 4.5, + }, + }, }, }, }, @@ -261,95 +302,115 @@ func TestQueryOneToManyWithParentJoinGroupNumberAndNumberFilterOnGroup(t *testin } func TestQueryOneToManyWithParentJoinGroupNumberAndNumberFilterOnGroupAndOnGroupJoin(t *testing.T) { - tests := []testUtils.RequestTestCase{ + tests := []testUtils.TestCase{ { Description: "One-to-many relation query from many side with parent level group and filters", - Request: `query { - Author (groupBy: [age], filter: {age: {_gt: 300}}) { - age - _group { - name - published (filter: {rating: {_gt: 4.91}}){ - name - rating - } - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Client", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Candide", "rating": 4.95, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Zadig", "rating": 4.91, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", "rating": 2, "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Voltaire", "age": 327, "verified": true }`, - // bae-34a9bd41-1f0d-5748-8446-48fc36ef2614 - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Simon Pelloutier", "age": 327, "verified": true }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "age": int64(327), - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Author (groupBy: [age], filter: {age: {_gt: 300}}) { + age + _group { + name + published (filter: {rating: {_gt: 4.91}}){ + name + rating + } + } + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ { - "name": "Voltaire", - "published": []map[string]any{ + "age": int64(327), + "_group": []map[string]any{ + { + "name": "Voltaire", + "published": []map[string]any{ + { + "name": "Candide", + "rating": 4.95, + }, + }, + }, { - "name": "Candide", - "rating": 4.95, + "name": "Simon Pelloutier", + "published": []map[string]any{}, }, }, }, - { - "name": "Simon Pelloutier", - "published": []map[string]any{}, - }, }, }, }, diff --git a/tests/integration/query/one_to_many/with_group_related_id_alias_test.go b/tests/integration/query/one_to_many/with_group_related_id_alias_test.go index 9dde09334d..2847b0da2c 100644 --- a/tests/integration/query/one_to_many/with_group_related_id_alias_test.go +++ b/tests/integration/query/one_to_many/with_group_related_id_alias_test.go @@ -765,147 +765,185 @@ func TestQueryOneToManyWithParentGroupByOnRelatedTypeWithIDSelectionFromManySide } func TestQueryOneToManyWithParentGroupByOnRelatedTypeFromSingleSideUsingAlias(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many query with groupBy on related id field alias (from single side).", - Request: `query { - Author(groupBy: [published]) { - _group { - name - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Client", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Candide", "rating": 4.95, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Zadig", "rating": 4.91, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", "rating": 2, "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Voltaire", "age": 327, "verified": true }`, - // bae-34a9bd41-1f0d-5748-8446-48fc36ef2614 - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Simon Pelloutier", "age": 327, "verified": true }`, }, + testUtils.Request{ + Request: `query { + Author(groupBy: [published]) { + _group { + name + } + } + }`, + ExpectedError: "invalid field value to groupBy. Field: published", + }, }, - - ExpectedError: "invalid field value to groupBy. Field: published", } executeTestCase(t, test) } func TestQueryOneToManyWithParentGroupByOnRelatedTypeWithIDSelectionFromSingleSideUsingAlias(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many query with groupBy on related id field alias, with id selection (from single side).", - Request: `query { - Author(groupBy: [published]) { - published_id - _group { - name - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Client", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Candide", "rating": 4.95, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Zadig", "rating": 4.91, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", "rating": 2, "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Voltaire", "age": 327, "verified": true }`, - // bae-34a9bd41-1f0d-5748-8446-48fc36ef2614 - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Simon Pelloutier", "age": 327, "verified": true }`, }, + testUtils.Request{ + Request: `query { + Author(groupBy: [published]) { + published_id + _group { + name + } + } + }`, + ExpectedError: "Cannot query field \"published_id\" on type \"Author\". ", + }, }, - - ExpectedError: "Cannot query field \"published_id\" on type \"Author\". ", } executeTestCase(t, test) diff --git a/tests/integration/query/one_to_many/with_group_related_id_test.go b/tests/integration/query/one_to_many/with_group_related_id_test.go index da3a1cac3f..86d391a2f6 100644 --- a/tests/integration/query/one_to_many/with_group_related_id_test.go +++ b/tests/integration/query/one_to_many/with_group_related_id_test.go @@ -17,138 +17,158 @@ import ( ) func TestQueryOneToManyWithParentGroupByOnRelatedTypeIDFromManySide(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many query with groupBy on related id (from many side).", - Request: `query { - Book(groupBy: [author_id]) { - author_id - _group { - name - rating - author { - name - age - } - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Client", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Candide", "rating": 4.95, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Zadig", "rating": 4.91, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", "rating": 2, "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Voltaire", "age": 327, "verified": true }`, - // bae-34a9bd41-1f0d-5748-8446-48fc36ef2614 - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Simon Pelloutier", "age": 327, "verified": true }`, }, - }, - Results: map[string]any{ - "Book": []map[string]any{ - { - "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b", - "_group": []map[string]any{ - { - "name": "The Client", - "rating": 4.5, - "author": map[string]any{ - "age": int64(65), - "name": "John Grisham", - }, - }, - { - "name": "Painted House", - "rating": 4.9, - "author": map[string]any{ - "age": int64(65), - "name": "John Grisham", - }, - }, - { - "name": "A Time for Mercy", - "rating": 4.5, - "author": map[string]any{ - "age": int64(65), - "name": "John Grisham", - }, - }, - }, - }, - { - "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614", - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Book(groupBy: [author_id]) { + author_id + _group { + name + rating + author { + name + age + } + } + } + }`, + Results: map[string]any{ + "Book": []map[string]any{ { - "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", - "rating": 2.0, - "author": map[string]any{ - "age": int64(327), - "name": "Simon Pelloutier", + "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b", + "_group": []map[string]any{ + { + "name": "The Client", + "rating": 4.5, + "author": map[string]any{ + "age": int64(65), + "name": "John Grisham", + }, + }, + { + "name": "Painted House", + "rating": 4.9, + "author": map[string]any{ + "age": int64(65), + "name": "John Grisham", + }, + }, + { + "name": "A Time for Mercy", + "rating": 4.5, + "author": map[string]any{ + "age": int64(65), + "name": "John Grisham", + }, + }, }, }, - }, - }, - { - "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c", - "_group": []map[string]any{ { - "name": "Candide", - "rating": 4.95, - "author": map[string]any{ - "age": int64(327), - "name": "Voltaire", + "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614", + "_group": []map[string]any{ + { + "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", + "rating": 2.0, + "author": map[string]any{ + "age": int64(327), + "name": "Simon Pelloutier", + }, + }, }, }, { - "name": "Zadig", - "rating": 4.91, - "author": map[string]any{ - "age": int64(327), - "name": "Voltaire", + "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c", + "_group": []map[string]any{ + { + "name": "Candide", + "rating": 4.95, + "author": map[string]any{ + "age": int64(327), + "name": "Voltaire", + }, + }, + { + "name": "Zadig", + "rating": 4.91, + "author": map[string]any{ + "age": int64(327), + "name": "Voltaire", + }, + }, }, }, }, @@ -161,138 +181,158 @@ func TestQueryOneToManyWithParentGroupByOnRelatedTypeIDFromManySide(t *testing.T } func TestQueryOneToManyWithParentGroupByOnRelatedTypeIDWithIDSelectionFromManySide(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many query with groupBy on related id, with id selection (from many side).", - Request: `query { - Book(groupBy: [author_id]) { - author_id - _group { - name - rating - author { - name - age - } - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Client", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Candide", "rating": 4.95, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Zadig", "rating": 4.91, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", "rating": 2, "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Voltaire", "age": 327, "verified": true }`, - // bae-34a9bd41-1f0d-5748-8446-48fc36ef2614 - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Simon Pelloutier", "age": 327, "verified": true }`, }, - }, - Results: map[string]any{ - "Book": []map[string]any{ - { - "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b", - "_group": []map[string]any{ - { - "name": "The Client", - "rating": 4.5, - "author": map[string]any{ - "age": int64(65), - "name": "John Grisham", - }, - }, - { - "name": "Painted House", - "rating": 4.9, - "author": map[string]any{ - "age": int64(65), - "name": "John Grisham", - }, - }, - { - "name": "A Time for Mercy", - "rating": 4.5, - "author": map[string]any{ - "age": int64(65), - "name": "John Grisham", - }, - }, - }, - }, - { - "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614", - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Book(groupBy: [author_id]) { + author_id + _group { + name + rating + author { + name + age + } + } + } + }`, + Results: map[string]any{ + "Book": []map[string]any{ { - "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", - "rating": 2.0, - "author": map[string]any{ - "age": int64(327), - "name": "Simon Pelloutier", + "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b", + "_group": []map[string]any{ + { + "name": "The Client", + "rating": 4.5, + "author": map[string]any{ + "age": int64(65), + "name": "John Grisham", + }, + }, + { + "name": "Painted House", + "rating": 4.9, + "author": map[string]any{ + "age": int64(65), + "name": "John Grisham", + }, + }, + { + "name": "A Time for Mercy", + "rating": 4.5, + "author": map[string]any{ + "age": int64(65), + "name": "John Grisham", + }, + }, }, }, - }, - }, - { - "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c", - "_group": []map[string]any{ { - "name": "Candide", - "rating": 4.95, - "author": map[string]any{ - "age": int64(327), - "name": "Voltaire", + "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614", + "_group": []map[string]any{ + { + "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", + "rating": 2.0, + "author": map[string]any{ + "age": int64(327), + "name": "Simon Pelloutier", + }, + }, }, }, { - "name": "Zadig", - "rating": 4.91, - "author": map[string]any{ - "age": int64(327), - "name": "Voltaire", + "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c", + "_group": []map[string]any{ + { + "name": "Candide", + "rating": 4.95, + "author": map[string]any{ + "age": int64(327), + "name": "Voltaire", + }, + }, + { + "name": "Zadig", + "rating": 4.91, + "author": map[string]any{ + "age": int64(327), + "name": "Voltaire", + }, + }, }, }, }, @@ -305,155 +345,193 @@ func TestQueryOneToManyWithParentGroupByOnRelatedTypeIDWithIDSelectionFromManySi } func TestQueryOneToManyWithParentGroupByOnRelatedTypeFromSingleSide(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many query with groupBy on related id (from single side).", - Request: `query { - Author(groupBy: [published_id]) { - _group { - name - published { - name - rating - } - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Client", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Candide", "rating": 4.95, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Zadig", "rating": 4.91, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", "rating": 2, "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Voltaire", "age": 327, "verified": true }`, - // bae-34a9bd41-1f0d-5748-8446-48fc36ef2614 - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Simon Pelloutier", "age": 327, "verified": true }`, }, + testUtils.Request{ + Request: `query { + Author(groupBy: [published_id]) { + _group { + name + published { + name + rating + } + } + } + }`, + ExpectedError: "Argument \"groupBy\" has invalid value [published_id].\nIn element #1: Expected type \"AuthorField\", found published_id.", + }, }, - - ExpectedError: "Argument \"groupBy\" has invalid value [published_id].\nIn element #1: Expected type \"AuthorField\", found published_id.", } executeTestCase(t, test) } func TestQueryOneToManyWithParentGroupByOnRelatedTypeWithIDSelectionFromSingleSide(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many query with groupBy on related id, with id selection (from single side).", - Request: `query { - Author(groupBy: [published_id]) { - published_id - _group { - name - published { - name - rating - } - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Client", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Candide", "rating": 4.95, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Zadig", "rating": 4.91, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", "rating": 2, "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Voltaire", "age": 327, "verified": true }`, - // bae-34a9bd41-1f0d-5748-8446-48fc36ef2614 - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Simon Pelloutier", "age": 327, "verified": true }`, }, + testUtils.Request{ + Request: `query { + Author(groupBy: [published_id]) { + published_id + _group { + name + published { + name + rating + } + } + } + }`, + ExpectedError: "Argument \"groupBy\" has invalid value [published_id].\nIn element #1: Expected type \"AuthorField\", found published_id.", + }, }, - - ExpectedError: "Argument \"groupBy\" has invalid value [published_id].\nIn element #1: Expected type \"AuthorField\", found published_id.", } executeTestCase(t, test) diff --git a/tests/integration/query/one_to_many/with_group_test.go b/tests/integration/query/one_to_many/with_group_test.go index b1fe1034f8..421c785dbe 100644 --- a/tests/integration/query/one_to_many/with_group_test.go +++ b/tests/integration/query/one_to_many/with_group_test.go @@ -17,97 +17,109 @@ import ( ) func TestQueryOneToManyWithInnerJoinGroupNumber(t *testing.T) { - tests := []testUtils.RequestTestCase{ + tests := []testUtils.TestCase{ { Description: "One-to-many relation query from many side with group inside of join", - Request: `query { - Author { - name - age - published (groupBy: [rating]){ - rating - _group { - name - } - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Client", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "Cornelia Funke", - "age": int64(62), - "published": []map[string]any{ + testUtils.Request{ + Request: `query { + Author { + name + age + published (groupBy: [rating]){ + rating + _group { + name + } + } + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ { - "rating": 4.8, - "_group": []map[string]any{ + "name": "Cornelia Funke", + "age": int64(62), + "published": []map[string]any{ { - "name": "Theif Lord", + "rating": 4.8, + "_group": []map[string]any{ + { + "name": "Theif Lord", + }, + }, }, }, }, - }, - }, - { - "name": "John Grisham", - "age": int64(65), - "published": []map[string]any{ { - "rating": 4.5, - "_group": []map[string]any{ + "name": "John Grisham", + "age": int64(65), + "published": []map[string]any{ { - "name": "The Client", + "rating": 4.5, + "_group": []map[string]any{ + { + "name": "The Client", + }, + { + "name": "A Time for Mercy", + }, + }, }, { - "name": "A Time for Mercy", - }, - }, - }, - { - "rating": 4.9, - "_group": []map[string]any{ - { - "name": "Painted House", + "rating": 4.9, + "_group": []map[string]any{ + { + "name": "Painted House", + }, + }, }, }, }, @@ -124,122 +136,142 @@ func TestQueryOneToManyWithInnerJoinGroupNumber(t *testing.T) { } func TestQueryOneToManyWithParentJoinGroupNumber(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from many side with parent level group", - Request: `query { - Author (groupBy: [age]) { - age - _group { - name - published { - name - rating - } - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Client", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Candide", "rating": 4.95, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Zadig", "rating": 4.91, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ - "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", - "rating": 2, - "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614" - }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ + "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", + "rating": 2, + "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614" + }`, + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Voltaire", "age": 327, "verified": true }`, - // bae-34a9bd41-1f0d-5748-8446-48fc36ef2614 - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Simon Pelloutier", "age": 327, "verified": true }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "age": int64(327), - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Author (groupBy: [age]) { + age + _group { + name + published { + name + rating + } + } + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ { - "name": "Voltaire", - "published": []map[string]any{ + "age": int64(327), + "_group": []map[string]any{ { - "name": "Candide", - "rating": 4.95, + "name": "Voltaire", + "published": []map[string]any{ + { + "name": "Candide", + "rating": 4.95, + }, + { + "name": "Zadig", + "rating": 4.91, + }, + }, }, { - "name": "Zadig", - "rating": 4.91, - }, - }, - }, - { - "name": "Simon Pelloutier", - "published": []map[string]any{ - { - "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", - "rating": float64(2), + "name": "Simon Pelloutier", + "published": []map[string]any{ + { + "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", + "rating": float64(2), + }, + }, }, }, }, - }, - }, - { - "age": int64(65), - "_group": []map[string]any{ { - "name": "John Grisham", - "published": []map[string]any{ - { - "name": "The Client", - "rating": 4.5, - }, - { - "name": "Painted House", - "rating": 4.9, - }, + "age": int64(65), + "_group": []map[string]any{ { - "name": "A Time for Mercy", - "rating": 4.5, + "name": "John Grisham", + "published": []map[string]any{ + { + "name": "The Client", + "rating": 4.5, + }, + { + "name": "Painted House", + "rating": 4.9, + }, + { + "name": "A Time for Mercy", + "rating": 4.5, + }, + }, }, }, }, @@ -253,23 +285,26 @@ func TestQueryOneToManyWithParentJoinGroupNumber(t *testing.T) { } func TestQueryOneToManyWithInnerJoinGroupNumberWithNonGroupFieldsSelected(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from many side with group inside of join and invalid field", - Request: `query { - Author { - name - age - published (groupBy: [rating]){ - rating - name - _group { + Actions: []any{ + testUtils.Request{ + Request: `query { + Author { name + age + published (groupBy: [rating]){ + rating + name + _group { + name + } + } } - } - } - }`, - Docs: map[int][]string{}, - ExpectedError: "cannot select a non-group-by field at group-level", + }`, + ExpectedError: "cannot select a non-group-by field at group-level", + }, + }, } executeTestCase(t, test) diff --git a/tests/integration/query/one_to_many/with_limit_test.go b/tests/integration/query/one_to_many/with_limit_test.go index 1cfbaf6d98..8badd8f742 100644 --- a/tests/integration/query/one_to_many/with_limit_test.go +++ b/tests/integration/query/one_to_many/with_limit_test.go @@ -17,69 +17,78 @@ import ( ) func TestQueryOneToManyWithSingleChildLimit(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from many side with limit", - Request: `query { - Author { - name - published (limit: 1) { - name - rating - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "Cornelia Funke", - "published": []map[string]any{ + testUtils.Request{ + Request: `query { + Author { + name + published (limit: 1) { + name + rating + } + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ { - "name": "Theif Lord", - "rating": 4.8, + "name": "Cornelia Funke", + "published": []map[string]any{ + { + "name": "Theif Lord", + "rating": 4.8, + }, + }, }, - }, - }, - { - "name": "John Grisham", - "published": []map[string]any{ { - "name": "Painted House", - "rating": 4.9, + "name": "John Grisham", + "published": []map[string]any{ + { + "name": "Painted House", + "rating": 4.9, + }, + }, }, }, }, @@ -91,89 +100,98 @@ func TestQueryOneToManyWithSingleChildLimit(t *testing.T) { } func TestQueryOneToManyWithMultipleChildLimits(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from many side with limit", - Request: `query { - Author { - name - p1: published (limit: 1) { - name - rating - } - p2: published (limit: 2) { - name - rating - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "Cornelia Funke", - "p1": []map[string]any{ - { - "name": "Theif Lord", - "rating": 4.8, - }, - }, - "p2": []map[string]any{ - { - "name": "Theif Lord", - "rating": 4.8, - }, - }, - }, - { - "name": "John Grisham", - "p1": []map[string]any{ - { - "name": "Painted House", - "rating": 4.9, - }, - }, - "p2": []map[string]any{ + testUtils.Request{ + Request: `query { + Author { + name + p1: published (limit: 1) { + name + rating + } + p2: published (limit: 2) { + name + rating + } + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ { - "name": "Painted House", - "rating": 4.9, + "name": "Cornelia Funke", + "p1": []map[string]any{ + { + "name": "Theif Lord", + "rating": 4.8, + }, + }, + "p2": []map[string]any{ + { + "name": "Theif Lord", + "rating": 4.8, + }, + }, }, { - "name": "A Time for Mercy", - "rating": 4.5, + "name": "John Grisham", + "p1": []map[string]any{ + { + "name": "Painted House", + "rating": 4.9, + }, + }, + "p2": []map[string]any{ + { + "name": "Painted House", + "rating": 4.9, + }, + { + "name": "A Time for Mercy", + "rating": 4.5, + }, + }, }, }, }, diff --git a/tests/integration/query/one_to_many/with_order_filter_limit_test.go b/tests/integration/query/one_to_many/with_order_filter_limit_test.go index d10fabb100..f1602985d1 100644 --- a/tests/integration/query/one_to_many/with_order_filter_limit_test.go +++ b/tests/integration/query/one_to_many/with_order_filter_limit_test.go @@ -19,62 +19,71 @@ import ( func TestQueryOneToManyWithNumericGreaterThanFilterOnParentAndNumericSortAscendingAndLimitOnChild( t *testing.T, ) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from the many side, asc. order & limit on sub", - Request: `query { - Author(filter: {age: {_gt: 63}}) { - name - age - published(order: {rating: ASC}, limit: 1) { - name - rating - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "John Grisham", - "age": int64(65), - "published": []map[string]any{ + testUtils.Request{ + Request: `query { + Author(filter: {age: {_gt: 63}}) { + name + age + published(order: {rating: ASC}, limit: 1) { + name + rating + } + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ { - "name": "A Time for Mercy", - "rating": 4.5, + "name": "John Grisham", + "age": int64(65), + "published": []map[string]any{ + { + "name": "A Time for Mercy", + "rating": 4.5, + }, + }, }, }, }, @@ -88,62 +97,71 @@ func TestQueryOneToManyWithNumericGreaterThanFilterOnParentAndNumericSortAscendi func TestQueryOneToManyWithNumericGreaterThanFilterOnParentAndNumericSortDescendingAndLimitOnChild( t *testing.T, ) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from the many side, desc. order & limit on sub", - Request: `query { - Author(filter: {age: {_gt: 63}}) { - name - age - published(order: {rating: DESC}, limit: 1) { - name - rating - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "John Grisham", - "age": int64(65), - "published": []map[string]any{ + testUtils.Request{ + Request: `query { + Author(filter: {age: {_gt: 63}}) { + name + age + published(order: {rating: DESC}, limit: 1) { + name + rating + } + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ { - "name": "Painted House", - "rating": 4.9, + "name": "John Grisham", + "age": int64(65), + "published": []map[string]any{ + { + "name": "Painted House", + "rating": 4.9, + }, + }, }, }, }, diff --git a/tests/integration/query/one_to_many/with_order_filter_test.go b/tests/integration/query/one_to_many/with_order_filter_test.go index 3aec1e6a73..42ec0f85d5 100644 --- a/tests/integration/query/one_to_many/with_order_filter_test.go +++ b/tests/integration/query/one_to_many/with_order_filter_test.go @@ -19,66 +19,75 @@ import ( func TestQueryOneToManyWithNumericGreaterThanFilterOnParentAndNumericSortAscendingOnChild( t *testing.T, ) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from the many side, order on sub", - Request: `query { - Author(filter: {age: {_gt: 63}}) { - name - age - published(order: {rating: ASC}) { - name - rating - } - } - }`, - Docs: map[int][]string{ - //books - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "John Grisham", - "age": int64(65), - "published": []map[string]any{ - { - "name": "A Time for Mercy", - "rating": 4.5, - }, + testUtils.Request{ + Request: `query { + Author(filter: {age: {_gt: 63}}) { + name + age + published(order: {rating: ASC}) { + name + rating + } + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ { - "name": "Painted House", - "rating": 4.9, + "name": "John Grisham", + "age": int64(65), + "published": []map[string]any{ + { + "name": "A Time for Mercy", + "rating": 4.5, + }, + { + "name": "Painted House", + "rating": 4.9, + }, + }, }, }, }, @@ -90,76 +99,85 @@ func TestQueryOneToManyWithNumericGreaterThanFilterOnParentAndNumericSortAscendi } func TestQueryOneToManyWithNumericGreaterThanFilterAndNumericSortDescendingOnChild(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from the many side, filter on sub from root", - Request: `query { - Author(filter: {published: {rating: {_gt: 4.1}}}) { - name - age - published(order: {rating: DESC}) { - name - rating - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "Cornelia Funke", - "age": int64(62), - "published": []map[string]any{ - { - "name": "Theif Lord", - "rating": 4.8, - }, - }, - }, - { - "name": "John Grisham", - "age": int64(65), - "published": []map[string]any{ + testUtils.Request{ + Request: `query { + Author(filter: {published: {rating: {_gt: 4.1}}}) { + name + age + published(order: {rating: DESC}) { + name + rating + } + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ { - "name": "Painted House", - "rating": 4.9, + "name": "Cornelia Funke", + "age": int64(62), + "published": []map[string]any{ + { + "name": "Theif Lord", + "rating": 4.8, + }, + }, }, { - "name": "A Time for Mercy", - "rating": 4.5, + "name": "John Grisham", + "age": int64(65), + "published": []map[string]any{ + { + "name": "Painted House", + "rating": 4.9, + }, + { + "name": "A Time for Mercy", + "rating": 4.5, + }, + }, }, }, }, diff --git a/tests/integration/query/one_to_many/with_related_id_test.go b/tests/integration/query/one_to_many/with_related_id_test.go index c5955352b5..906719c532 100644 --- a/tests/integration/query/one_to_many/with_related_id_test.go +++ b/tests/integration/query/one_to_many/with_related_id_test.go @@ -17,100 +17,115 @@ import ( ) func TestQueryOneToManyWithRelatedTypeIDFromManySide(t *testing.T) { - test := testUtils.RequestTestCase{ - + test := testUtils.TestCase{ Description: "One-to-many query with related id (from many side).", - - Request: `query { - Book { - name - author_id - } - }`, - - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Client", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Candide", "rating": 4.95, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Zadig", "rating": 4.91, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", "rating": 2, "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614" }`, }, - - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Voltaire", "age": 327, "verified": true }`, - // bae-34a9bd41-1f0d-5748-8446-48fc36ef2614 - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Simon Pelloutier", "age": 327, "verified": true }`, }, - }, - - Results: map[string]any{ - "Book": []map[string]any{ - { - "name": "The Client", - "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b", - }, - { - "name": "Painted House", - "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b", - }, - { - "name": "A Time for Mercy", - "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b", - }, - { - "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", - "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614", - }, - { - "name": "Candide", - "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c", - }, - { - "name": "Zadig", - "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c", + testUtils.Request{ + Request: `query { + Book { + name + author_id + } + }`, + Results: map[string]any{ + "Book": []map[string]any{ + { + "name": "The Client", + "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b", + }, + { + "name": "Painted House", + "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b", + }, + { + "name": "A Time for Mercy", + "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b", + }, + { + "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", + "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614", + }, + { + "name": "Candide", + "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c", + }, + { + "name": "Zadig", + "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c", + }, + }, }, }, }, @@ -120,76 +135,91 @@ func TestQueryOneToManyWithRelatedTypeIDFromManySide(t *testing.T) { } func TestQueryOneToManyWithRelatedTypeIDFromSingleSide(t *testing.T) { - test := testUtils.RequestTestCase{ - + test := testUtils.TestCase{ Description: "One-to-many query with related id (from single side).", - - Request: `query { - Author { - name - author_id - } - }`, - - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Client", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Candide", "rating": 4.95, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Zadig", "rating": 4.91, "author_id": "bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Histoiare des Celtes et particulierement des Gaulois et des Germains depuis les temps fabuleux jusqua la prise de Roze par les Gaulois", "rating": 2, "author_id": "bae-34a9bd41-1f0d-5748-8446-48fc36ef2614" }`, }, - - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-1594d2aa-d63c-51d2-8e5e-06ee0c9e2e8c - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Voltaire", "age": 327, "verified": true }`, - // bae-34a9bd41-1f0d-5748-8446-48fc36ef2614 - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Simon Pelloutier", "age": 327, "verified": true }`, }, + testUtils.Request{ + Request: `query { + Author { + name + author_id + } + }`, + ExpectedError: "Cannot query field \"author_id\" on type \"Author\".", + }, }, - - ExpectedError: "Cannot query field \"author_id\" on type \"Author\".", } executeTestCase(t, test) diff --git a/tests/integration/query/one_to_many/with_same_field_name_test.go b/tests/integration/query/one_to_many/with_same_field_name_test.go index fbe56099b5..c16774ac25 100644 --- a/tests/integration/query/one_to_many/with_same_field_name_test.go +++ b/tests/integration/query/one_to_many/with_same_field_name_test.go @@ -17,10 +17,10 @@ import ( ) var sameFieldNameGQLSchema = (` - type Book { - name: String - relationship1: Author - } + type Book { + name: String + relationship1: Author + } type Author { name: String @@ -28,43 +28,58 @@ var sameFieldNameGQLSchema = (` } `) -func executeSameFieldNameTestCase(t *testing.T, test testUtils.RequestTestCase) { - testUtils.ExecuteRequestTestCase(t, sameFieldNameGQLSchema, []string{"Book", "Author"}, test) +func executeSameFieldNameTestCase(t *testing.T, test testUtils.TestCase) { + testUtils.ExecuteTestCase( + t, + testUtils.TestCase{ + Description: test.Description, + Actions: append( + []any{ + testUtils.SchemaUpdate{ + Schema: sameFieldNameGQLSchema, + }, + }, + test.Actions..., + ), + }, + ) } func TestQueryOneToManyWithSameFieldName(t *testing.T) { - tests := []testUtils.RequestTestCase{ + tests := []testUtils.TestCase{ { Description: "One-to-many relation query from one side, same field name", - Request: `query { - Book { - name - relationship1 { - name - } - } - }`, - Docs: map[int][]string{ - //books - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "relationship1_id": "bae-ee5973cf-73c3-558f-8aec-8b590b8e77cf" }`, }, - //authors - 1: { // bae-ee5973cf-73c3-558f-8aec-8b590b8e77cf - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham" }`, }, - }, - Results: map[string]any{ - "Book": []map[string]any{ - { - "name": "Painted House", - "relationship1": map[string]any{ - "name": "John Grisham", + testUtils.Request{ + Request: `query { + Book { + name + relationship1 { + name + } + } + }`, + Results: map[string]any{ + "Book": []map[string]any{ + { + "name": "Painted House", + "relationship1": map[string]any{ + "name": "John Grisham", + }, + }, }, }, }, @@ -72,36 +87,39 @@ func TestQueryOneToManyWithSameFieldName(t *testing.T) { }, { Description: "One-to-many relation query from many side, same field name", - Request: `query { - Author { - name - relationship1 { - name - } - } - }`, - Docs: map[int][]string{ - //books - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "relationship1_id": "bae-ee5973cf-73c3-558f-8aec-8b590b8e77cf" }`, }, - //authors - 1: { // bae-ee5973cf-73c3-558f-8aec-8b590b8e77cf - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham" }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "John Grisham", - "relationship1": []map[string]any{ + testUtils.Request{ + Request: `query { + Author { + name + relationship1 { + name + } + } + }`, + + Results: map[string]any{ + "Author": []map[string]any{ { - "name": "Painted House", + "name": "John Grisham", + "relationship1": []map[string]any{ + { + "name": "Painted House", + }, + }, }, }, }, diff --git a/tests/integration/query/one_to_many/with_sum_filter_order_test.go b/tests/integration/query/one_to_many/with_sum_filter_order_test.go index 0c2fcc0b70..46d36c82d8 100644 --- a/tests/integration/query/one_to_many/with_sum_filter_order_test.go +++ b/tests/integration/query/one_to_many/with_sum_filter_order_test.go @@ -17,88 +17,111 @@ import ( ) func TestOneToManyAscOrderAndFilterOnParentWithAggSumOnSubTypeField(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "1-N ascending order & filter on parent, with sum on on subtype field.", - Request: `query { - Author(order: {age: ASC}, filter: {age: {_gt: 8}}) { - name - _sum(published: {field: rating}) - } - }`, - - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Associate", "rating": 4.2, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Sooley", "rating": 3.2, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Rooster Bar", "rating": 4, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Little Kid", "age": 6, "verified": true }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Not a Writer", "age": 85, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "Cornelia Funke", - "_sum": 4.8, - }, - { - "name": "John Grisham", - "_sum": 20.8, - }, - { - "name": "Not a Writer", - "_sum": 0.0, + testUtils.Request{ + Request: `query { + Author(order: {age: ASC}, filter: {age: {_gt: 8}}) { + name + _sum(published: {field: rating}) + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ + { + "name": "Cornelia Funke", + "_sum": 4.8, + }, + { + "name": "John Grisham", + "_sum": 20.8, + }, + { + "name": "Not a Writer", + "_sum": 0.0, + }, + }, }, }, }, @@ -108,88 +131,111 @@ func TestOneToManyAscOrderAndFilterOnParentWithAggSumOnSubTypeField(t *testing.T } func TestOneToManyDescOrderAndFilterOnParentWithAggSumOnSubTypeField(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "1-N descending order & filter on parent, with sum on on subtype field.", - Request: `query { - Author(order: {age: DESC}, filter: {age: {_gt: 8}}) { - name - _sum(published: {field: rating}) - } - }`, - - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Associate", "rating": 4.2, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Sooley", "rating": 3.2, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Rooster Bar", "rating": 4, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Little Kid", "age": 6, "verified": true }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Not a Writer", "age": 85, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "Not a Writer", - "_sum": 0.0, - }, - { - "name": "John Grisham", - "_sum": 20.8, - }, - { - "name": "Cornelia Funke", - "_sum": 4.8, + testUtils.Request{ + Request: `query { + Author(order: {age: DESC}, filter: {age: {_gt: 8}}) { + name + _sum(published: {field: rating}) + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ + { + "name": "Not a Writer", + "_sum": 0.0, + }, + { + "name": "John Grisham", + "_sum": 20.8, + }, + { + "name": "Cornelia Funke", + "_sum": 4.8, + }, + }, }, }, }, @@ -199,97 +245,120 @@ func TestOneToManyDescOrderAndFilterOnParentWithAggSumOnSubTypeField(t *testing. } func TestOnetoManySumBySubTypeFieldAndSumBySybTypeFieldWithDescOrderingOnFieldWithLimit(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "1-N sum subtype and sum subtype with desc. order on field with limit.", - Request: `query { - Author { - name - sum1: _sum(published: {field: rating}) - sum2: _sum(published: {field: rating, limit: 2, order: {rating: DESC}}) - } - }`, - - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Associate", "rating": 4.2, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Sooley", "rating": 3.2, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Rooster Bar", "rating": 4, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Little Kid", "age": 6, "verified": true }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Not a Writer", "age": 85, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "Little Kid", - "sum1": 0.0, - "sum2": 0.0, - }, - { - "name": "Not a Writer", - "sum1": 0.0, - "sum2": 0.0, - }, - { - "name": "Cornelia Funke", - "sum1": 4.8, - "sum2": 4.8, - }, - { - "name": "John Grisham", - "sum1": 20.8, - "sum2": 4.9 + 4.5, + testUtils.Request{ + Request: `query { + Author { + name + sum1: _sum(published: {field: rating}) + sum2: _sum(published: {field: rating, limit: 2, order: {rating: DESC}}) + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ + { + "name": "Little Kid", + "sum1": 0.0, + "sum2": 0.0, + }, + { + "name": "Not a Writer", + "sum1": 0.0, + "sum2": 0.0, + }, + { + "name": "Cornelia Funke", + "sum1": 4.8, + "sum2": 4.8, + }, + { + "name": "John Grisham", + "sum1": 20.8, + "sum2": 4.9 + 4.5, + }, + }, }, }, }, @@ -299,97 +368,120 @@ func TestOnetoManySumBySubTypeFieldAndSumBySybTypeFieldWithDescOrderingOnFieldWi } func TestOnetoManySumBySubTypeFieldAndSumBySybTypeFieldWithAscOrderingOnFieldWithLimit(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "1-N sum subtype and sum subtype with asc. order on field with limit.", - Request: `query { - Author { - name - sum1: _sum(published: {field: rating}) - sum2: _sum(published: {field: rating, limit: 2, order: {rating: ASC}}) - } - }`, - - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Associate", "rating": 4.2, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Sooley", "rating": 3.2, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Rooster Bar", "rating": 4, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Little Kid", "age": 6, "verified": true }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Not a Writer", "age": 85, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "Little Kid", - "sum1": 0.0, - "sum2": 0.0, - }, - { - "name": "Not a Writer", - "sum1": 0.0, - "sum2": 0.0, - }, - { - "name": "Cornelia Funke", - "sum1": 4.8, - "sum2": 4.8, - }, - { - "name": "John Grisham", - "sum1": 20.8, - "sum2": 4.0 + 3.2, + testUtils.Request{ + Request: `query { + Author { + name + sum1: _sum(published: {field: rating}) + sum2: _sum(published: {field: rating, limit: 2, order: {rating: ASC}}) + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ + { + "name": "Little Kid", + "sum1": 0.0, + "sum2": 0.0, + }, + { + "name": "Not a Writer", + "sum1": 0.0, + "sum2": 0.0, + }, + { + "name": "Cornelia Funke", + "sum1": 4.8, + "sum2": 4.8, + }, + { + "name": "John Grisham", + "sum1": 20.8, + "sum2": 4.0 + 3.2, + }, + }, }, }, }, @@ -399,103 +491,126 @@ func TestOnetoManySumBySubTypeFieldAndSumBySybTypeFieldWithAscOrderingOnFieldWit } func TestOneToManyLimitAscOrderSumOfSubTypeAndLimitAscOrderFieldsOfSubtype(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "1-N sum of subtype float field with limit and asc. order, and non-sum query of same subtype fields.", - Request: `query { - Author { - LimitOrderSum: _sum(published: {field: rating, limit: 2, order: {rating: ASC}}) - LimitOrderFields: published(order: {rating: ASC}, limit: 2) { - name - } - } - }`, - - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Associate", "rating": 4.2, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Sooley", "rating": 3.2, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Rooster Bar", "rating": 4, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Little Kid", "age": 6, "verified": true }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Not a Writer", "age": 85, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "LimitOrderSum": 0.0, - "LimitOrderFields": []map[string]any{}, - }, - { - "LimitOrderSum": 0.0, - "LimitOrderFields": []map[string]any{}, - }, - { - "LimitOrderSum": 4.8, - "LimitOrderFields": []map[string]any{ + testUtils.Request{ + Request: `query { + Author { + LimitOrderSum: _sum(published: {field: rating, limit: 2, order: {rating: ASC}}) + LimitOrderFields: published(order: {rating: ASC}, limit: 2) { + name + } + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ { - "name": "Theif Lord", + "LimitOrderSum": 0.0, + "LimitOrderFields": []map[string]any{}, + }, + { + "LimitOrderSum": 0.0, + "LimitOrderFields": []map[string]any{}, }, - }, - }, - { - "LimitOrderSum": 3.2 + 4.0, - "LimitOrderFields": []map[string]any{ { - "name": "Sooley", + "LimitOrderSum": 4.8, + "LimitOrderFields": []map[string]any{ + { + "name": "Theif Lord", + }, + }, }, { - "name": "The Rooster Bar", + "LimitOrderSum": 3.2 + 4.0, + "LimitOrderFields": []map[string]any{ + { + "name": "Sooley", + }, + { + "name": "The Rooster Bar", + }, + }, }, }, }, @@ -507,103 +622,126 @@ func TestOneToManyLimitAscOrderSumOfSubTypeAndLimitAscOrderFieldsOfSubtype(t *te } func TestOneToManyLimitDescOrderSumOfSubTypeAndLimitAscOrderFieldsOfSubtype(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "1-N sum of subtype float field with limit and desc. order, and non-sum query of same subtype fields.", - Request: `query { - Author { - LimitOrderSum: _sum(published: {field: rating, limit: 2, order: {rating: DESC}}) - LimitOrderFields: published(order: {rating: DESC}, limit: 2) { - name - } - } - }`, - - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Associate", "rating": 4.2, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Sooley", "rating": 3.2, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Rooster Bar", "rating": 4, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Little Kid", "age": 6, "verified": true }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Not a Writer", "age": 85, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "LimitOrderSum": 0.0, - "LimitOrderFields": []map[string]any{}, - }, - { - "LimitOrderSum": 0.0, - "LimitOrderFields": []map[string]any{}, - }, - { - "LimitOrderSum": 4.8, - "LimitOrderFields": []map[string]any{ + testUtils.Request{ + Request: `query { + Author { + LimitOrderSum: _sum(published: {field: rating, limit: 2, order: {rating: DESC}}) + LimitOrderFields: published(order: {rating: DESC}, limit: 2) { + name + } + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ { - "name": "Theif Lord", + "LimitOrderSum": 0.0, + "LimitOrderFields": []map[string]any{}, + }, + { + "LimitOrderSum": 0.0, + "LimitOrderFields": []map[string]any{}, }, - }, - }, - { - "LimitOrderSum": 4.9 + 4.5, - "LimitOrderFields": []map[string]any{ { - "name": "Painted House", + "LimitOrderSum": 4.8, + "LimitOrderFields": []map[string]any{ + { + "name": "Theif Lord", + }, + }, }, { - "name": "A Time for Mercy", + "LimitOrderSum": 4.9 + 4.5, + "LimitOrderFields": []map[string]any{ + { + "name": "Painted House", + }, + { + "name": "A Time for Mercy", + }, + }, }, }, }, diff --git a/tests/integration/query/one_to_many/with_sum_limit_offset_test.go b/tests/integration/query/one_to_many/with_sum_limit_offset_test.go index 3fce23bfd5..420deeca19 100644 --- a/tests/integration/query/one_to_many/with_sum_limit_offset_test.go +++ b/tests/integration/query/one_to_many/with_sum_limit_offset_test.go @@ -17,63 +17,75 @@ import ( ) func TestQueryOneToManyWithSumWithLimitAndOffset(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from many side with sum with limit and offset", - Request: `query { - Author { - name - _sum(published: {field: rating, offset: 1, limit: 2}) - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Associate", "rating": 4.2, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "Cornelia Funke", - "_sum": float64(0), - }, - { - "name": "John Grisham", - "_sum": 9.4, + testUtils.Request{ + Request: `query { + Author { + name + _sum(published: {field: rating, offset: 1, limit: 2}) + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ + { + "name": "Cornelia Funke", + "_sum": float64(0), + }, + { + "name": "John Grisham", + "_sum": 9.4, + }, + }, }, }, }, diff --git a/tests/integration/query/one_to_many/with_sum_limit_test.go b/tests/integration/query/one_to_many/with_sum_limit_test.go index 4ab46b65bd..b3cfba74b0 100644 --- a/tests/integration/query/one_to_many/with_sum_limit_test.go +++ b/tests/integration/query/one_to_many/with_sum_limit_test.go @@ -17,64 +17,76 @@ import ( ) func TestQueryOneToManyWithSumWithLimit(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from many side with sum with limit", - Request: `query { - Author { - name - _sum(published: {field: rating, limit: 2}) - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "A Time for Mercy", "rating": 4.5, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "The Associate", "rating": 4.2, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8, "author_id": "bae-72e8c691-9f20-55e7-9228-8af1cf54cace" }`, }, - //authors - 1: { - // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, - // bae-72e8c691-9f20-55e7-9228-8af1cf54cace - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "Cornelia Funke", - "_sum": 4.8, - }, - { - "name": "John Grisham", - // .00...1 is float math thing - "_sum": 9.100000000000001, + testUtils.Request{ + Request: `query { + Author { + name + _sum(published: {field: rating, limit: 2}) + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ + { + "name": "Cornelia Funke", + "_sum": 4.8, + }, + { + "name": "John Grisham", + // .00...1 is float math thing + "_sum": 9.100000000000001, + }, + }, }, }, }, diff --git a/tests/integration/query/one_to_many/with_typename_test.go b/tests/integration/query/one_to_many/with_typename_test.go index da627c8625..b4852b2d4e 100644 --- a/tests/integration/query/one_to_many/with_typename_test.go +++ b/tests/integration/query/one_to_many/with_typename_test.go @@ -17,44 +17,46 @@ import ( ) func TestQueryOneToManyWithTypeName(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-many relation query from one side with typename", - Request: `query { - Book { - name - __typename - author { - name - __typename - } - } - }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9, "author_id": "bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b" }`, }, - //authors - 1: { // bae-e1ea288f-09fa-55fa-b0b5-0ac8941ea35b - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true }`, }, - }, - Results: map[string]any{ - "Book": []map[string]any{ - { - "name": "Painted House", - "__typename": "Book", - "author": map[string]any{ - "name": "John Grisham", - "__typename": "Author", + testUtils.Request{ + Request: `query { + Book { + name + __typename + author { + name + __typename + } + } + }`, + Results: map[string]any{ + "Book": []map[string]any{ + { + "name": "Painted House", + "__typename": "Book", + "author": map[string]any{ + "name": "John Grisham", + "__typename": "Author", + }, + }, }, }, }, diff --git a/tests/integration/query/one_to_one/simple_test.go b/tests/integration/query/one_to_one/simple_test.go index 2ebad49df6..4433c3ff9c 100644 --- a/tests/integration/query/one_to_one/simple_test.go +++ b/tests/integration/query/one_to_one/simple_test.go @@ -17,10 +17,28 @@ import ( ) func TestQueryOneToOne(t *testing.T) { - tests := []testUtils.RequestTestCase{ + tests := []testUtils.TestCase{ { Description: "One-to-one relation query with no filter", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ + "name": "Painted House", + "rating": 4.9 + }`, + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ + "name": "John Grisham", + "age": 65, + "verified": true, + "published_id": "bae-be6d8024-4953-5a92-84b4-f042d25230c6" + }`, + }, + testUtils.Request{ + Request: `query { Book { name rating @@ -30,40 +48,42 @@ func TestQueryOneToOne(t *testing.T) { } } }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Results: map[string]any{ + "Book": []map[string]any{ + { + "name": "Painted House", + "rating": 4.9, + "author": map[string]any{ + "name": "John Grisham", + "age": int64(65), + }, + }, + }, + }, + }, + }, + }, + { + Description: "One-to-one relation secondary direction, no filter", + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9 }`, }, - //authors - 1: { // bae-7aabc9d2-fbbc-5911-b0d0-b49a2a1d0e84 - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true, "published_id": "bae-be6d8024-4953-5a92-84b4-f042d25230c6" }`, }, - }, - Results: map[string]any{ - "Book": []map[string]any{ - { - "name": "Painted House", - "rating": 4.9, - "author": map[string]any{ - "name": "John Grisham", - "age": int64(65), - }, - }, - }, - }, - }, - { - Description: "One-to-one relation secondary direction, no filter", - Request: `query { + testUtils.Request{ + Request: `query { Author { name age @@ -73,32 +93,16 @@ func TestQueryOneToOne(t *testing.T) { } } }`, - Docs: map[int][]string{ - //books - 0: { // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ - "name": "Painted House", - "rating": 4.9 - }`, - }, - //authors - 1: { // bae-7aabc9d2-fbbc-5911-b0d0-b49a2a1d0e84 - `{ - "name": "John Grisham", - "age": 65, - "verified": true, - "published_id": "bae-be6d8024-4953-5a92-84b4-f042d25230c6" - }`, - }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "John Grisham", - "age": int64(65), - "published": map[string]any{ - "name": "Painted House", - "rating": 4.9, + Results: map[string]any{ + "Author": []map[string]any{ + { + "name": "John Grisham", + "age": int64(65), + "published": map[string]any{ + "name": "Painted House", + "rating": 4.9, + }, + }, }, }, }, @@ -274,29 +278,31 @@ func TestQueryOneToOneWithMultipleRecordsSecondaryDirection(t *testing.T) { } func TestQueryOneToOneWithNilChild(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-one relation primary direction, nil child", - Request: `query { - Author { - name - published { - name - } - } - }`, - Docs: map[int][]string{ - //authors - 1: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham" }`, }, - }, - Results: map[string]any{ - "Author": []map[string]any{ - { - "name": "John Grisham", - "published": nil, + testUtils.Request{ + Request: `query { + Author { + name + published { + name + } + } + }`, + Results: map[string]any{ + "Author": []map[string]any{ + { + "name": "John Grisham", + "published": nil, + }, + }, }, }, }, @@ -306,29 +312,30 @@ func TestQueryOneToOneWithNilChild(t *testing.T) { } func TestQueryOneToOneWithNilParent(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-one relation primary direction, nil parent", - Request: `query { - Book { - name - author { - name - } - } - }`, - Docs: map[int][]string{ - //books - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "name": "Painted House" }`, }, - }, - Results: map[string]any{ - "Book": []map[string]any{ - { - "name": "Painted House", - "author": nil, + testUtils.Request{ + Request: `query { + Book { + name + author { + name + } + } + }`, + Results: map[string]any{ + "Book": []map[string]any{ + { + "name": "Painted House", + "author": nil, + }, + }, }, }, }, diff --git a/tests/integration/query/one_to_one/utils.go b/tests/integration/query/one_to_one/utils.go index 64aa7590fb..0778ce4b0a 100644 --- a/tests/integration/query/one_to_one/utils.go +++ b/tests/integration/query/one_to_one/utils.go @@ -31,6 +31,19 @@ var bookAuthorGQLSchema = ` } ` -func executeTestCase(t *testing.T, test testUtils.RequestTestCase) { - testUtils.ExecuteRequestTestCase(t, bookAuthorGQLSchema, []string{"Book", "Author"}, test) +func executeTestCase(t *testing.T, test testUtils.TestCase) { + testUtils.ExecuteTestCase( + t, + testUtils.TestCase{ + Description: test.Description, + Actions: append( + []any{ + testUtils.SchemaUpdate{ + Schema: bookAuthorGQLSchema, + }, + }, + test.Actions..., + ), + }, + ) } diff --git a/tests/integration/query/one_to_one/with_filter_order_test.go b/tests/integration/query/one_to_one/with_filter_order_test.go index 24682d4fb4..90682b31e3 100644 --- a/tests/integration/query/one_to_one/with_filter_order_test.go +++ b/tests/integration/query/one_to_one/with_filter_order_test.go @@ -17,58 +17,62 @@ import ( ) func TestOnetoOneSubTypeDscOrderByQueryWithFilterHavinghNoSubTypeSelections(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-one subtype descending order query with filter, no subtype child fields selected.", - Request: `query { - Book( - filter: {author: {age: {_gt: 5}}}, - order: {author: {age: DESC}} - ){ - name - rating - } - }`, - Docs: map[int][]string{ - //books - 0: { - // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9 }`, - // bae-26a28d23-ae5b-5257-91b7-d4f2c6abef7b - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8 }`, }, - //authors - 1: { - // "bae-3bfe0092-e31f-5ebe-a3ba-fa18fac448a6" - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true, "published_id": "bae-be6d8024-4953-5a92-84b4-f042d25230c6" }`, - // "bae-08519989-280d-5a4d-90b2-915ea06df3c4" - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false, "published_id": "bae-26a28d23-ae5b-5257-91b7-d4f2c6abef7b" }`, }, - }, - Results: map[string]any{ - "Book": []map[string]any{ - { - "name": "Painted House", - "rating": 4.9, - }, - { - "name": "Theif Lord", - "rating": 4.8, + testUtils.Request{ + Request: `query { + Book( + filter: {author: {age: {_gt: 5}}}, + order: {author: {age: DESC}} + ){ + name + rating + } + }`, + Results: map[string]any{ + "Book": []map[string]any{ + { + "name": "Painted House", + "rating": 4.9, + }, + { + "name": "Theif Lord", + "rating": 4.8, + }, + }, }, }, }, @@ -78,58 +82,62 @@ func TestOnetoOneSubTypeDscOrderByQueryWithFilterHavinghNoSubTypeSelections(t *t } func TestOnetoOneSubTypeAscOrderByQueryWithFilterHavinghNoSubTypeSelections(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-one subtype ascending order query with filter, no subtype child fields selected.", - Request: `query { - Book( - filter: {author: {age: {_gt: 5}}}, - order: {author: {age: ASC}} - ){ - name - rating - } - }`, - Docs: map[int][]string{ - //books - 0: { - // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9 }`, - // bae-26a28d23-ae5b-5257-91b7-d4f2c6abef7b - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8 }`, }, - //authors - 1: { - // "bae-3bfe0092-e31f-5ebe-a3ba-fa18fac448a6" - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true, "published_id": "bae-be6d8024-4953-5a92-84b4-f042d25230c6" }`, - // "bae-08519989-280d-5a4d-90b2-915ea06df3c4" - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false, "published_id": "bae-26a28d23-ae5b-5257-91b7-d4f2c6abef7b" }`, }, - }, - Results: map[string]any{ - "Book": []map[string]any{ - { - "name": "Theif Lord", - "rating": 4.8, - }, - { - "name": "Painted House", - "rating": 4.9, + testUtils.Request{ + Request: `query { + Book( + filter: {author: {age: {_gt: 5}}}, + order: {author: {age: ASC}} + ){ + name + rating + } + }`, + Results: map[string]any{ + "Book": []map[string]any{ + { + "name": "Theif Lord", + "rating": 4.8, + }, + { + "name": "Painted House", + "rating": 4.9, + }, + }, }, }, }, diff --git a/tests/integration/query/one_to_one/with_order_test.go b/tests/integration/query/one_to_one/with_order_test.go index 9a2ca8c4c9..3475ebfc63 100644 --- a/tests/integration/query/one_to_one/with_order_test.go +++ b/tests/integration/query/one_to_one/with_order_test.go @@ -17,66 +17,70 @@ import ( ) func TestQueryOneToOneWithChildBooleanOrderDescending(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-one relation query with simple descending order by sub type", - Request: `query { - Book(order: {author: {verified: DESC}}) { - name - rating - author { - name - age - } - } - }`, - Docs: map[int][]string{ - //books - 0: { - // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9 }`, - // bae-26a28d23-ae5b-5257-91b7-d4f2c6abef7b - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8 }`, }, - //authors - 1: { - // bae-7aabc9d2-fbbc-5911-b0d0-b49a2a1d0e84 - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true, "published_id": "bae-be6d8024-4953-5a92-84b4-f042d25230c6" }`, - // bae-b769708d-f552-5c3d-a402-ccfd7ac7fb04 - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false, "published_id": "bae-26a28d23-ae5b-5257-91b7-d4f2c6abef7b" }`, }, - }, - Results: map[string]any{ - "Book": []map[string]any{ - { - "name": "Painted House", - "rating": 4.9, - "author": map[string]any{ - "name": "John Grisham", - "age": int64(65), - }, - }, - { - "name": "Theif Lord", - "rating": 4.8, - "author": map[string]any{ - "name": "Cornelia Funke", - "age": int64(62), + testUtils.Request{ + Request: `query { + Book(order: {author: {verified: DESC}}) { + name + rating + author { + name + age + } + } + }`, + Results: map[string]any{ + "Book": []map[string]any{ + { + "name": "Painted House", + "rating": 4.9, + "author": map[string]any{ + "name": "John Grisham", + "age": int64(65), + }, + }, + { + "name": "Theif Lord", + "rating": 4.8, + "author": map[string]any{ + "name": "Cornelia Funke", + "age": int64(62), + }, + }, }, }, }, @@ -87,66 +91,70 @@ func TestQueryOneToOneWithChildBooleanOrderDescending(t *testing.T) { } func TestQueryOneToOneWithChildBooleanOrderAscending(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "One-to-one relation query with simple ascending order by sub type", - Request: `query { - Book(order: {author: {verified: ASC}}) { - name - rating - author { - name - age - } - } - }`, - Docs: map[int][]string{ - //books - 0: { - // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9 }`, - // bae-26a28d23-ae5b-5257-91b7-d4f2c6abef7b - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8 }`, }, - //authors - 1: { - // bae-7aabc9d2-fbbc-5911-b0d0-b49a2a1d0e84 - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true, "published_id": "bae-be6d8024-4953-5a92-84b4-f042d25230c6" }`, - // bae-b769708d-f552-5c3d-a402-ccfd7ac7fb04 - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false, "published_id": "bae-26a28d23-ae5b-5257-91b7-d4f2c6abef7b" }`, }, - }, - Results: map[string]any{ - "Book": []map[string]any{ - { - "name": "Theif Lord", - "rating": 4.8, - "author": map[string]any{ - "name": "Cornelia Funke", - "age": int64(62), - }, - }, - { - "name": "Painted House", - "rating": 4.9, - "author": map[string]any{ - "name": "John Grisham", - "age": int64(65), + testUtils.Request{ + Request: `query { + Book(order: {author: {verified: ASC}}) { + name + rating + author { + name + age + } + } + }`, + Results: map[string]any{ + "Book": []map[string]any{ + { + "name": "Theif Lord", + "rating": 4.8, + "author": map[string]any{ + "name": "Cornelia Funke", + "age": int64(62), + }, + }, + { + "name": "Painted House", + "rating": 4.9, + "author": map[string]any{ + "name": "John Grisham", + "age": int64(65), + }, + }, }, }, }, @@ -157,55 +165,59 @@ func TestQueryOneToOneWithChildBooleanOrderAscending(t *testing.T) { } func TestQueryOneToOneWithChildIntOrderDescendingWithNoSubTypeFieldsSelected(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Relation query with descending order by sub-type's int field, but only parent fields are selected.", - Request: `query { - Book(order: {author: {age: DESC}}) { - name - rating - } - }`, - Docs: map[int][]string{ - //books - 0: { - // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9 }`, - // bae-26a28d23-ae5b-5257-91b7-d4f2c6abef7b - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8 }`, }, - //authors - 1: { - // "bae-3bfe0092-e31f-5ebe-a3ba-fa18fac448a6" - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true, "published_id": "bae-be6d8024-4953-5a92-84b4-f042d25230c6" }`, - // "bae-08519989-280d-5a4d-90b2-915ea06df3c4" - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false, "published_id": "bae-26a28d23-ae5b-5257-91b7-d4f2c6abef7b" }`, }, - }, - Results: map[string]any{ - "Book": []map[string]any{ - { - "name": "Painted House", - "rating": 4.9, - }, - { - "name": "Theif Lord", - "rating": 4.8, + testUtils.Request{ + Request: `query { + Book(order: {author: {age: DESC}}) { + name + rating + } + }`, + Results: map[string]any{ + "Book": []map[string]any{ + { + "name": "Painted House", + "rating": 4.9, + }, + { + "name": "Theif Lord", + "rating": 4.8, + }, + }, }, }, }, @@ -215,55 +227,59 @@ func TestQueryOneToOneWithChildIntOrderDescendingWithNoSubTypeFieldsSelected(t * } func TestQueryOneToOneWithChildIntOrderAscendingWithNoSubTypeFieldsSelected(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Relation query with ascending order by sub-type's int field, but only parent fields are selected.", - Request: `query { - Book(order: {author: {age: ASC}}) { - name - rating - } - }`, - Docs: map[int][]string{ - //books - 0: { - // bae-be6d8024-4953-5a92-84b4-f042d25230c6 - `{ + Actions: []any{ + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Painted House", "rating": 4.9 }`, - // bae-26a28d23-ae5b-5257-91b7-d4f2c6abef7b - `{ + }, + testUtils.CreateDoc{ + CollectionID: 0, + Doc: `{ "name": "Theif Lord", "rating": 4.8 }`, }, - //authors - 1: { - // "bae-3bfe0092-e31f-5ebe-a3ba-fa18fac448a6" - `{ + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "John Grisham", "age": 65, "verified": true, "published_id": "bae-be6d8024-4953-5a92-84b4-f042d25230c6" }`, - // "bae-08519989-280d-5a4d-90b2-915ea06df3c4" - `{ + }, + testUtils.CreateDoc{ + CollectionID: 1, + Doc: `{ "name": "Cornelia Funke", "age": 62, "verified": false, "published_id": "bae-26a28d23-ae5b-5257-91b7-d4f2c6abef7b" }`, }, - }, - Results: map[string]any{ - "Book": []map[string]any{ - { - "name": "Theif Lord", - "rating": 4.8, - }, - { - "name": "Painted House", - "rating": 4.9, + testUtils.Request{ + Request: `query { + Book(order: {author: {age: ASC}}) { + name + rating + } + }`, + Results: map[string]any{ + "Book": []map[string]any{ + { + "name": "Theif Lord", + "rating": 4.8, + }, + { + "name": "Painted House", + "rating": 4.9, + }, + }, }, }, }, diff --git a/tests/integration/query/simple/simple_test.go b/tests/integration/query/simple/simple_test.go index fce69f1412..eff5b09d65 100644 --- a/tests/integration/query/simple/simple_test.go +++ b/tests/integration/query/simple/simple_test.go @@ -17,29 +17,31 @@ import ( ) func TestQuerySimple(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with no filter", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 21 + }`, + }, + testUtils.Request{ + Request: `query { Users { _docID Name Age } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 21 - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "_docID": "bae-d4303725-7db9-53d2-b324-f3ee44020e52", - "Name": "John", - "Age": int64(21), + Results: map[string]any{ + "Users": []map[string]any{ + { + "_docID": "bae-d4303725-7db9-53d2-b324-f3ee44020e52", + "Name": "John", + "Age": int64(21), + }, + }, }, }, }, @@ -49,27 +51,29 @@ func TestQuerySimple(t *testing.T) { } func TestQuerySimpleWithAlias(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with alias, no filter", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 21 + }`, + }, + testUtils.Request{ + Request: `query { Users { username: Name age: Age } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 21 - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "username": "John", - "age": int64(21), + Results: map[string]any{ + "Users": []map[string]any{ + { + "username": "John", + "age": int64(21), + }, + }, }, }, }, @@ -79,35 +83,39 @@ func TestQuerySimpleWithAlias(t *testing.T) { } func TestQuerySimpleWithMultipleRows(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with no filter, multiple rows", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 21 + }`, + }, + testUtils.CreateDoc{ + Doc: `{ + "Name": "Bob", + "Age": 27 + }`, + }, + testUtils.Request{ + Request: `query { Users { Name Age } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 21 - }`, - `{ - "Name": "Bob", - "Age": 27 - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Bob", - "Age": int64(27), - }, - { - "Name": "John", - "Age": int64(21), + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Bob", + "Age": int64(27), + }, + { + "Name": "John", + "Age": int64(21), + }, + }, }, }, }, @@ -117,24 +125,35 @@ func TestQuerySimpleWithMultipleRows(t *testing.T) { } func TestQuerySimpleWithUndefinedField(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query for undefined field", - Request: `query { + Actions: []any{ + testUtils.Request{ + Request: `query { Users { Name ThisFieldDoesNotExists } }`, - ExpectedError: "Cannot query field \"ThisFieldDoesNotExists\" on type \"Users\".", + ExpectedError: "Cannot query field \"ThisFieldDoesNotExists\" on type \"Users\".", + }, + }, } executeTestCase(t, test) } func TestQuerySimpleWithSomeDefaultValues(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with some default-value fields", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John" + }`, + }, + testUtils.Request{ + Request: `query { Users { Name Email @@ -143,21 +162,16 @@ func TestQuerySimpleWithSomeDefaultValues(t *testing.T) { Verified } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John" - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Email": nil, - "Age": nil, - "HeightM": nil, - "Verified": nil, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "Email": nil, + "Age": nil, + "HeightM": nil, + "Verified": nil, + }, + }, }, }, }, @@ -167,9 +181,14 @@ func TestQuerySimpleWithSomeDefaultValues(t *testing.T) { } func TestQuerySimpleWithDefaultValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with default-value fields", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ }`, + }, + testUtils.Request{ + Request: `query { Users { Name Email @@ -178,19 +197,16 @@ func TestQuerySimpleWithDefaultValue(t *testing.T) { Verified } }`, - Docs: map[int][]string{ - 0: { - `{ }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": nil, - "Email": nil, - "Age": nil, - "HeightM": nil, - "Verified": nil, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": nil, + "Email": nil, + "Age": nil, + "HeightM": nil, + "Verified": nil, + }, + }, }, }, }, diff --git a/tests/integration/query/simple/utils.go b/tests/integration/query/simple/utils.go index 0343eca82c..0f2258e30e 100644 --- a/tests/integration/query/simple/utils.go +++ b/tests/integration/query/simple/utils.go @@ -27,6 +27,19 @@ var userCollectionGQLSchema = (` } `) -func executeTestCase(t *testing.T, test testUtils.RequestTestCase) { - testUtils.ExecuteRequestTestCase(t, userCollectionGQLSchema, []string{"Users"}, test) +func executeTestCase(t *testing.T, test testUtils.TestCase) { + testUtils.ExecuteTestCase( + t, + testUtils.TestCase{ + Description: test.Description, + Actions: append( + []any{ + testUtils.SchemaUpdate{ + Schema: userCollectionGQLSchema, + }, + }, + test.Actions..., + ), + }, + ) } diff --git a/tests/integration/query/simple/with_average_filter_test.go b/tests/integration/query/simple/with_average_filter_test.go index 48bf59ab89..0886d8f8f0 100644 --- a/tests/integration/query/simple/with_average_filter_test.go +++ b/tests/integration/query/simple/with_average_filter_test.go @@ -17,29 +17,35 @@ import ( ) func TestQuerySimpleWithAverageWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query, average with filter", - Request: `query { - _avg(Users: {field: Age, filter: {Age: {_gt: 26}}}) - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 30 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 32 }`, }, - }, - Results: map[string]any{ - "_avg": float64(31), + testUtils.Request{ + Request: `query { + _avg(Users: {field: Age, filter: {Age: {_gt: 26}}}) + }`, + Results: map[string]any{ + "_avg": float64(31), + }, + }, }, } @@ -47,32 +53,38 @@ func TestQuerySimpleWithAverageWithFilter(t *testing.T) { } func TestQuerySimpleWithAverageWithDateTimeFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query, average with datetime filter", - Request: `query { - _avg(Users: {field: Age, filter: {CreatedAt: {_gt: "2017-07-23T03:46:56-05:00"}}}) - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21, "CreatedAt": "2017-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 30, "CreatedAt": "2018-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 32, "CreatedAt": "2019-07-23T03:46:56-05:00" }`, }, - }, - Results: map[string]any{ - "_avg": float64(31), + testUtils.Request{ + Request: `query { + _avg(Users: {field: Age, filter: {CreatedAt: {_gt: "2017-07-23T03:46:56-05:00"}}}) + }`, + Results: map[string]any{ + "_avg": float64(31), + }, + }, }, } diff --git a/tests/integration/query/simple/with_average_test.go b/tests/integration/query/simple/with_average_test.go index 1237c21cb6..36aedd1ee8 100644 --- a/tests/integration/query/simple/with_average_test.go +++ b/tests/integration/query/simple/with_average_test.go @@ -17,37 +17,49 @@ import ( ) func TestQuerySimpleWithAverageOnUndefinedObject(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query, average on undefined object", - Request: `query { + Actions: []any{ + testUtils.Request{ + Request: `query { _avg }`, - ExpectedError: "aggregate must be provided with a property to aggregate", + ExpectedError: "aggregate must be provided with a property to aggregate", + }, + }, } executeTestCase(t, test) } func TestQuerySimpleWithAverageOnUndefinedField(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query, average on undefined field", - Request: `query { + Actions: []any{ + testUtils.Request{ + Request: `query { _avg(Users: {}) }`, - ExpectedError: "Argument \"Users\" has invalid value {}.\nIn field \"field\": Expected \"UsersNumericFieldsArg!\", found null.", + ExpectedError: "Argument \"Users\" has invalid value {}.\nIn field \"field\": Expected \"UsersNumericFieldsArg!\", found null.", + }, + }, } executeTestCase(t, test) } func TestQuerySimpleWithAverageOnEmptyCollection(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query, average on empty", - Request: `query { + Actions: []any{ + testUtils.Request{ + Request: `query { _avg(Users: {field: Age}) }`, - Results: map[string]any{ - "_avg": float64(0), + Results: map[string]any{ + "_avg": float64(0), + }, + }, }, } @@ -55,25 +67,29 @@ func TestQuerySimpleWithAverageOnEmptyCollection(t *testing.T) { } func TestQuerySimpleWithAverage(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query, average", - Request: `query { - _avg(Users: {field: Age}) - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 28 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 30 }`, }, - }, - Results: map[string]any{ - "_avg": float64(29), + testUtils.Request{ + Request: `query { + _avg(Users: {field: Age}) + }`, + Results: map[string]any{ + "_avg": float64(29), + }, + }, }, } diff --git a/tests/integration/query/simple/with_cid_test.go b/tests/integration/query/simple/with_cid_test.go index 044748a9b3..baa8b09402 100644 --- a/tests/integration/query/simple/with_cid_test.go +++ b/tests/integration/query/simple/with_cid_test.go @@ -17,22 +17,24 @@ import ( ) func TestQuerySimpleWithInvalidCid(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with cid", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 21 + }`, + }, + testUtils.Request{ + Request: `query { Users (cid: "any non-nil string value - this will be ignored") { Name } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 21 - }`, + ExpectedError: "invalid cid: selected encoding not supported", }, }, - ExpectedError: "invalid cid: selected encoding not supported", } executeTestCase(t, test) diff --git a/tests/integration/query/simple/with_count_filter_test.go b/tests/integration/query/simple/with_count_filter_test.go index 8bf9182bfe..d9055ab05e 100644 --- a/tests/integration/query/simple/with_count_filter_test.go +++ b/tests/integration/query/simple/with_count_filter_test.go @@ -17,29 +17,35 @@ import ( ) func TestQuerySimpleWithCountWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query, count with filter", - Request: `query { - _count(Users: {filter: {Age: {_gt: 26}}}) - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 30 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 32 }`, }, - }, - Results: map[string]any{ - "_count": 2, + testUtils.Request{ + Request: `query { + _count(Users: {filter: {Age: {_gt: 26}}}) + }`, + Results: map[string]any{ + "_count": 2, + }, + }, }, } @@ -47,32 +53,38 @@ func TestQuerySimpleWithCountWithFilter(t *testing.T) { } func TestQuerySimpleWithCountWithDateTimeFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query, count with datetime filter", - Request: `query { - _count(Users: {filter: {CreatedAt: {_gt: "2017-08-23T03:46:56-05:00"}}}) - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21, "CreatedAt": "2017-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 30, "CreatedAt": "2017-09-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 32, "CreatedAt": "2017-10-23T03:46:56-05:00" }`, }, - }, - Results: map[string]any{ - "_count": 2, + testUtils.Request{ + Request: `query { + _count(Users: {filter: {CreatedAt: {_gt: "2017-08-23T03:46:56-05:00"}}}) + }`, + Results: map[string]any{ + "_count": 2, + }, + }, }, } diff --git a/tests/integration/query/simple/with_count_test.go b/tests/integration/query/simple/with_count_test.go index 338d6847b6..20068e0672 100644 --- a/tests/integration/query/simple/with_count_test.go +++ b/tests/integration/query/simple/with_count_test.go @@ -17,25 +17,33 @@ import ( ) func TestQuerySimpleWithCountOnUndefined(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query, count on undefined", - Request: `query { + Actions: []any{ + testUtils.Request{ + Request: `query { _count }`, - ExpectedError: "aggregate must be provided with a property to aggregate", + ExpectedError: "aggregate must be provided with a property to aggregate", + }, + }, } executeTestCase(t, test) } func TestQuerySimpleWithCountOnEmptyCollection(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query, count on empty", - Request: `query { + Actions: []any{ + testUtils.Request{ + Request: `query { _count(Users: {}) }`, - Results: map[string]any{ - "_count": 0, + Results: map[string]any{ + "_count": 0, + }, + }, }, } @@ -43,25 +51,29 @@ func TestQuerySimpleWithCountOnEmptyCollection(t *testing.T) { } func TestQuerySimpleWithCount(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query, count", - Request: `query { - _count(Users: {}) - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 30 }`, }, - }, - Results: map[string]any{ - "_count": 2, + testUtils.Request{ + Request: `query { + _count(Users: {}) + }`, + Results: map[string]any{ + "_count": 2, + }, + }, }, } diff --git a/tests/integration/query/simple/with_doc_id_filter_test.go b/tests/integration/query/simple/with_doc_id_filter_test.go index 91bf2ef9cb..d54c9480df 100644 --- a/tests/integration/query/simple/with_doc_id_filter_test.go +++ b/tests/integration/query/simple/with_doc_id_filter_test.go @@ -17,31 +17,35 @@ import ( ) func TestQuerySimpleWithDocIDFilterBlock(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic filter (docID by filter block)", - Request: `query { - Users(filter: {_docID: {_eq: "bae-d4303725-7db9-53d2-b324-f3ee44020e52"}}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Age": int64(21), + testUtils.Request{ + Request: `query { + Users(filter: {_docID: {_eq: "bae-d4303725-7db9-53d2-b324-f3ee44020e52"}}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "Age": int64(21), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_doc_id_test.go b/tests/integration/query/simple/with_doc_id_test.go index 5f0b6fb316..a698da5ccf 100644 --- a/tests/integration/query/simple/with_doc_id_test.go +++ b/tests/integration/query/simple/with_doc_id_test.go @@ -17,77 +17,85 @@ import ( ) func TestQuerySimpleWithDocIDFilter(t *testing.T) { - tests := []testUtils.RequestTestCase{ + tests := []testUtils.TestCase{ { Description: "Simple query with basic filter (by docID arg)", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 21 + }`, + }, + testUtils.Request{ + Request: `query { Users(docID: "bae-d4303725-7db9-53d2-b324-f3ee44020e52") { Name Age } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 21 - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Age": int64(21), + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "Age": int64(21), + }, + }, }, }, }, }, { Description: "Simple query with basic filter (by docID arg), no results", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 21 + }`, + }, + testUtils.Request{ + Request: `query { Users(docID: "bae-52b9170d-b77a-5887-b877-cbdbb99b009g") { Name Age } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 21 - }`, + Results: map[string]any{ + "Users": []map[string]any{}, + }, }, }, - Results: map[string]any{ - "Users": []map[string]any{}, - }, }, { Description: "Simple query with basic filter (by docID arg), partial results", - Request: `query { - Users(docID: "bae-d4303725-7db9-53d2-b324-f3ee44020e52") { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Age": int64(21), + testUtils.Request{ + Request: `query { + Users(docID: "bae-d4303725-7db9-53d2-b324-f3ee44020e52") { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "Age": int64(21), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_doc_ids_test.go b/tests/integration/query/simple/with_doc_ids_test.go index 285a84f87e..4b2aa16ce0 100644 --- a/tests/integration/query/simple/with_doc_ids_test.go +++ b/tests/integration/query/simple/with_doc_ids_test.go @@ -17,114 +17,128 @@ import ( ) func TestQuerySimpleWithDocIDsFilter(t *testing.T) { - tests := []testUtils.RequestTestCase{ + tests := []testUtils.TestCase{ { Description: "Simple query with basic filter (single ID by docIDs arg)", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 21 + }`, + }, + testUtils.Request{ + Request: `query { Users(docIDs: ["bae-d4303725-7db9-53d2-b324-f3ee44020e52"]) { Name Age } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 21 - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Age": int64(21), + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "Age": int64(21), + }, + }, }, }, }, }, { Description: "Simple query with basic filter (single ID by docIDs arg), no results", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 21 + }`, + }, + testUtils.Request{ + Request: `query { Users(docIDs: ["bae-52b9170d-b77a-5887-b877-cbdbb99b009g"]) { Name Age } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 21 - }`, + Results: map[string]any{ + "Users": []map[string]any{}, + }, }, }, - Results: map[string]any{ - "Users": []map[string]any{}, - }, }, { Description: "Simple query with basic filter (duplicate ID by docIDs arg), partial results", - Request: `query { - Users(docIDs: ["bae-d4303725-7db9-53d2-b324-f3ee44020e52", "bae-d4303725-7db9-53d2-b324-f3ee44020e52"]) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Age": int64(21), + testUtils.Request{ + Request: `query { + Users(docIDs: ["bae-d4303725-7db9-53d2-b324-f3ee44020e52", "bae-d4303725-7db9-53d2-b324-f3ee44020e52"]) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "Age": int64(21), + }, + }, }, }, }, }, { Description: "Simple query with basic filter (multiple ID by docIDs arg), partial results", - Request: `query { - Users(docIDs: ["bae-d4303725-7db9-53d2-b324-f3ee44020e52", "bae-428c6d76-3491-520b-ad1f-a218f4dad787"]) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Jim", "Age": 27 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Jim", - "Age": int64(27), - }, - { - "Name": "John", - "Age": int64(21), + testUtils.Request{ + Request: `query { + Users(docIDs: ["bae-d4303725-7db9-53d2-b324-f3ee44020e52", "bae-428c6d76-3491-520b-ad1f-a218f4dad787"]) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Jim", + "Age": int64(27), + }, + { + "Name": "John", + "Age": int64(21), + }, + }, }, }, }, @@ -137,25 +151,27 @@ func TestQuerySimpleWithDocIDsFilter(t *testing.T) { } func TestQuerySimpleReturnsNothinGivenEmptyDocIDsFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with empty docIDs arg", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 21 + }`, + }, + testUtils.Request{ + Request: `query { Users(docIDs: []) { Name Age } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 21 - }`, + Results: map[string]any{ + "Users": []map[string]any{}, + }, }, }, - Results: map[string]any{ - "Users": []map[string]any{}, - }, } executeTestCase(t, test) diff --git a/tests/integration/query/simple/with_filter/utils.go b/tests/integration/query/simple/with_filter/utils.go index 28d84e61dd..4e4375096b 100644 --- a/tests/integration/query/simple/with_filter/utils.go +++ b/tests/integration/query/simple/with_filter/utils.go @@ -26,6 +26,19 @@ var userCollectionGQLSchema = (` } `) -func executeTestCase(t *testing.T, test testUtils.RequestTestCase) { - testUtils.ExecuteRequestTestCase(t, userCollectionGQLSchema, []string{"Users"}, test) +func executeTestCase(t *testing.T, test testUtils.TestCase) { + testUtils.ExecuteTestCase( + t, + testUtils.TestCase{ + Description: test.Description, + Actions: append( + []any{ + testUtils.SchemaUpdate{ + Schema: userCollectionGQLSchema, + }, + }, + test.Actions..., + ), + }, + ) } diff --git a/tests/integration/query/simple/with_filter/with_and_test.go b/tests/integration/query/simple/with_filter/with_and_test.go index 4bac7cf5af..81ccbeb35f 100644 --- a/tests/integration/query/simple/with_filter/with_and_test.go +++ b/tests/integration/query/simple/with_filter/with_and_test.go @@ -17,43 +17,51 @@ import ( ) func TestQuerySimpleWithIntGreaterThanAndIntLessThanFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with logical compound filter (and)", - Request: `query { - Users(filter: {_and: [{Age: {_gt: 20}}, {Age: {_lt: 50}}]}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Age": int64(21), - }, - { - "Name": "Bob", - "Age": int64(32), + testUtils.Request{ + Request: `query { + Users(filter: {_and: [{Age: {_gt: 20}}, {Age: {_lt: 50}}]}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "Age": int64(21), + }, + { + "Name": "Bob", + "Age": int64(32), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_eq_datetime_test.go b/tests/integration/query/simple/with_filter/with_eq_datetime_test.go index 0f72bd05ab..dbf6152244 100644 --- a/tests/integration/query/simple/with_filter/with_eq_datetime_test.go +++ b/tests/integration/query/simple/with_filter/with_eq_datetime_test.go @@ -17,35 +17,39 @@ import ( ) func TestQuerySimpleWithDateTimeEqualsFilterBlock(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic filter(age)", - Request: `query { - Users(filter: {CreatedAt: {_eq: "2017-07-23T03:46:56-05:00"}}) { - Name - Age - CreatedAt - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21, "CreatedAt": "2017-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32, "CreatedAt": "2016-07-23T03:46:56-05:00" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Age": int64(21), - "CreatedAt": testUtils.MustParseTime("2017-07-23T03:46:56-05:00"), + testUtils.Request{ + Request: `query { + Users(filter: {CreatedAt: {_eq: "2017-07-23T03:46:56-05:00"}}) { + Name + Age + CreatedAt + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "Age": int64(21), + "CreatedAt": testUtils.MustParseTime("2017-07-23T03:46:56-05:00"), + }, + }, }, }, }, @@ -55,39 +59,45 @@ func TestQuerySimpleWithDateTimeEqualsFilterBlock(t *testing.T) { } func TestQuerySimpleWithDateTimeEqualsNilFilterBlock(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic filter(age)", - Request: `query { - Users(filter: {CreatedAt: {_eq: null}}) { - Name - Age - CreatedAt - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21, "CreatedAt": "2017-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32, "CreatedAt": "2016-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Fred", "Age": 44 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Fred", - "Age": int64(44), - "CreatedAt": nil, + testUtils.Request{ + Request: `query { + Users(filter: {CreatedAt: {_eq: null}}) { + Name + Age + CreatedAt + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Fred", + "Age": int64(44), + "CreatedAt": nil, + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_eq_float_test.go b/tests/integration/query/simple/with_filter/with_eq_float_test.go index 340236f580..99f3de859f 100644 --- a/tests/integration/query/simple/with_filter/with_eq_float_test.go +++ b/tests/integration/query/simple/with_filter/with_eq_float_test.go @@ -17,31 +17,35 @@ import ( ) func TestQuerySimpleWithFloatEqualsFilterBlock(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic float filter", - Request: `query { - Users(filter: {HeightM: {_eq: 2.1}}) { - Name - HeightM - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.1 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "HeightM": float64(2.1), + testUtils.Request{ + Request: `query { + Users(filter: {HeightM: {_eq: 2.1}}) { + Name + HeightM + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "HeightM": float64(2.1), + }, + }, }, }, }, @@ -51,34 +55,40 @@ func TestQuerySimpleWithFloatEqualsFilterBlock(t *testing.T) { } func TestQuerySimpleWithFloatEqualsNilFilterBlock(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic float nil filter", - Request: `query { - Users(filter: {HeightM: {_eq: null}}) { - Name - HeightM - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.1 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "HeightM": 1.82 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Fred" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Fred", - "HeightM": nil, + testUtils.Request{ + Request: `query { + Users(filter: {HeightM: {_eq: null}}) { + Name + HeightM + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Fred", + "HeightM": nil, + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_eq_int_test.go b/tests/integration/query/simple/with_filter/with_eq_int_test.go index 576f2fa38e..4871f22e86 100644 --- a/tests/integration/query/simple/with_filter/with_eq_int_test.go +++ b/tests/integration/query/simple/with_filter/with_eq_int_test.go @@ -17,31 +17,35 @@ import ( ) func TestQuerySimpleWithIntEqualsFilterBlock(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic filter(age)", - Request: `query { - Users(filter: {Age: {_eq: 21}}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Age": int64(21), + testUtils.Request{ + Request: `query { + Users(filter: {Age: {_eq: 21}}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "Age": int64(21), + }, + }, }, }, }, @@ -51,34 +55,40 @@ func TestQuerySimpleWithIntEqualsFilterBlock(t *testing.T) { } func TestQuerySimpleWithIntEqualsNilFilterBlock(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic int nil filter", - Request: `query { - Users(filter: {Age: {_eq: null}}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Fred" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Fred", - "Age": nil, + testUtils.Request{ + Request: `query { + Users(filter: {Age: {_eq: null}}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Fred", + "Age": nil, + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_eq_string_test.go b/tests/integration/query/simple/with_filter/with_eq_string_test.go index bc9d249877..11deb874dc 100644 --- a/tests/integration/query/simple/with_filter/with_eq_string_test.go +++ b/tests/integration/query/simple/with_filter/with_eq_string_test.go @@ -17,31 +17,35 @@ import ( ) func TestQuerySimpleWithStringFilterBlock(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic filter (Name)", - Request: `query { - Users(filter: {Name: {_eq: "John"}}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Age": int64(21), + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_eq: "John"}}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "Age": int64(21), + }, + }, }, }, }, @@ -51,34 +55,40 @@ func TestQuerySimpleWithStringFilterBlock(t *testing.T) { } func TestQuerySimpleWithStringEqualsNilFilterBlock(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic string nil filter", - Request: `query { - Users(filter: {Name: {_eq: null}}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Age": 60 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": nil, - "Age": int64(60), + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_eq: null}}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": nil, + "Age": int64(60), + }, + }, }, }, }, @@ -88,80 +98,90 @@ func TestQuerySimpleWithStringEqualsNilFilterBlock(t *testing.T) { } func TestQuerySimpleWithStringFilterBlockAndSelect(t *testing.T) { - tests := []testUtils.RequestTestCase{ + tests := []testUtils.TestCase{ { Description: "Simple query with basic filter and selection", - Request: `query { - Users(filter: {Name: {_eq: "John"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_eq: "John"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + }, }, }, }, }, { Description: "Simple query with basic filter and selection (diff from filter)", - Request: `query { - Users(filter: {Name: {_eq: "John"}}) { - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(21), + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_eq: "John"}}) { + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Age": int64(21), + }, + }, }, }, }, }, { Description: "Simple query with basic filter(name), no results", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 21 + }`, + }, + testUtils.Request{ + Request: `query { Users(filter: {Name: {_eq: "Bob"}}) { Name Age } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 21 - }`, + Results: map[string]any{ + "Users": []map[string]any{}, + }, }, }, - Results: map[string]any{ - "Users": []map[string]any{}, - }, }, } diff --git a/tests/integration/query/simple/with_filter/with_ge_datetime_test.go b/tests/integration/query/simple/with_filter/with_ge_datetime_test.go index a21a120c44..5c2aacaa00 100644 --- a/tests/integration/query/simple/with_filter/with_ge_datetime_test.go +++ b/tests/integration/query/simple/with_filter/with_ge_datetime_test.go @@ -17,31 +17,35 @@ import ( ) func TestQuerySimpleWithDateTimeGEFilterBlockWithEqualValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic ge int filter with equal value", - Request: `query { - Users(filter: {CreatedAt: {_ge: "2017-07-23T03:46:56-05:00"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21, "CreatedAt": "2017-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32, "CreatedAt": "2010-07-23T03:46:56-05:00" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {CreatedAt: {_ge: "2017-07-23T03:46:56-05:00"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + }, }, }, }, @@ -51,31 +55,35 @@ func TestQuerySimpleWithDateTimeGEFilterBlockWithEqualValue(t *testing.T) { } func TestQuerySimpleWithDateTimeGEFilterBlockWithGreaterValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic ge int filter with equal value", - Request: `query { - Users(filter: {CreatedAt: {_ge: "2017-07-22T03:46:56-05:00"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21, "CreatedAt": "2017-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32, "CreatedAt": "2010-07-23T03:46:56-05:00" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {CreatedAt: {_ge: "2017-07-22T03:46:56-05:00"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + }, }, }, }, @@ -85,29 +93,33 @@ func TestQuerySimpleWithDateTimeGEFilterBlockWithGreaterValue(t *testing.T) { } func TestQuerySimpleWithDateTimeGEFilterBlockWithLesserValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic ge int filter with equal value", - Request: `query { - Users(filter: {CreatedAt: {_ge: "2017-07-25T03:46:56-05:00"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21, "CreatedAt": "2017-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32, "CreatedAt": "2010-07-23T03:46:56-05:00" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{}, + testUtils.Request{ + Request: `query { + Users(filter: {CreatedAt: {_ge: "2017-07-25T03:46:56-05:00"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{}, + }, + }, }, } @@ -115,31 +127,35 @@ func TestQuerySimpleWithDateTimeGEFilterBlockWithLesserValue(t *testing.T) { } func TestQuerySimpleWithDateTimeGEFilterBlockWithNilValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic ge nil filter", - Request: `query { - Users(filter: {CreatedAt: {_ge: null}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "CreatedAt": "2010-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Bob", - }, - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {CreatedAt: {_ge: null}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Bob", + }, + { + "Name": "John", + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_ge_float_test.go b/tests/integration/query/simple/with_filter/with_ge_float_test.go index be0a6d9c12..9ea5559972 100644 --- a/tests/integration/query/simple/with_filter/with_ge_float_test.go +++ b/tests/integration/query/simple/with_filter/with_ge_float_test.go @@ -17,29 +17,33 @@ import ( ) func TestQuerySimpleWithHeightMGEFilterBlockWithEqualValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic ge int filter with equal value", - Request: `query { - Users(filter: {HeightM: {_ge: 2.1}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.1 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {HeightM: {_ge: 2.1}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + }, }, }, }, @@ -49,29 +53,33 @@ func TestQuerySimpleWithHeightMGEFilterBlockWithEqualValue(t *testing.T) { } func TestQuerySimpleWithHeightMGEFilterBlockWithLesserValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic ge int filter with lesser value", - Request: `query { - Users(filter: {HeightM: {_ge: 2.0999999999999}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.1 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {HeightM: {_ge: 2.0999999999999}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + }, }, }, }, @@ -81,29 +89,33 @@ func TestQuerySimpleWithHeightMGEFilterBlockWithLesserValue(t *testing.T) { } func TestQuerySimpleWithHeightMGEFilterBlockWithLesserIntValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic ge int filter with lesser int value", - Request: `query { - Users(filter: {HeightM: {_ge: 2}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.1 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {HeightM: {_ge: 2}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + }, }, }, }, @@ -113,31 +125,35 @@ func TestQuerySimpleWithHeightMGEFilterBlockWithLesserIntValue(t *testing.T) { } func TestQuerySimpleWithHeightMGEFilterBlockWithNilValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic ge float nil filter", - Request: `query { - Users(filter: {HeightM: {_ge: null}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.1 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - }, - { - "Name": "Bob", + testUtils.Request{ + Request: `query { + Users(filter: {HeightM: {_ge: null}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + { + "Name": "Bob", + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_ge_int_test.go b/tests/integration/query/simple/with_filter/with_ge_int_test.go index 5a07a18b01..1c2b629960 100644 --- a/tests/integration/query/simple/with_filter/with_ge_int_test.go +++ b/tests/integration/query/simple/with_filter/with_ge_int_test.go @@ -17,29 +17,33 @@ import ( ) func TestQuerySimpleWithIntGEFilterBlockWithEqualValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic ge int filter with equal value", - Request: `query { - Users(filter: {Age: {_ge: 32}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Bob", + testUtils.Request{ + Request: `query { + Users(filter: {Age: {_ge: 32}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Bob", + }, + }, }, }, }, @@ -49,29 +53,33 @@ func TestQuerySimpleWithIntGEFilterBlockWithEqualValue(t *testing.T) { } func TestQuerySimpleWithIntGEFilterBlockWithGreaterValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic ge int filter with greater value", - Request: `query { - Users(filter: {Age: {_ge: 31}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Bob", + testUtils.Request{ + Request: `query { + Users(filter: {Age: {_ge: 31}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Bob", + }, + }, }, }, }, @@ -81,31 +89,35 @@ func TestQuerySimpleWithIntGEFilterBlockWithGreaterValue(t *testing.T) { } func TestQuerySimpleWithIntGEFilterBlockWithNilValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic ge nil filter", - Request: `query { - Users(filter: {Age: {_ge: null}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Bob", - }, - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {Age: {_ge: null}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Bob", + }, + { + "Name": "John", + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_gt_datetime_test.go b/tests/integration/query/simple/with_filter/with_gt_datetime_test.go index e12a74a36f..67ee8a05a0 100644 --- a/tests/integration/query/simple/with_filter/with_gt_datetime_test.go +++ b/tests/integration/query/simple/with_filter/with_gt_datetime_test.go @@ -17,31 +17,35 @@ import ( ) func TestQuerySimpleWithDateTimeGTFilterBlockWithEqualValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic gt datetime filter with equal value", - Request: `query { - Users(filter: {CreatedAt: {_gt: "2017-07-20T03:46:56-05:00"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21, "CreatedAt": "2017-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32, "CreatedAt": "2010-07-23T03:46:56-05:00" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {CreatedAt: {_gt: "2017-07-20T03:46:56-05:00"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + }, }, }, }, @@ -51,31 +55,35 @@ func TestQuerySimpleWithDateTimeGTFilterBlockWithEqualValue(t *testing.T) { } func TestQuerySimpleWithDateTimeGTFilterBlockWithGreaterValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic gt DateTime filter with equal value", - Request: `query { - Users(filter: {CreatedAt: {_gt: "2017-07-22T03:46:56-05:00"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21, "CreatedAt": "2017-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32, "CreatedAt": "2010-07-23T03:46:56-05:00" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {CreatedAt: {_gt: "2017-07-22T03:46:56-05:00"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + }, }, }, }, @@ -85,29 +93,33 @@ func TestQuerySimpleWithDateTimeGTFilterBlockWithGreaterValue(t *testing.T) { } func TestQuerySimpleWithDateTimeGTFilterBlockWithLesserValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic gt datetime filter with lesser value", - Request: `query { - Users(filter: {CreatedAt: {_gt: "2017-07-25T03:46:56-05:00"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21, "CreatedAt": "2017-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32, "CreatedAt": "2010-07-23T03:46:56-05:00" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{}, + testUtils.Request{ + Request: `query { + Users(filter: {CreatedAt: {_gt: "2017-07-25T03:46:56-05:00"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{}, + }, + }, }, } @@ -115,28 +127,32 @@ func TestQuerySimpleWithDateTimeGTFilterBlockWithLesserValue(t *testing.T) { } func TestQuerySimpleWithDateTimeGTFilterBlockWithNilValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic gt datetime nil filter", - Request: `query { - Users(filter: {CreatedAt: {_gt: null}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "CreatedAt": "2010-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {CreatedAt: {_gt: null}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_gt_float_test.go b/tests/integration/query/simple/with_filter/with_gt_float_test.go index da72d4df51..a362223488 100644 --- a/tests/integration/query/simple/with_filter/with_gt_float_test.go +++ b/tests/integration/query/simple/with_filter/with_gt_float_test.go @@ -17,83 +17,95 @@ import ( ) func TestQuerySimpleWithFloatGreaterThanFilterBlock(t *testing.T) { - tests := []testUtils.RequestTestCase{ + tests := []testUtils.TestCase{ { Description: "Simple query with basic float greater than filter", - Request: `query { - Users(filter: {HeightM: {_gt: 2.0999999999999}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.1 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {HeightM: {_gt: 2.0999999999999}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + }, }, }, }, }, { Description: "Simple query with basic float greater than filter, no results", - Request: `query { - Users(filter: {HeightM: {_gt: 40}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.1 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{}, + testUtils.Request{ + Request: `query { + Users(filter: {HeightM: {_gt: 40}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{}, + }, + }, }, }, { Description: "Simple query with basic float greater than filter, multiple results", - Request: `query { - Users(filter: {HeightM: {_gt: 1.8199999999999}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.1 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - }, - { - "Name": "Bob", + testUtils.Request{ + Request: `query { + Users(filter: {HeightM: {_gt: 1.8199999999999}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + { + "Name": "Bob", + }, + }, }, }, }, @@ -106,29 +118,33 @@ func TestQuerySimpleWithFloatGreaterThanFilterBlock(t *testing.T) { } func TestQuerySimpleWithFloatGreaterThanFilterBlockWithIntFilterValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic float greater than filter, with int filter value", - Request: `query { - Users(filter: {HeightM: {_gt: 2}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.1 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {HeightM: {_gt: 2}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + }, }, }, }, @@ -138,28 +154,32 @@ func TestQuerySimpleWithFloatGreaterThanFilterBlockWithIntFilterValue(t *testing } func TestQuerySimpleWithFloatGreaterThanFilterBlockWithNullFilterValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic float greater than filter, with null filter value", - Request: `query { - Users(filter: {HeightM: {_gt: null}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.1 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {HeightM: {_gt: null}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_gt_int_test.go b/tests/integration/query/simple/with_filter/with_gt_int_test.go index 3cbdf82250..3069131e97 100644 --- a/tests/integration/query/simple/with_filter/with_gt_int_test.go +++ b/tests/integration/query/simple/with_filter/with_gt_int_test.go @@ -17,89 +17,101 @@ import ( ) func TestQuerySimpleWithIntGreaterThanFilterBlock(t *testing.T) { - tests := []testUtils.RequestTestCase{ + tests := []testUtils.TestCase{ { Description: "Simple query with basic filter(age), greater than", - Request: `query { - Users(filter: {Age: {_gt: 20}}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Age": int64(21), + testUtils.Request{ + Request: `query { + Users(filter: {Age: {_gt: 20}}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "Age": int64(21), + }, + }, }, }, }, }, { Description: "Simple query with basic filter(age), no results", - Request: `query { - Users(filter: {Age: {_gt: 40}}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{}, - }, - }, - { - Description: "Simple query with basic filter(age), multiple results", - Request: `query { - Users(filter: {Age: {_gt: 20}}) { + testUtils.Request{ + Request: `query { + Users(filter: {Age: {_gt: 40}}) { Name Age } }`, - Docs: map[int][]string{ - 0: { - `{ + Results: map[string]any{ + "Users": []map[string]any{}, + }, + }, + }, + }, + { + Description: "Simple query with basic filter(age), multiple results", + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Age": int64(21), - }, - { - "Name": "Bob", - "Age": int64(32), + testUtils.Request{ + Request: `query { + Users(filter: {Age: {_gt: 20}}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "Age": int64(21), + }, + { + "Name": "Bob", + "Age": int64(32), + }, + }, }, }, }, @@ -112,28 +124,32 @@ func TestQuerySimpleWithIntGreaterThanFilterBlock(t *testing.T) { } func TestQuerySimpleWithIntGreaterThanFilterBlockWithNullFilterValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic int greater than filter, with null filter value", - Request: `query { - Users(filter: {Age: {_gt: null}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {Age: {_gt: null}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_in_test.go b/tests/integration/query/simple/with_filter/with_in_test.go index 887a4ccbdb..5afca0c170 100644 --- a/tests/integration/query/simple/with_filter/with_in_test.go +++ b/tests/integration/query/simple/with_filter/with_in_test.go @@ -17,43 +17,51 @@ import ( ) func TestQuerySimpleWithIntInFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with special filter (or)", - Request: `query { - Users(filter: {Age: {_in: [19, 40, 55]}}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Carlo", - "Age": int64(55), - }, - { - "Name": "Alice", - "Age": int64(19), + testUtils.Request{ + Request: `query { + Users(filter: {Age: {_in: [19, 40, 55]}}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Carlo", + "Age": int64(55), + }, + { + "Name": "Alice", + "Age": int64(19), + }, + }, }, }, }, @@ -63,40 +71,48 @@ func TestQuerySimpleWithIntInFilter(t *testing.T) { } func TestQuerySimpleWithIntInFilterOnFloat(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with _in filter on float", - Request: `query { - Users(filter: {HeightM: {_in: [21, 21.2]}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 21.0 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "HeightM": 21.1 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "HeightM": 21.2 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "HeightM": 21.3 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Carlo", - }, - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {HeightM: {_in: [21, 21.2]}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Carlo", + }, + { + "Name": "John", + }, + }, }, }, }, @@ -106,50 +122,60 @@ func TestQuerySimpleWithIntInFilterOnFloat(t *testing.T) { } func TestQuerySimpleWithIntInFilterWithNullValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with special filter (or)", - Request: `query { - Users(filter: {Age: {_in: [19, 40, 55, null]}}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Fred" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Fred", - "Age": nil, - }, - { - "Name": "Carlo", - "Age": int64(55), - }, - { - "Name": "Alice", - "Age": int64(19), + testUtils.Request{ + Request: `query { + Users(filter: {Age: {_in: [19, 40, 55, null]}}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Fred", + "Age": nil, + }, + { + "Name": "Carlo", + "Age": int64(55), + }, + { + "Name": "Alice", + "Age": int64(19), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_le_datetime_test.go b/tests/integration/query/simple/with_filter/with_le_datetime_test.go index 3e1dc9ff96..6ffbbbac69 100644 --- a/tests/integration/query/simple/with_filter/with_le_datetime_test.go +++ b/tests/integration/query/simple/with_filter/with_le_datetime_test.go @@ -17,31 +17,35 @@ import ( ) func TestQuerySimpleWithDateTimeLEFilterBlockWithEqualValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic le DateTime filter with equal value", - Request: `query { - Users(filter: {CreatedAt: {_le: "2017-07-23T03:46:56-05:00"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21, "CreatedAt": "2017-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32, "CreatedAt": "2019-07-23T03:46:56-05:00" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {CreatedAt: {_le: "2017-07-23T03:46:56-05:00"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + }, }, }, }, @@ -51,31 +55,35 @@ func TestQuerySimpleWithDateTimeLEFilterBlockWithEqualValue(t *testing.T) { } func TestQuerySimpleWithDateTimeLEFilterBlockWithGreaterValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic le DateTime filter with greater value", - Request: `query { - Users(filter: {CreatedAt: {_le: "2018-07-23T03:46:56-05:00"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21, "CreatedAt": "2017-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32, "CreatedAt": "2019-07-23T03:46:56-05:00" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {CreatedAt: {_le: "2018-07-23T03:46:56-05:00"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + }, }, }, }, @@ -85,30 +93,34 @@ func TestQuerySimpleWithDateTimeLEFilterBlockWithGreaterValue(t *testing.T) { } func TestQuerySimpleWithDateTimeLEFilterBlockWithNullValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic le DateTime filter with null value", - Request: `query { - Users(filter: {CreatedAt: {_le: null}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21, "CreatedAt": "2017-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Bob", + testUtils.Request{ + Request: `query { + Users(filter: {CreatedAt: {_le: null}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Bob", + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_le_float_test.go b/tests/integration/query/simple/with_filter/with_le_float_test.go index f5d2e7e3fc..ecd162b222 100644 --- a/tests/integration/query/simple/with_filter/with_le_float_test.go +++ b/tests/integration/query/simple/with_filter/with_le_float_test.go @@ -17,29 +17,33 @@ import ( ) func TestQuerySimpleWithFloatLEFilterBlockWithEqualValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic le float filter with equal value", - Request: `query { - Users(filter: {HeightM: {_le: 1.82}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.1 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Bob", + testUtils.Request{ + Request: `query { + Users(filter: {HeightM: {_le: 1.82}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Bob", + }, + }, }, }, }, @@ -49,29 +53,33 @@ func TestQuerySimpleWithFloatLEFilterBlockWithEqualValue(t *testing.T) { } func TestQuerySimpleWithFloatLEFilterBlockWithGreaterValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic le float filter with greater value", - Request: `query { - Users(filter: {HeightM: {_le: 1.820000000001}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.1 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Bob", + testUtils.Request{ + Request: `query { + Users(filter: {HeightM: {_le: 1.820000000001}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Bob", + }, + }, }, }, }, @@ -81,29 +89,33 @@ func TestQuerySimpleWithFloatLEFilterBlockWithGreaterValue(t *testing.T) { } func TestQuerySimpleWithFloatLEFilterBlockWithGreaterIntValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic le float filter with greater int value", - Request: `query { - Users(filter: {HeightM: {_le: 2}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.1 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Bob", + testUtils.Request{ + Request: `query { + Users(filter: {HeightM: {_le: 2}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Bob", + }, + }, }, }, }, @@ -113,28 +125,32 @@ func TestQuerySimpleWithFloatLEFilterBlockWithGreaterIntValue(t *testing.T) { } func TestQuerySimpleWithFloatLEFilterBlockWithNullValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic le float filter with null value", - Request: `query { - Users(filter: {HeightM: {_le: null}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.1 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Bob", + testUtils.Request{ + Request: `query { + Users(filter: {HeightM: {_le: null}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Bob", + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_le_int_test.go b/tests/integration/query/simple/with_filter/with_le_int_test.go index 1dd363c25e..12275bd90e 100644 --- a/tests/integration/query/simple/with_filter/with_le_int_test.go +++ b/tests/integration/query/simple/with_filter/with_le_int_test.go @@ -17,29 +17,33 @@ import ( ) func TestQuerySimpleWithIntLEFilterBlockWithEqualValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic le int filter with equal value", - Request: `query { - Users(filter: {Age: {_le: 21}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {Age: {_le: 21}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + }, }, }, }, @@ -49,29 +53,33 @@ func TestQuerySimpleWithIntLEFilterBlockWithEqualValue(t *testing.T) { } func TestQuerySimpleWithIntLEFilterBlockWithGreaterValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic le int filter with greater value", - Request: `query { - Users(filter: {Age: {_le: 22}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {Age: {_le: 22}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + }, }, }, }, @@ -81,28 +89,32 @@ func TestQuerySimpleWithIntLEFilterBlockWithGreaterValue(t *testing.T) { } func TestQuerySimpleWithIntLEFilterBlockWithNullValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic le int filter with null value", - Request: `query { - Users(filter: {Age: {_le: null}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Bob", + testUtils.Request{ + Request: `query { + Users(filter: {Age: {_le: null}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Bob", + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_like_string_test.go b/tests/integration/query/simple/with_filter/with_like_string_test.go index 9aa5ede34b..dce0c381f1 100644 --- a/tests/integration/query/simple/with_filter/with_like_string_test.go +++ b/tests/integration/query/simple/with_filter/with_like_string_test.go @@ -17,29 +17,33 @@ import ( ) func TestQuerySimpleWithLikeStringContainsFilterBlockContainsString(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic like-string filter contains string", - Request: `query { - Users(filter: {Name: {_like: "%Stormborn%"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_like: "%Stormborn%"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + }, + }, }, }, }, @@ -49,29 +53,33 @@ func TestQuerySimpleWithLikeStringContainsFilterBlockContainsString(t *testing.T } func TestQuerySimple_WithCaseInsensitiveLike_ShouldMatchString(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic case insensitive like-string filter contains string", - Request: `query { - Users(filter: {Name: {_ilike: "%stormborn%"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_ilike: "%stormborn%"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + }, + }, }, }, }, @@ -81,29 +89,33 @@ func TestQuerySimple_WithCaseInsensitiveLike_ShouldMatchString(t *testing.T) { } func TestQuerySimpleWithLikeStringContainsFilterBlockAsPrefixString(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic like-string filter with string as prefix", - Request: `query { - Users(filter: {Name: {_like: "Viserys%"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Viserys I Targaryen, King of the Andals", + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_like: "Viserys%"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Viserys I Targaryen, King of the Andals", + }, + }, }, }, }, @@ -113,29 +125,33 @@ func TestQuerySimpleWithLikeStringContainsFilterBlockAsPrefixString(t *testing.T } func TestQuerySimple_WithCaseInsensitiveLikeString_ShouldMatchPrefixString(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic case insensitive like-string filter with string as prefix", - Request: `query { - Users(filter: {Name: {_ilike: "viserys%"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Viserys I Targaryen, King of the Andals", + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_ilike: "viserys%"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Viserys I Targaryen, King of the Andals", + }, + }, }, }, }, @@ -145,29 +161,33 @@ func TestQuerySimple_WithCaseInsensitiveLikeString_ShouldMatchPrefixString(t *te } func TestQuerySimpleWithLikeStringContainsFilterBlockAsSuffixString(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic like-string filter with string as suffix", - Request: `query { - Users(filter: {Name: {_like: "%Andals"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Viserys I Targaryen, King of the Andals", + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_like: "%Andals"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Viserys I Targaryen, King of the Andals", + }, + }, }, }, }, @@ -177,29 +197,33 @@ func TestQuerySimpleWithLikeStringContainsFilterBlockAsSuffixString(t *testing.T } func TestQuerySimple_WithCaseInsensitiveLikeString_ShouldMatchSuffixString(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic case insensitive like-string filter with string as suffix", - Request: `query { - Users(filter: {Name: {_ilike: "%andals"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Viserys I Targaryen, King of the Andals", + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_ilike: "%andals"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Viserys I Targaryen, King of the Andals", + }, + }, }, }, }, @@ -209,29 +233,33 @@ func TestQuerySimple_WithCaseInsensitiveLikeString_ShouldMatchSuffixString(t *te } func TestQuerySimpleWithLikeStringContainsFilterBlockExactString(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic like-string filter with string as suffix", - Request: `query { - Users(filter: {Name: {_like: "Daenerys Stormborn of House Targaryen, the First of Her Name"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_like: "Daenerys Stormborn of House Targaryen, the First of Her Name"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + }, + }, }, }, }, @@ -241,29 +269,33 @@ func TestQuerySimpleWithLikeStringContainsFilterBlockExactString(t *testing.T) { } func TestQuerySimple_WithCaseInsensitiveLikeString_ShouldMatchExactString(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic like-string filter with string as suffix", - Request: `query { - Users(filter: {Name: {_ilike: "daenerys stormborn of house targaryen, the first of her name"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_ilike: "daenerys stormborn of house targaryen, the first of her name"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + }, + }, }, }, }, @@ -273,32 +305,36 @@ func TestQuerySimple_WithCaseInsensitiveLikeString_ShouldMatchExactString(t *tes } func TestQuerySimpleWithLikeStringContainsFilterBlockContainsStringMuplitpleResults(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic like-string filter with contains string multiple results", - Request: `query { - Users(filter: {Name: {_like: "%Targaryen%"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Viserys I Targaryen, King of the Andals", - }, - { - "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_like: "%Targaryen%"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Viserys I Targaryen, King of the Andals", + }, + { + "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + }, + }, }, }, }, @@ -308,29 +344,33 @@ func TestQuerySimpleWithLikeStringContainsFilterBlockContainsStringMuplitpleResu } func TestQuerySimpleWithLikeStringContainsFilterBlockHasStartAndEnd(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic like-string filter with string as start and end", - Request: `query { - Users(filter: {Name: {_like: "Daenerys%Name"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_like: "Daenerys%Name"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + }, + }, }, }, }, @@ -340,27 +380,31 @@ func TestQuerySimpleWithLikeStringContainsFilterBlockHasStartAndEnd(t *testing.T } func TestQuerySimpleWithLikeStringContainsFilterBlockHasBoth(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic like-string filter with none of the strings", - Request: `query { - Users(filter: {_and: [{Name: {_like: "%Baratheon%"}}, {Name: {_like: "%Stormborn%"}}]}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{}, + testUtils.Request{ + Request: `query { + Users(filter: {_and: [{Name: {_like: "%Baratheon%"}}, {Name: {_like: "%Stormborn%"}}]}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{}, + }, + }, }, } @@ -368,29 +412,33 @@ func TestQuerySimpleWithLikeStringContainsFilterBlockHasBoth(t *testing.T) { } func TestQuerySimpleWithLikeStringContainsFilterBlockHasEither(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic like-string filter with either strings", - Request: `query { - Users(filter: {_or: [{Name: {_like: "%Baratheon%"}}, {Name: {_like: "%Stormborn%"}}]}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + testUtils.Request{ + Request: `query { + Users(filter: {_or: [{Name: {_like: "%Baratheon%"}}, {Name: {_like: "%Stormborn%"}}]}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + }, + }, }, }, }, @@ -400,32 +448,38 @@ func TestQuerySimpleWithLikeStringContainsFilterBlockHasEither(t *testing.T) { } func TestQuerySimpleWithLikeStringContainsFilterBlockPropNotSet(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic like-string filter with either strings", - Request: `query { - Users(filter: {Name: {_like: "%King%"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "HeightM": 1.92 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Viserys I Targaryen, King of the Andals", + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_like: "%King%"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Viserys I Targaryen, King of the Andals", + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_lt_datetime_test.go b/tests/integration/query/simple/with_filter/with_lt_datetime_test.go index da6f60354e..a2230b3b20 100644 --- a/tests/integration/query/simple/with_filter/with_lt_datetime_test.go +++ b/tests/integration/query/simple/with_filter/with_lt_datetime_test.go @@ -17,31 +17,35 @@ import ( ) func TestQuerySimpleWithDateTimeLTFilterBlockWithGreaterValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic lt DateTime filter with equal value", - Request: `query { - Users(filter: {CreatedAt: {_lt: "2017-07-25T03:46:56-05:00"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21, "CreatedAt": "2017-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32, "CreatedAt": "2019-07-23T03:46:56-05:00" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {CreatedAt: {_lt: "2017-07-25T03:46:56-05:00"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + }, }, }, }, @@ -51,28 +55,32 @@ func TestQuerySimpleWithDateTimeLTFilterBlockWithGreaterValue(t *testing.T) { } func TestQuerySimpleWithDateTimeLTFilterBlockWithNullValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic lt DateTime filter with null value", - Request: `query { - Users(filter: {CreatedAt: {_lt: null}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21, "CreatedAt": "2017-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{}, + testUtils.Request{ + Request: `query { + Users(filter: {CreatedAt: {_lt: null}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{}, + }, + }, }, } diff --git a/tests/integration/query/simple/with_filter/with_lt_float_test.go b/tests/integration/query/simple/with_filter/with_lt_float_test.go index 84e3c6122a..3c255b7def 100644 --- a/tests/integration/query/simple/with_filter/with_lt_float_test.go +++ b/tests/integration/query/simple/with_filter/with_lt_float_test.go @@ -17,29 +17,33 @@ import ( ) func TestQuerySimpleWithFloatLessThanFilterBlockWithGreaterValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic lt float filter with greater value", - Request: `query { - Users(filter: {HeightM: {_lt: 1.820000000001}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.1 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Bob", + testUtils.Request{ + Request: `query { + Users(filter: {HeightM: {_lt: 1.820000000001}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Bob", + }, + }, }, }, }, @@ -49,29 +53,33 @@ func TestQuerySimpleWithFloatLessThanFilterBlockWithGreaterValue(t *testing.T) { } func TestQuerySimpleWithFloatLessThanFilterBlockWithGreaterIntValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic lt float filter with greater int value", - Request: `query { - Users(filter: {HeightM: {_lt: 2}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.1 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Bob", + testUtils.Request{ + Request: `query { + Users(filter: {HeightM: {_lt: 2}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Bob", + }, + }, }, }, }, @@ -81,27 +89,31 @@ func TestQuerySimpleWithFloatLessThanFilterBlockWithGreaterIntValue(t *testing.T } func TestQuerySimpleWithFloatLessThanFilterBlockWithNullValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic lt float filter with null value", - Request: `query { - Users(filter: {HeightM: {_lt: null}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.1 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{}, + testUtils.Request{ + Request: `query { + Users(filter: {HeightM: {_lt: null}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{}, + }, + }, }, } diff --git a/tests/integration/query/simple/with_filter/with_lt_int_test.go b/tests/integration/query/simple/with_filter/with_lt_int_test.go index 12bf972938..b5a0c85cb5 100644 --- a/tests/integration/query/simple/with_filter/with_lt_int_test.go +++ b/tests/integration/query/simple/with_filter/with_lt_int_test.go @@ -17,29 +17,33 @@ import ( ) func TestQuerySimpleWithIntLessThanFilterBlockWithGreaterValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic lt int filter with greater value", - Request: `query { - Users(filter: {Age: {_lt: 22}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {Age: {_lt: 22}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + }, }, }, }, @@ -49,26 +53,30 @@ func TestQuerySimpleWithIntLessThanFilterBlockWithGreaterValue(t *testing.T) { } func TestQuerySimpleWithIntLessThanFilterBlockWithNullValue(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic lt int filter with null value", - Request: `query { - Users(filter: {Age: {_lt: null}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{}, + testUtils.Request{ + Request: `query { + Users(filter: {Age: {_lt: null}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{}, + }, + }, }, } diff --git a/tests/integration/query/simple/with_filter/with_ne_bool_test.go b/tests/integration/query/simple/with_filter/with_ne_bool_test.go index 1f25203e89..d1acd27ad2 100644 --- a/tests/integration/query/simple/with_filter/with_ne_bool_test.go +++ b/tests/integration/query/simple/with_filter/with_ne_bool_test.go @@ -17,35 +17,41 @@ import ( ) func TestQuerySimpleWithBoolNotEqualsTrueFilterBlock(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with ne true filter", - Request: `query { - Users(filter: {Verified: {_ne: true}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Fred", "Verified": false }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Fred", - }, - { - "Name": "Bob", + testUtils.Request{ + Request: `query { + Users(filter: {Verified: {_ne: true}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Fred", + }, + { + "Name": "Bob", + }, + }, }, }, }, @@ -55,35 +61,41 @@ func TestQuerySimpleWithBoolNotEqualsTrueFilterBlock(t *testing.T) { } func TestQuerySimpleWithBoolNotEqualsNilFilterBlock(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with ne nil filter", - Request: `query { - Users(filter: {Verified: {_ne: null}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Fred", "Verified": false }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - }, - { - "Name": "Fred", + testUtils.Request{ + Request: `query { + Users(filter: {Verified: {_ne: null}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + { + "Name": "Fred", + }, + }, }, }, }, @@ -93,35 +105,41 @@ func TestQuerySimpleWithBoolNotEqualsNilFilterBlock(t *testing.T) { } func TestQuerySimpleWithBoolNotEqualsFalseFilterBlock(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with ne false filter", - Request: `query { - Users(filter: {Verified: {_ne: false}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Fred", "Verified": false }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - }, - { - "Name": "Bob", + testUtils.Request{ + Request: `query { + Users(filter: {Verified: {_ne: false}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + { + "Name": "Bob", + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_ne_datetime_test.go b/tests/integration/query/simple/with_filter/with_ne_datetime_test.go index f6423ed95c..5320a9c7eb 100644 --- a/tests/integration/query/simple/with_filter/with_ne_datetime_test.go +++ b/tests/integration/query/simple/with_filter/with_ne_datetime_test.go @@ -17,31 +17,35 @@ import ( ) func TestQuerySimpleWithDateTimeNotEqualsFilterBlock(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with ne DateTime filter", - Request: `query { - Users(filter: {CreatedAt: {_ne: "2017-07-23T03:46:56-05:00"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21, "CreatedAt": "2017-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32, "CreatedAt": "2011-07-23T03:46:56-05:00" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Bob", + testUtils.Request{ + Request: `query { + Users(filter: {CreatedAt: {_ne: "2017-07-23T03:46:56-05:00"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Bob", + }, + }, }, }, }, @@ -51,38 +55,44 @@ func TestQuerySimpleWithDateTimeNotEqualsFilterBlock(t *testing.T) { } func TestQuerySimpleWithDateTimeNotEqualsNilFilterBlock(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with ne DateTime nil filter", - Request: `query { - Users(filter: {CreatedAt: {_ne: null}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21, "CreatedAt": "2017-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32, "CreatedAt": "2011-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Fred", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Bob", - }, - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(filter: {CreatedAt: {_ne: null}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Bob", + }, + { + "Name": "John", + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_ne_float_test.go b/tests/integration/query/simple/with_filter/with_ne_float_test.go index 6e8e04175f..58b2985013 100644 --- a/tests/integration/query/simple/with_filter/with_ne_float_test.go +++ b/tests/integration/query/simple/with_filter/with_ne_float_test.go @@ -17,29 +17,33 @@ import ( ) func TestQuerySimpleWithFloatNotEqualsFilterBlock(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with ne float filter", - Request: `query { - Users(filter: {HeightM: {_ne: 2.1}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.1 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "HeightM": 3.2 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Bob", + testUtils.Request{ + Request: `query { + Users(filter: {HeightM: {_ne: 2.1}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Bob", + }, + }, }, }, }, @@ -49,35 +53,41 @@ func TestQuerySimpleWithFloatNotEqualsFilterBlock(t *testing.T) { } func TestQuerySimpleWithFloatNotEqualsNilFilterBlock(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with ne float nil filter", - Request: `query { - Users(filter: {HeightM: {_ne: null}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.1 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "HeightM": 3.2 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Fred" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - }, - { - "Name": "Bob", + testUtils.Request{ + Request: `query { + Users(filter: {HeightM: {_ne: null}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + { + "Name": "Bob", + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_ne_int_test.go b/tests/integration/query/simple/with_filter/with_ne_int_test.go index 543af47d31..173f7fb461 100644 --- a/tests/integration/query/simple/with_filter/with_ne_int_test.go +++ b/tests/integration/query/simple/with_filter/with_ne_int_test.go @@ -17,29 +17,33 @@ import ( ) func TestQuerySimpleWithIntNotEqualsFilterBlock(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with ne int filter", - Request: `query { - Users(filter: {Age: {_ne: 21}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Bob", + testUtils.Request{ + Request: `query { + Users(filter: {Age: {_ne: 21}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Bob", + }, + }, }, }, }, @@ -49,35 +53,41 @@ func TestQuerySimpleWithIntNotEqualsFilterBlock(t *testing.T) { } func TestQuerySimpleWithIntNotEqualsNilFilterBlock(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with ne int nil filter", - Request: `query { - Users(filter: {Age: {_ne: null}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Fred" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - }, - { - "Name": "Bob", + testUtils.Request{ + Request: `query { + Users(filter: {Age: {_ne: null}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + { + "Name": "Bob", + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_ne_string_test.go b/tests/integration/query/simple/with_filter/with_ne_string_test.go index 141e9b6d78..d72e60f927 100644 --- a/tests/integration/query/simple/with_filter/with_ne_string_test.go +++ b/tests/integration/query/simple/with_filter/with_ne_string_test.go @@ -17,29 +17,33 @@ import ( ) func TestQuerySimpleWithStringNotEqualsFilterBlock(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with ne string filter", - Request: `query { - Users(filter: {Name: {_ne: "John"}}) { - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_ne: "John"}}) { + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Age": int64(32), + }, + }, }, }, }, @@ -49,35 +53,41 @@ func TestQuerySimpleWithStringNotEqualsFilterBlock(t *testing.T) { } func TestQuerySimpleWithStringNotEqualsNilFilterBlock(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with ne string nil filter", - Request: `query { - Users(filter: {Name: {_ne: null}}) { - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Age": 36 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(21), - }, - { - "Age": int64(32), + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_ne: null}}) { + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Age": int64(21), + }, + { + "Age": int64(32), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_nin_test.go b/tests/integration/query/simple/with_filter/with_nin_test.go index bd0f1b7333..7f961bf537 100644 --- a/tests/integration/query/simple/with_filter/with_nin_test.go +++ b/tests/integration/query/simple/with_filter/with_nin_test.go @@ -17,43 +17,53 @@ import ( ) func TestQuerySimpleWithNotInFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with not-in filter", - Request: `query { - Users(filter: {Age: {_nin: [19, 40, 55, null]}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Fred" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - }, - { - "Name": "Bob", + testUtils.Request{ + Request: `query { + Users(filter: {Age: {_nin: [19, 40, 55, null]}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + }, + { + "Name": "Bob", + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_nlike_string_test.go b/tests/integration/query/simple/with_filter/with_nlike_string_test.go index 7c07b785ae..f6d3165d30 100644 --- a/tests/integration/query/simple/with_filter/with_nlike_string_test.go +++ b/tests/integration/query/simple/with_filter/with_nlike_string_test.go @@ -17,29 +17,33 @@ import ( ) func TestQuerySimpleWithNotLikeStringContainsFilterBlockContainsString(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic not like-string filter contains string", - Request: `query { - Users(filter: {Name: {_nlike: "%Stormborn%"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Viserys I Targaryen, King of the Andals", + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_nlike: "%Stormborn%"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Viserys I Targaryen, King of the Andals", + }, + }, }, }, }, @@ -49,29 +53,33 @@ func TestQuerySimpleWithNotLikeStringContainsFilterBlockContainsString(t *testin } func TestQuerySimple_WithNotCaseInsensitiveLikeString_ShouldMatchString(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic not case insensitive like-string filter contains string", - Request: `query { - Users(filter: {Name: {_nilike: "%stormborn%"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Viserys I Targaryen, King of the Andals", + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_nilike: "%stormborn%"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Viserys I Targaryen, King of the Andals", + }, + }, }, }, }, @@ -81,29 +89,33 @@ func TestQuerySimple_WithNotCaseInsensitiveLikeString_ShouldMatchString(t *testi } func TestQuerySimpleWithNotLikeStringContainsFilterBlockAsPrefixString(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic not like-string filter with string as prefix", - Request: `query { - Users(filter: {Name: {_nlike: "Viserys%"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_nlike: "Viserys%"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + }, + }, }, }, }, @@ -113,29 +125,33 @@ func TestQuerySimpleWithNotLikeStringContainsFilterBlockAsPrefixString(t *testin } func TestQuerySimple_WithNotCaseInsensitiveLikeString_ShouldMatchPrefixString(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic not case insensitive like-string filter with string as prefix", - Request: `query { - Users(filter: {Name: {_nilike: "viserys%"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_nilike: "viserys%"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + }, + }, }, }, }, @@ -145,29 +161,33 @@ func TestQuerySimple_WithNotCaseInsensitiveLikeString_ShouldMatchPrefixString(t } func TestQuerySimpleWithNotLikeStringContainsFilterBlockAsSuffixString(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic not like-string filter with string as suffix", - Request: `query { - Users(filter: {Name: {_nlike: "%Andals"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_nlike: "%Andals"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + }, + }, }, }, }, @@ -177,29 +197,33 @@ func TestQuerySimpleWithNotLikeStringContainsFilterBlockAsSuffixString(t *testin } func TestQuerySimple_WithNotCaseInsensitiveLikeString_ShouldMatchSuffixString(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic not like-string filter with string as suffix", - Request: `query { - Users(filter: {Name: {_nilike: "%andals"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_nilike: "%andals"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + }, + }, }, }, }, @@ -209,29 +233,33 @@ func TestQuerySimple_WithNotCaseInsensitiveLikeString_ShouldMatchSuffixString(t } func TestQuerySimpleWithNotLikeStringContainsFilterBlockExactString(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic not like-string filter with string as suffix", - Request: `query { - Users(filter: {Name: {_nlike: "Daenerys Stormborn of House Targaryen, the First of Her Name"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Viserys I Targaryen, King of the Andals", + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_nlike: "Daenerys Stormborn of House Targaryen, the First of Her Name"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Viserys I Targaryen, King of the Andals", + }, + }, }, }, }, @@ -241,29 +269,33 @@ func TestQuerySimpleWithNotLikeStringContainsFilterBlockExactString(t *testing.T } func TestQuerySimple_WithNotCaseInsensitiveLikeString_MatchExactString(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic not case insensitive like-string filter with string as suffix", - Request: `query { - Users(filter: {Name: {_nilike: "daenerys stormborn of house targaryen, the first of her name"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Viserys I Targaryen, King of the Andals", + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_nilike: "daenerys stormborn of house targaryen, the first of her name"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Viserys I Targaryen, King of the Andals", + }, + }, }, }, }, @@ -273,27 +305,31 @@ func TestQuerySimple_WithNotCaseInsensitiveLikeString_MatchExactString(t *testin } func TestQuerySimpleWithNotLikeStringContainsFilterBlockContainsStringMuplitpleResults(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic not like-string filter with contains string multiple results", - Request: `query { - Users(filter: {Name: {_nlike: "%Targaryen%"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{}, + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_nlike: "%Targaryen%"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{}, + }, + }, }, } @@ -301,29 +337,33 @@ func TestQuerySimpleWithNotLikeStringContainsFilterBlockContainsStringMuplitpleR } func TestQuerySimpleWithNotLikeStringContainsFilterBlockHasStartAndEnd(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic not like-string filter with string as start and end", - Request: `query { - Users(filter: {Name: {_nlike: "Daenerys%Name"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Viserys I Targaryen, King of the Andals", + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_nlike: "Daenerys%Name"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Viserys I Targaryen, King of the Andals", + }, + }, }, }, }, @@ -333,29 +373,33 @@ func TestQuerySimpleWithNotLikeStringContainsFilterBlockHasStartAndEnd(t *testin } func TestQuerySimpleWithNotLikeStringContainsFilterBlockHasBoth(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic not like-string filter with none of the strings", - Request: `query { - Users(filter: {_and: [{Name: {_nlike: "%Baratheon%"}}, {Name: {_nlike: "%Stormborn%"}}]}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Viserys I Targaryen, King of the Andals", + testUtils.Request{ + Request: `query { + Users(filter: {_and: [{Name: {_nlike: "%Baratheon%"}}, {Name: {_nlike: "%Stormborn%"}}]}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Viserys I Targaryen, King of the Andals", + }, + }, }, }, }, @@ -365,32 +409,36 @@ func TestQuerySimpleWithNotLikeStringContainsFilterBlockHasBoth(t *testing.T) { } func TestQuerySimpleWithNotLikeStringContainsFilterBlockHasEither(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic not like-string filter with either strings", - Request: `query { - Users(filter: {_or: [{Name: {_nlike: "%Baratheon%"}}, {Name: {_nlike: "%Stormborn%"}}]}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Viserys I Targaryen, King of the Andals", - }, - { - "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + testUtils.Request{ + Request: `query { + Users(filter: {_or: [{Name: {_nlike: "%Baratheon%"}}, {Name: {_nlike: "%Stormborn%"}}]}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Viserys I Targaryen, King of the Andals", + }, + { + "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + }, + }, }, }, }, @@ -400,35 +448,41 @@ func TestQuerySimpleWithNotLikeStringContainsFilterBlockHasEither(t *testing.T) } func TestQuerySimpleWithNotLikeStringContainsFilterBlockPropNotSet(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic not like-string filter with either strings", - Request: `query { - Users(filter: {Name: {_nlike: "%King%"}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", "HeightM": 1.65 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Viserys I Targaryen, King of the Andals", "HeightM": 1.82 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "HeightM": 1.92 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", - }, - { - "Name": nil, + testUtils.Request{ + Request: `query { + Users(filter: {Name: {_nlike: "%King%"}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Daenerys Stormborn of House Targaryen, the First of Her Name", + }, + { + "Name": nil, + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_not_test.go b/tests/integration/query/simple/with_filter/with_not_test.go index 6e9ffcc0da..15071e9c14 100644 --- a/tests/integration/query/simple/with_filter/with_not_test.go +++ b/tests/integration/query/simple/with_filter/with_not_test.go @@ -17,47 +17,55 @@ import ( ) func TestQuerySimple_WithNotEqualToXFilter_NoError(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with logical compound filter (not)", - Request: `query { - Users(filter: {_not: {Age: {_eq: 55}}}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Age": int64(21), - }, - { - "Name": "Bob", - "Age": int64(32), - }, - { - "Name": "Alice", - "Age": int64(19), + testUtils.Request{ + Request: `query { + Users(filter: {_not: {Age: {_eq: 55}}}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "Age": int64(21), + }, + { + "Name": "Bob", + "Age": int64(32), + }, + { + "Name": "Alice", + "Age": int64(19), + }, + }, }, }, }, @@ -67,39 +75,47 @@ func TestQuerySimple_WithNotEqualToXFilter_NoError(t *testing.T) { } func TestQuerySimple_WithNotAndComparisonXFilter_NoError(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with _not filter with _gt condition)", - Request: `query { - Users(filter: {_not: {Age: {_gt: 20}}}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Alice", - "Age": int64(19), + testUtils.Request{ + Request: `query { + Users(filter: {_not: {Age: {_gt: 20}}}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Alice", + "Age": int64(19), + }, + }, }, }, }, @@ -109,43 +125,51 @@ func TestQuerySimple_WithNotAndComparisonXFilter_NoError(t *testing.T) { } func TestQuerySimple_WithNotEqualToXorYFilter_NoError(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with logical compound filter (not)", - Request: `query { - Users(filter: {_not: {_or: [{Age: {_eq: 55}}, {Name: {_eq: "Alice"}}]}}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Age": int64(21), - }, - { - "Name": "Bob", - "Age": int64(32), + testUtils.Request{ + Request: `query { + Users(filter: {_not: {_or: [{Age: {_eq: 55}}, {Name: {_eq: "Alice"}}]}}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "Age": int64(21), + }, + { + "Name": "Bob", + "Age": int64(32), + }, + }, }, }, }, @@ -155,36 +179,44 @@ func TestQuerySimple_WithNotEqualToXorYFilter_NoError(t *testing.T) { } func TestQuerySimple_WithEmptyNotFilter_ReturnError(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with empty logical compound filter (not) returns empty result set", - Request: `query { - Users(filter: {_not: {}}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{}, + testUtils.Request{ + Request: `query { + Users(filter: {_not: {}}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{}, + }, + }, }, } @@ -192,55 +224,65 @@ func TestQuerySimple_WithEmptyNotFilter_ReturnError(t *testing.T) { } func TestQuerySimple_WithNotEqualToXAndNotYFilter_NoError(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with logical compound filter (not)", - Request: `query { - Users(filter: {_not: {Age: {_eq: 55}, _not: {Name: {_eq: "Carlo"}}}}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Frank", "Age": 55 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Age": int64(21), - }, - { - "Name": "Bob", - "Age": int64(32), - }, - { - "Name": "Carlo", - "Age": int64(55), - }, - { - "Name": "Alice", - "Age": int64(19), + testUtils.Request{ + Request: `query { + Users(filter: {_not: {Age: {_eq: 55}, _not: {Name: {_eq: "Carlo"}}}}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "Age": int64(21), + }, + { + "Name": "Bob", + "Age": int64(32), + }, + { + "Name": "Carlo", + "Age": int64(55), + }, + { + "Name": "Alice", + "Age": int64(19), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_filter/with_or_test.go b/tests/integration/query/simple/with_filter/with_or_test.go index 6a913730c2..fe63d7cc62 100644 --- a/tests/integration/query/simple/with_filter/with_or_test.go +++ b/tests/integration/query/simple/with_filter/with_or_test.go @@ -17,43 +17,51 @@ import ( ) func TestQuerySimpleWithIntEqualToXOrYFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with logical compound filter (or)", - Request: `query { - Users(filter: {_or: [{Age: {_eq: 55}}, {Age: {_eq: 19}}]}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Carlo", - "Age": int64(55), - }, - { - "Name": "Alice", - "Age": int64(19), + testUtils.Request{ + Request: `query { + Users(filter: {_or: [{Age: {_eq: 55}}, {Age: {_eq: 19}}]}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Carlo", + "Age": int64(55), + }, + { + "Name": "Alice", + "Age": int64(19), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_group_average_count_test.go b/tests/integration/query/simple/with_group_average_count_test.go index 837b12d11c..771259d115 100644 --- a/tests/integration/query/simple/with_group_average_count_test.go +++ b/tests/integration/query/simple/with_group_average_count_test.go @@ -21,43 +21,48 @@ import ( // verify that that code path is taken, but it does verfiy that the correct result // is returned to the consumer in case the more efficient code path is taken. func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildIntegerAverageAndCount(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, average and sum on non-rendered group integer value", - Request: `query { - Users(groupBy: [Name]) { - Name - _avg(_group: {field: Age}) - _count(_group: {}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 38 }`, - // It is important to test negative values here, due to the auto-typing of numbers - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": -19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_avg": float64(35), - "_count": int(2), - }, - { - "Name": "Alice", - "_avg": float64(-19), - "_count": int(1), + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _avg(_group: {field: Age}) + _count(_group: {}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "_avg": float64(35), + "_count": int(2), + }, + { + "Name": "Alice", + "_avg": float64(-19), + "_count": int(1), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_group_average_filter_test.go b/tests/integration/query/simple/with_group_average_filter_test.go index 6f17370301..d5c145c15f 100644 --- a/tests/integration/query/simple/with_group_average_filter_test.go +++ b/tests/integration/query/simple/with_group_average_filter_test.go @@ -17,39 +17,45 @@ import ( ) func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildAverageWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, no children, average on non-rendered, unfiltered group", - Request: `query { - Users(groupBy: [Name]) { - Name - _avg(_group: {field: Age, filter: {Age: {_gt: 26}}}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 34 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_avg": float64(33), - }, - { - "Name": "Alice", - "_avg": float64(0), + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _avg(_group: {field: Age, filter: {Age: {_gt: 26}}}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "_avg": float64(33), + }, + { + "Name": "Alice", + "_avg": float64(0), + }, + }, }, }, }, @@ -59,53 +65,59 @@ func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildAverageWithFilt } func TestQuerySimpleWithGroupByStringWithRenderedGroupAndChildAverageWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, no children, average on rendered, unfiltered group", - Request: `query { - Users(groupBy: [Name]) { - Name - _avg(_group: {field: Age, filter: {Age: {_gt: 26}}}) - _group { - Age - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 34 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_avg": float64(33), - "_group": []map[string]any{ - { - "Age": int64(34), - }, + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _avg(_group: {field: Age, filter: {Age: {_gt: 26}}}) + _group { + Age + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Age": int64(32), + "Name": "John", + "_avg": float64(33), + "_group": []map[string]any{ + { + "Age": int64(34), + }, + { + "Age": int64(32), + }, + }, }, - }, - }, - { - "Name": "Alice", - "_avg": float64(0), - "_group": []map[string]any{ { - "Age": int64(19), + "Name": "Alice", + "_avg": float64(0), + "_group": []map[string]any{ + { + "Age": int64(19), + }, + }, }, }, }, @@ -117,56 +129,62 @@ func TestQuerySimpleWithGroupByStringWithRenderedGroupAndChildAverageWithFilter( } func TestQuerySimpleWithGroupByStringWithRenderedGroupAndChildAverageWithDateTimeFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, no children, average on rendered, unfiltered group", - Request: `query { - Users(groupBy: [Name]) { - Name - _avg(_group: {field: Age, filter: {CreatedAt: {_gt: "2017-07-23T03:46:56-05:00"}}}) - _group { - Age - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 34, "CreatedAt": "2019-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32, "CreatedAt": "2018-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19, "CreatedAt": "2011-07-23T03:46:56-05:00" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_avg": float64(33), - "_group": []map[string]any{ - { - "Age": int64(32), - }, + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _avg(_group: {field: Age, filter: {CreatedAt: {_gt: "2017-07-23T03:46:56-05:00"}}}) + _group { + Age + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Age": int64(34), + "Name": "John", + "_avg": float64(33), + "_group": []map[string]any{ + { + "Age": int64(32), + }, + { + "Age": int64(34), + }, + }, }, - }, - }, - { - "Name": "Alice", - "_avg": float64(0), - "_group": []map[string]any{ { - "Age": int64(19), + "Name": "Alice", + "_avg": float64(0), + "_group": []map[string]any{ + { + "Age": int64(19), + }, + }, }, }, }, @@ -178,49 +196,55 @@ func TestQuerySimpleWithGroupByStringWithRenderedGroupAndChildAverageWithDateTim } func TestQuerySimpleWithGroupByStringWithRenderedGroupWithFilterAndChildAverageWithMatchingFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, no children, average on rendered, matching filtered group", - Request: `query { - Users(groupBy: [Name]) { - Name - _avg(_group: {field: Age, filter: {Age: {_gt: 33}}}) - _group(filter: {Age: {_gt: 33}}) { - Age - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 34 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_avg": float64(34), - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _avg(_group: {field: Age, filter: {Age: {_gt: 33}}}) + _group(filter: {Age: {_gt: 33}}) { + Age + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "_avg": float64(34), + "_group": []map[string]any{ + { + "Age": int64(34), + }, + }, + }, { - "Age": int64(34), + "Name": "Alice", + "_avg": float64(0), + "_group": []map[string]any{}, }, }, }, - { - "Name": "Alice", - "_avg": float64(0), - "_group": []map[string]any{}, - }, }, }, } @@ -229,52 +253,58 @@ func TestQuerySimpleWithGroupByStringWithRenderedGroupWithFilterAndChildAverageW } func TestQuerySimpleWithGroupByStringWithRenderedGroupWithFilterAndChildAverageWithMatchingDateTimeFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, no children, average on rendered, matching datetime filtered group", - Request: `query { - Users(groupBy: [Name]) { - Name - _avg(_group: {field: Age, filter: {CreatedAt: {_gt: "2016-07-23T03:46:56-05:00"}}}) - _group(filter: {CreatedAt: {_gt: "2016-07-23T03:46:56-05:00"}}) { - Age - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 34, "CreatedAt": "2017-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32, "CreatedAt": "2011-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19, "CreatedAt": "2010-07-23T03:46:56-05:00" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_avg": float64(34), - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _avg(_group: {field: Age, filter: {CreatedAt: {_gt: "2016-07-23T03:46:56-05:00"}}}) + _group(filter: {CreatedAt: {_gt: "2016-07-23T03:46:56-05:00"}}) { + Age + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Age": int64(34), + "Name": "John", + "_avg": float64(34), + "_group": []map[string]any{ + { + "Age": int64(34), + }, + }, + }, + { + "Name": "Alice", + "_avg": float64(0), + "_group": []map[string]any{}, }, }, }, - { - "Name": "Alice", - "_avg": float64(0), - "_group": []map[string]any{}, - }, }, }, } @@ -283,50 +313,56 @@ func TestQuerySimpleWithGroupByStringWithRenderedGroupWithFilterAndChildAverageW } func TestQuerySimpleWithGroupByStringWithRenderedGroupWithFilterAndChildAverageWithDifferentFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, no children, average on non-rendered, different filtered group", - Request: `query { - Users(groupBy: [Name]) { - Name - _avg(_group: {field: Age, filter: {Age: {_gt: 33}}}) - _group(filter: {Age: {_lt: 33}}) { - Age - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 34 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_avg": float64(34), - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _avg(_group: {field: Age, filter: {Age: {_gt: 33}}}) + _group(filter: {Age: {_lt: 33}}) { + Age + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Age": int64(32), + "Name": "John", + "_avg": float64(34), + "_group": []map[string]any{ + { + "Age": int64(32), + }, + }, }, - }, - }, - { - "Name": "Alice", - "_avg": float64(0), - "_group": []map[string]any{ { - "Age": int64(19), + "Name": "Alice", + "_avg": float64(0), + "_group": []map[string]any{ + { + "Age": int64(19), + }, + }, }, }, }, @@ -338,42 +374,48 @@ func TestQuerySimpleWithGroupByStringWithRenderedGroupWithFilterAndChildAverageW } func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildAveragesWithDifferentFilters(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, no children, average on non-rendered, unfiltered group", - Request: `query { - Users(groupBy: [Name]) { - Name - A1: _avg(_group: {field: Age, filter: {Age: {_gt: 26}}}) - A2: _avg(_group: {field: Age, filter: {Age: {_lt: 26}}}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 34 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "A1": float64(33), - "A2": float64(0), - }, - { - "Name": "Alice", - "A1": float64(0), - "A2": float64(19), + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + A1: _avg(_group: {field: Age, filter: {Age: {_gt: 26}}}) + A2: _avg(_group: {field: Age, filter: {Age: {_lt: 26}}}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "A1": float64(33), + "A2": float64(0), + }, + { + "Name": "Alice", + "A1": float64(0), + "A2": float64(19), + }, + }, }, }, }, @@ -384,46 +426,56 @@ func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildAveragesWithDif func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildAverageWithFilterAndNilItem(t *testing.T) { // This test checks that the appended/internal nil filter does not clash with the consumer-defined filter - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, no children, average with filter on non-rendered, unfiltered group", - Request: `query { - Users(groupBy: [Name]) { - Name - _avg(_group: {field: Age, filter: {Age: {_lt: 33}}}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 34 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 30 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_avg": float64(31), - }, - { - "Name": "Alice", - "_avg": float64(19), + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _avg(_group: {field: Age, filter: {Age: {_lt: 33}}}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "_avg": float64(31), + }, + { + "Name": "Alice", + "_avg": float64(19), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_group_average_limit_offset_test.go b/tests/integration/query/simple/with_group_average_limit_offset_test.go index 110dcc8bfd..0d7ba5d7e1 100644 --- a/tests/integration/query/simple/with_group_average_limit_offset_test.go +++ b/tests/integration/query/simple/with_group_average_limit_offset_test.go @@ -17,44 +17,51 @@ import ( ) func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildIntegerAverageWithLimitAndOffset(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, limited average on non-rendered group integer value", - Request: `query { - Users(groupBy: [Name]) { - Name - _avg(_group: {field: Age, offset: 1, limit: 2}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 38 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 28 }`, - // It is important to test negative values here, due to the auto-typing of numbers - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": -19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_avg": float64(35), - }, - { - "Name": "Alice", - "_avg": float64(0), + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _avg(_group: {field: Age, offset: 1, limit: 2}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "_avg": float64(35), + }, + { + "Name": "Alice", + "_avg": float64(0), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_group_average_limit_test.go b/tests/integration/query/simple/with_group_average_limit_test.go index ca5b1b0d81..415e2eee5b 100644 --- a/tests/integration/query/simple/with_group_average_limit_test.go +++ b/tests/integration/query/simple/with_group_average_limit_test.go @@ -17,44 +17,52 @@ import ( ) func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildIntegerAverageWithLimit(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, limited average on non-rendered group integer value", - Request: `query { - Users(groupBy: [Name]) { - Name - _avg(_group: {field: Age, limit: 2}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 38 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 28 }`, + }, + testUtils.CreateDoc{ // It is important to test negative values here, due to the auto-typing of numbers - `{ + Doc: `{ "Name": "Alice", "Age": -19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_avg": float64(33), - }, - { - "Name": "Alice", - "_avg": float64(-19), + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _avg(_group: {field: Age, limit: 2}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "_avg": float64(33), + }, + { + "Name": "Alice", + "_avg": float64(-19), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_group_average_sum_test.go b/tests/integration/query/simple/with_group_average_sum_test.go index 4e00607986..e16aab05e7 100644 --- a/tests/integration/query/simple/with_group_average_sum_test.go +++ b/tests/integration/query/simple/with_group_average_sum_test.go @@ -17,80 +17,90 @@ import ( ) func TestQuerySimpleWithGroupByStringWithInnerGroupBooleanAndSumOfCountOfInt(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, with child group by boolean, and sum of average on int", - Request: `query { - Users(groupBy: [Name]) { - Name - _sum(_group: {field: _avg}) - _group (groupBy: [Verified]){ - Verified - _avg(_group: {field: Age}) - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 25, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 34, "Verified": false }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19, "Verified": false }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_sum": float64(62.5), - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _sum(_group: {field: _avg}) + _group (groupBy: [Verified]){ + Verified + _avg(_group: {field: Age}) + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Verified": true, - "_avg": float64(28.5), + "Name": "John", + "_sum": float64(62.5), + "_group": []map[string]any{ + { + "Verified": true, + "_avg": float64(28.5), + }, + { + "Verified": false, + "_avg": float64(34), + }, + }, }, { - "Verified": false, - "_avg": float64(34), + "Name": "Carlo", + "_sum": float64(55), + "_group": []map[string]any{ + { + "Verified": true, + "_avg": float64(55), + }, + }, }, - }, - }, - { - "Name": "Carlo", - "_sum": float64(55), - "_group": []map[string]any{ { - "Verified": true, - "_avg": float64(55), - }, - }, - }, - { - "Name": "Alice", - "_sum": float64(19), - "_group": []map[string]any{ - { - "Verified": false, - "_avg": float64(19), + "Name": "Alice", + "_sum": float64(19), + "_group": []map[string]any{ + { + "Verified": false, + "_avg": float64(19), + }, + }, }, }, }, @@ -106,43 +116,49 @@ func TestQuerySimpleWithGroupByStringWithInnerGroupBooleanAndSumOfCountOfInt(t * // verify that that code path is taken, but it does verfiy that the correct result // is returned to the consumer in case the more efficient code path is taken. func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildIntegerAverageAndSum(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, average and sum on non-rendered group integer value", - Request: `query { - Users(groupBy: [Name]) { - Name - _avg(_group: {field: Age}) - _sum(_group: {field: Age}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 38 }`, + }, + testUtils.CreateDoc{ // It is important to test negative values here, due to the auto-typing of numbers - `{ + Doc: `{ "Name": "Alice", "Age": -19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_avg": float64(35), - "_sum": int64(70), - }, - { - "Name": "Alice", - "_avg": float64(-19), - "_sum": int64(-19), + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _avg(_group: {field: Age}) + _sum(_group: {field: Age}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "_avg": float64(35), + "_sum": int64(70), + }, + { + "Name": "Alice", + "_avg": float64(-19), + "_sum": int64(-19), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_group_average_test.go b/tests/integration/query/simple/with_group_average_test.go index 9afbef7a3e..a346ee61fa 100644 --- a/tests/integration/query/simple/with_group_average_test.go +++ b/tests/integration/query/simple/with_group_average_test.go @@ -17,39 +17,45 @@ import ( ) func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndAverageOfUndefined(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with average on unspecified field", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 32 + }`, + }, + testUtils.Request{ + Request: `query { Users (groupBy: [Name]) { Name _avg } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 32 - }`, + ExpectedError: "aggregate must be provided with a property to aggregate", }, }, - ExpectedError: "aggregate must be provided with a property to aggregate", } executeTestCase(t, test) } func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildIntegerAverageOnEmptyCollection(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, average on non-rendered group, empty collection", - Request: `query { + Actions: []any{ + testUtils.Request{ + Request: `query { Users(groupBy: [Age]) { Age _avg(_group: {field: Age}) } }`, - Results: map[string]any{ - "Users": []map[string]any{}, + Results: map[string]any{ + "Users": []map[string]any{}, + }, + }, }, } @@ -57,40 +63,46 @@ func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildIntegerAverageO } func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildIntegerAverage(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, average on non-rendered group integer value", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 32 + }`, + }, + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 38 + }`, + }, + testUtils.CreateDoc{ + // It is important to test negative values here, due to the auto-typing of numbers + Doc: `{ + "Name": "Alice", + "Age": -19 + }`, + }, + testUtils.Request{ + Request: `query { Users(groupBy: [Name]) { Name _avg(_group: {field: Age}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 32 - }`, - `{ - "Name": "John", - "Age": 38 - }`, - // It is important to test negative values here, due to the auto-typing of numbers - `{ - "Name": "Alice", - "Age": -19 - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_avg": float64(35), - }, - { - "Name": "Alice", - "_avg": float64(-19), + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "_avg": float64(35), + }, + { + "Name": "Alice", + "_avg": float64(-19), + }, + }, }, }, }, @@ -100,39 +112,45 @@ func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildIntegerAverage( } func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildNilAverage(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, average on non-rendered group nil and integer values", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 32 + }`, + }, + testUtils.CreateDoc{ + // Age is undefined here and must be ignored + Doc: `{ + "Name": "John" + }`, + }, + testUtils.CreateDoc{ + Doc: `{ + "Name": "Alice", + "Age": 19 + }`, + }, + testUtils.Request{ + Request: `query { Users(groupBy: [Name]) { Name _avg(_group: {field: Age}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 32 - }`, - // Age is undefined here and must be ignored - `{ - "Name": "John" - }`, - `{ - "Name": "Alice", - "Age": 19 - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_avg": float64(32), - }, - { - "Name": "Alice", - "_avg": float64(19), + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "_avg": float64(32), + }, + { + "Name": "Alice", + "_avg": float64(19), + }, + }, }, }, }, @@ -142,9 +160,46 @@ func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildNilAverage(t *t } func TestQuerySimpleWithGroupByStringWithInnerGroupBooleanAndAverageOfAverageOfInt(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, with child group by boolean, and average of average on int", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 25, + "Verified": true + }`, + }, + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 32, + "Verified": true + }`, + }, + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 34, + "Verified": false + }`, + }, + testUtils.CreateDoc{ + Doc: `{ + "Name": "Carlo", + "Age": 55, + "Verified": true + }`, + }, + testUtils.CreateDoc{ + Doc: `{ + "Name": "Alice", + "Age": 19, + "Verified": false + }`, + }, + testUtils.Request{ + Request: `query { Users(groupBy: [Name]) { Name _avg(_group: {field: _avg}) @@ -154,68 +209,41 @@ func TestQuerySimpleWithGroupByStringWithInnerGroupBooleanAndAverageOfAverageOfI } } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 25, - "Verified": true - }`, - `{ - "Name": "John", - "Age": 32, - "Verified": true - }`, - `{ - "Name": "John", - "Age": 34, - "Verified": false - }`, - `{ - "Name": "Carlo", - "Age": 55, - "Verified": true - }`, - `{ - "Name": "Alice", - "Age": 19, - "Verified": false - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_avg": float64(31.25), - "_group": []map[string]any{ - { - "Verified": true, - "_avg": float64(28.5), - }, + Results: map[string]any{ + "Users": []map[string]any{ { - "Verified": false, - "_avg": float64(34), + "Name": "John", + "_avg": float64(31.25), + "_group": []map[string]any{ + { + "Verified": true, + "_avg": float64(28.5), + }, + { + "Verified": false, + "_avg": float64(34), + }, + }, }, - }, - }, - { - "Name": "Carlo", - "_avg": float64(55), - "_group": []map[string]any{ { - "Verified": true, - "_avg": float64(55), + "Name": "Carlo", + "_avg": float64(55), + "_group": []map[string]any{ + { + "Verified": true, + "_avg": float64(55), + }, + }, }, - }, - }, - { - "Name": "Alice", - "_avg": float64(19), - "_group": []map[string]any{ { - "Verified": false, - "_avg": float64(19), + "Name": "Alice", + "_avg": float64(19), + "_group": []map[string]any{ + { + "Verified": false, + "_avg": float64(19), + }, + }, }, }, }, @@ -227,38 +255,44 @@ func TestQuerySimpleWithGroupByStringWithInnerGroupBooleanAndAverageOfAverageOfI } func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildEmptyFloatAverage(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, average on non-rendered group float (default) value", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "HeightM": 1.82 + }`, + }, + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "HeightM": 1.89 + }`, + }, + testUtils.CreateDoc{ + Doc: `{ + "Name": "Alice" + }`, + }, + testUtils.Request{ + Request: `query { Users(groupBy: [Name]) { Name _avg(_group: {field: HeightM}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "HeightM": 1.82 - }`, - `{ - "Name": "John", - "HeightM": 1.89 - }`, - `{ - "Name": "Alice" - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_avg": float64(1.855), - }, - { - "Name": "Alice", - "_avg": float64(0), + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "_avg": float64(1.855), + }, + { + "Name": "Alice", + "_avg": float64(0), + }, + }, }, }, }, @@ -268,39 +302,45 @@ func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildEmptyFloatAvera } func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildFloatAverage(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, average on non-rendered group float value", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "HeightM": 1.82 + }`, + }, + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "HeightM": 1.89 + }`, + }, + testUtils.CreateDoc{ + Doc: `{ + "Name": "Alice", + "HeightM": 2.04 + }`, + }, + testUtils.Request{ + Request: `query { Users(groupBy: [Name]) { Name _avg(_group: {field: HeightM}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "HeightM": 1.82 - }`, - `{ - "Name": "John", - "HeightM": 1.89 - }`, - `{ - "Name": "Alice", - "HeightM": 2.04 - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_avg": float64(1.855), - }, - { - "Name": "Alice", - "_avg": float64(2.04), + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "_avg": float64(1.855), + }, + { + "Name": "Alice", + "_avg": float64(2.04), + }, + }, }, }, }, @@ -310,9 +350,46 @@ func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildFloatAverage(t } func TestQuerySimpleWithGroupByStringWithInnerGroupBooleanAndAverageOfAverageOfFloat(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, with child group by boolean, and average of average on float", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "HeightM": 1.82, + "Verified": true + }`, + }, + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "HeightM": 1.61, + "Verified": true + }`, + }, + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "HeightM": 2.22, + "Verified": false + }`, + }, + testUtils.CreateDoc{ + Doc: `{ + "Name": "Carlo", + "HeightM": 1.74, + "Verified": true + }`, + }, + testUtils.CreateDoc{ + Doc: `{ + "Name": "Alice", + "HeightM": 2.04, + "Verified": false + }`, + }, + testUtils.Request{ + Request: `query { Users(groupBy: [Name]) { Name _avg(_group: {field: _avg}) @@ -322,68 +399,41 @@ func TestQuerySimpleWithGroupByStringWithInnerGroupBooleanAndAverageOfAverageOfF } } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "HeightM": 1.82, - "Verified": true - }`, - `{ - "Name": "John", - "HeightM": 1.61, - "Verified": true - }`, - `{ - "Name": "John", - "HeightM": 2.22, - "Verified": false - }`, - `{ - "Name": "Carlo", - "HeightM": 1.74, - "Verified": true - }`, - `{ - "Name": "Alice", - "HeightM": 2.04, - "Verified": false - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Alice", - "_avg": float64(2.04), - "_group": []map[string]any{ - { - "Verified": false, - "_avg": float64(2.04), - }, - }, - }, - { - "Name": "John", - "_avg": float64(1.9675000000000002), - "_group": []map[string]any{ + Results: map[string]any{ + "Users": []map[string]any{ { - "Verified": true, - "_avg": float64(1.715), + "Name": "Alice", + "_avg": float64(2.04), + "_group": []map[string]any{ + { + "Verified": false, + "_avg": float64(2.04), + }, + }, }, { - "Verified": false, - "_avg": float64(2.22), + "Name": "John", + "_avg": float64(1.9675000000000002), + "_group": []map[string]any{ + { + "Verified": true, + "_avg": float64(1.715), + }, + { + "Verified": false, + "_avg": float64(2.22), + }, + }, }, - }, - }, - { - "Name": "Carlo", - "_avg": float64(1.74), - "_group": []map[string]any{ { - "Verified": true, - "_avg": float64(1.74), + "Name": "Carlo", + "_avg": float64(1.74), + "_group": []map[string]any{ + { + "Verified": true, + "_avg": float64(1.74), + }, + }, }, }, }, @@ -395,115 +445,125 @@ func TestQuerySimpleWithGroupByStringWithInnerGroupBooleanAndAverageOfAverageOfF } func TestQuerySimpleWithGroupByStringWithInnerGroupBooleanAndAverageOfAverageOfAverageOfFloat(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, with child group by boolean, and average of average of average of float", - Request: `query { - Users(groupBy: [Name]) { - Name - _avg(_group: {field: _avg}) - _group (groupBy: [Verified]){ - Verified - _avg(_group: {field: HeightM}) - _group (groupBy: [Age]){ - Age - _avg(_group: {field: HeightM}) - } - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 1.82, "Age": 25, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 1.61, "Age": 32, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.22, "Age": 34, "Verified": false }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "HeightM": 1.74, "Age": 55, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "HeightM": 2.04, "Age": 19, "Verified": false }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Carlo", - "_avg": float64(1.74), - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _avg(_group: {field: _avg}) + _group (groupBy: [Verified]){ + Verified + _avg(_group: {field: HeightM}) + _group (groupBy: [Age]){ + Age + _avg(_group: {field: HeightM}) + } + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Verified": true, - "_avg": float64(1.74), + "Name": "Carlo", + "_avg": float64(1.74), "_group": []map[string]any{ { - "Age": int64(55), - "_avg": float64(1.74), + "Verified": true, + "_avg": float64(1.74), + "_group": []map[string]any{ + { + "Age": int64(55), + "_avg": float64(1.74), + }, + }, }, }, }, - }, - }, - { - "Name": "Alice", - "_avg": float64(2.04), - "_group": []map[string]any{ { - "Verified": false, - "_avg": float64(2.04), + "Name": "Alice", + "_avg": float64(2.04), "_group": []map[string]any{ { - "Age": int64(19), - "_avg": float64(2.04), + "Verified": false, + "_avg": float64(2.04), + "_group": []map[string]any{ + { + "Age": int64(19), + "_avg": float64(2.04), + }, + }, }, }, }, - }, - }, - { - "Name": "John", - "_avg": float64(1.9675000000000002), - "_group": []map[string]any{ { - "Verified": true, - "_avg": float64(1.715), + "Name": "John", + "_avg": float64(1.9675000000000002), "_group": []map[string]any{ { - "Age": int64(32), - "_avg": float64(1.61), - }, - { - "Age": int64(25), - "_avg": float64(1.82), + "Verified": true, + "_avg": float64(1.715), + "_group": []map[string]any{ + { + "Age": int64(32), + "_avg": float64(1.61), + }, + { + "Age": int64(25), + "_avg": float64(1.82), + }, + }, }, - }, - }, - { - "Verified": false, - "_avg": float64(2.22), - "_group": []map[string]any{ { - "Age": int64(34), - "_avg": float64(2.22), + "Verified": false, + "_avg": float64(2.22), + "_group": []map[string]any{ + { + "Age": int64(34), + "_avg": float64(2.22), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_group_count_filter_test.go b/tests/integration/query/simple/with_group_count_filter_test.go index 9d2950b4e5..4544755898 100644 --- a/tests/integration/query/simple/with_group_count_filter_test.go +++ b/tests/integration/query/simple/with_group_count_filter_test.go @@ -17,39 +17,45 @@ import ( ) func TestQuerySimpleWithGroupByNumberWithoutRenderedGroupAndChildCountWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, count on non-rendered, unfiltered group", - Request: `query { - Users(groupBy: [Age]) { - Age - _count(_group: {filter: {Age: {_gt: 26}}}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "_count": 2, - }, - { - "Age": int64(19), - "_count": 0, + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + _count(_group: {filter: {Age: {_gt: 26}}}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Age": int64(32), + "_count": 2, + }, + { + "Age": int64(19), + "_count": 0, + }, + }, }, }, }, @@ -59,53 +65,59 @@ func TestQuerySimpleWithGroupByNumberWithoutRenderedGroupAndChildCountWithFilter } func TestQuerySimpleWithGroupByNumberWithRenderedGroupAndChildCountWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, count on non-rendered, filtered group", - Request: `query { - Users(groupBy: [Age]) { - Age - _count(_group: {filter: {Age: {_gt: 26}}}) - _group { - Name - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "_count": 2, - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + _count(_group: {filter: {Age: {_gt: 26}}}) + _group { + Name + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Name": "Bob", + "Age": int64(32), + "_count": 2, + "_group": []map[string]any{ + { + "Name": "Bob", + }, + { + "Name": "John", + }, + }, }, { - "Name": "John", - }, - }, - }, - { - "Age": int64(19), - "_count": 0, - "_group": []map[string]any{ - { - "Name": "Alice", + "Age": int64(19), + "_count": 0, + "_group": []map[string]any{ + { + "Name": "Alice", + }, + }, }, }, }, @@ -117,49 +129,55 @@ func TestQuerySimpleWithGroupByNumberWithRenderedGroupAndChildCountWithFilter(t } func TestQuerySimpleWithGroupByNumberWithRenderedGroupWithFilterAndChildCountWithMatchingFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, count on non-rendered, matching filtered group", - Request: `query { - Users(groupBy: [Age]) { - Age - _count(_group: {filter: {Name: {_eq: "John"}}}) - _group(filter: {Name: {_eq: "John"}}) { - Name - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "_count": 1, - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + _count(_group: {filter: {Name: {_eq: "John"}}}) + _group(filter: {Name: {_eq: "John"}}) { + Name + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Name": "John", + "Age": int64(32), + "_count": 1, + "_group": []map[string]any{ + { + "Name": "John", + }, + }, + }, + { + "Age": int64(19), + "_count": 0, + "_group": []map[string]any{}, }, }, }, - { - "Age": int64(19), - "_count": 0, - "_group": []map[string]any{}, - }, }, }, } @@ -168,49 +186,55 @@ func TestQuerySimpleWithGroupByNumberWithRenderedGroupWithFilterAndChildCountWit } func TestQuerySimpleWithGroupByNumberWithRenderedGroupWithFilterAndChildCountWithDifferentFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, count on non-rendered, different group filter", - Request: `query { - Users(groupBy: [Age]) { - Age - _count(_group: {filter: {Age: {_gt: 26}}}) - _group(filter: {Name: {_eq: "John"}}) { - Name - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "_count": 2, - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + _count(_group: {filter: {Age: {_gt: 26}}}) + _group(filter: {Name: {_eq: "John"}}) { + Name + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Age": int64(32), + "_count": 2, + "_group": []map[string]any{ + { + "Name": "John", + }, + }, + }, { - "Name": "John", + "Age": int64(19), + "_count": 0, + "_group": []map[string]any{}, }, }, }, - { - "Age": int64(19), - "_count": 0, - "_group": []map[string]any{}, - }, }, }, } @@ -219,42 +243,48 @@ func TestQuerySimpleWithGroupByNumberWithRenderedGroupWithFilterAndChildCountWit } func TestQuerySimpleWithGroupByNumberWithoutRenderedGroupAndChildCountsWithDifferentFilters(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, multiple counts on non-rendered, unfiltered group", - Request: `query { - Users(groupBy: [Age]) { - Age - C1: _count(_group: {filter: {Age: {_gt: 26}}}) - C2: _count(_group: {filter: {Age: {_lt: 26}}}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "C1": 2, - "C2": 0, - }, - { - "Age": int64(19), - "C1": 0, - "C2": 1, + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + C1: _count(_group: {filter: {Age: {_gt: 26}}}) + C2: _count(_group: {filter: {Age: {_lt: 26}}}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Age": int64(32), + "C1": 2, + "C2": 0, + }, + { + "Age": int64(19), + "C1": 0, + "C2": 1, + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_group_count_limit_offset_test.go b/tests/integration/query/simple/with_group_count_limit_offset_test.go index 4fe00f25b9..365cabc886 100644 --- a/tests/integration/query/simple/with_group_count_limit_offset_test.go +++ b/tests/integration/query/simple/with_group_count_limit_offset_test.go @@ -17,39 +17,45 @@ import ( ) func TestQuerySimpleWithGroupByNumberWithoutRenderedGroupAndChildCountWithLimitAndOffset(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, count with limit and offset on non-rendered group", - Request: `query { - Users(groupBy: [Age]) { - Age - _count(_group: {offset: 1, limit: 1}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "_count": 1, - }, - { - "Age": int64(19), - "_count": 0, + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + _count(_group: {offset: 1, limit: 1}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Age": int64(32), + "_count": 1, + }, + { + "Age": int64(19), + "_count": 0, + }, + }, }, }, }, @@ -59,57 +65,65 @@ func TestQuerySimpleWithGroupByNumberWithoutRenderedGroupAndChildCountWithLimitA } func TestQuerySimpleWithGroupByNumberWithRenderedGroupWithLimitAndChildCountWithLimitAndOffset(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, child limit, count with limit and offset on rendered group", - Request: `query { - Users(groupBy: [Age]) { - Age - _count(_group: {offset: 1, limit: 1}) - _group (limit: 2) { - Name - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Shahzad", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "_count": 1, - "_group": []map[string]any{ - { - "Name": "Bob", - }, + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + _count(_group: {offset: 1, limit: 1}) + _group (limit: 2) { + Name + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Name": "Shahzad", + "Age": int64(32), + "_count": 1, + "_group": []map[string]any{ + { + "Name": "Bob", + }, + { + "Name": "Shahzad", + }, + }, }, - }, - }, - { - "Age": int64(19), - "_count": 0, - "_group": []map[string]any{ { - "Name": "Alice", + "Age": int64(19), + "_count": 0, + "_group": []map[string]any{ + { + "Name": "Alice", + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_group_count_limit_test.go b/tests/integration/query/simple/with_group_count_limit_test.go index 7deae49208..d31639c6fc 100644 --- a/tests/integration/query/simple/with_group_count_limit_test.go +++ b/tests/integration/query/simple/with_group_count_limit_test.go @@ -17,39 +17,45 @@ import ( ) func TestQuerySimpleWithGroupByNumberWithoutRenderedGroupAndChildCountWithLimit(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, count with limit on non-rendered group", - Request: `query { - Users(groupBy: [Age]) { - Age - _count(_group: {limit: 1}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "_count": 1, - }, - { - "Age": int64(19), - "_count": 1, + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + _count(_group: {limit: 1}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Age": int64(32), + "_count": 1, + }, + { + "Age": int64(19), + "_count": 1, + }, + }, }, }, }, @@ -59,57 +65,65 @@ func TestQuerySimpleWithGroupByNumberWithoutRenderedGroupAndChildCountWithLimit( } func TestQuerySimpleWithGroupByNumberWithRenderedGroupWithLimitAndChildCountWithLimit(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, child limit, count with limit on rendered group", - Request: `query { - Users(groupBy: [Age]) { - Age - _count(_group: {limit: 1}) - _group (limit: 2) { - Name - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Shahzad", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "_count": 1, - "_group": []map[string]any{ - { - "Name": "Bob", - }, + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + _count(_group: {limit: 1}) + _group (limit: 2) { + Name + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Name": "Shahzad", + "Age": int64(32), + "_count": 1, + "_group": []map[string]any{ + { + "Name": "Bob", + }, + { + "Name": "Shahzad", + }, + }, }, - }, - }, - { - "Age": int64(19), - "_count": 1, - "_group": []map[string]any{ { - "Name": "Alice", + "Age": int64(19), + "_count": 1, + "_group": []map[string]any{ + { + "Name": "Alice", + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_group_count_sum_test.go b/tests/integration/query/simple/with_group_count_sum_test.go index 7e26628591..9fe06c9c79 100644 --- a/tests/integration/query/simple/with_group_count_sum_test.go +++ b/tests/integration/query/simple/with_group_count_sum_test.go @@ -17,80 +17,90 @@ import ( ) func TestQuerySimpleWithGroupByStringWithInnerGroupBooleanAndSumOfCount(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, with child group by boolean, and sum of count", - Request: `query { - Users(groupBy: [Name]) { - Name - _sum(_group: {field: _count}) - _group (groupBy: [Verified]){ - Verified - _count(_group: {}) - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 25, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 34, "Verified": false }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19, "Verified": false }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_sum": int64(3), - "_group": []map[string]any{ - { - "Verified": true, - "_count": int(2), - }, + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _sum(_group: {field: _count}) + _group (groupBy: [Verified]){ + Verified + _count(_group: {}) + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Verified": false, - "_count": int(1), + "Name": "John", + "_sum": int64(3), + "_group": []map[string]any{ + { + "Verified": true, + "_count": int(2), + }, + { + "Verified": false, + "_count": int(1), + }, + }, }, - }, - }, - { - "Name": "Carlo", - "_sum": int64(1), - "_group": []map[string]any{ { - "Verified": true, - "_count": int(1), + "Name": "Carlo", + "_sum": int64(1), + "_group": []map[string]any{ + { + "Verified": true, + "_count": int(1), + }, + }, }, - }, - }, - { - "Name": "Alice", - "_sum": int64(1), - "_group": []map[string]any{ { - "Verified": false, - "_count": int(1), + "Name": "Alice", + "_sum": int64(1), + "_group": []map[string]any{ + { + "Verified": false, + "_count": int(1), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_group_count_test.go b/tests/integration/query/simple/with_group_count_test.go index 4f979f3dcb..f41b1e1d99 100644 --- a/tests/integration/query/simple/with_group_count_test.go +++ b/tests/integration/query/simple/with_group_count_test.go @@ -17,32 +17,42 @@ import ( ) func TestQuerySimpleWithoutGroupByWithCountOnGroup(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query without group by, no children, count on non-existant group", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 32 + }`, + }, + testUtils.Request{ + Request: `query { Users { Age _count(_group: {}) } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 32 - }`, + ExpectedError: "_group may only be referenced when within a groupBy request", }, }, - ExpectedError: "_group may only be referenced when within a groupBy request", } executeTestCase(t, test) } func TestQuerySimpleWithGroupByNumberWithCountOnInnerNonExistantGroup(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query without group by, no children, count on inner non-existant group", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 32 + }`, + }, + testUtils.Request{ + Request: `query { Users(groupBy: [Age]) { Age _group { @@ -51,54 +61,54 @@ func TestQuerySimpleWithGroupByNumberWithCountOnInnerNonExistantGroup(t *testing } } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 32 - }`, + ExpectedError: "_group may only be referenced when within a groupBy request", }, }, - ExpectedError: "_group may only be referenced when within a groupBy request", } executeTestCase(t, test) } func TestQuerySimpleWithGroupByNumberWithoutRenderedGroupAndChildCount(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, count on non-rendered group", - Request: `query { - Users(groupBy: [Age]) { - Age - _count(_group: {}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "_count": 2, - }, - { - "Age": int64(19), - "_count": 1, + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + _count(_group: {}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Age": int64(32), + "_count": 2, + }, + { + "Age": int64(19), + "_count": 1, + }, + }, }, }, }, @@ -108,16 +118,20 @@ func TestQuerySimpleWithGroupByNumberWithoutRenderedGroupAndChildCount(t *testin } func TestQuerySimpleWithGroupByNumberWithoutRenderedGroupAndChildCountOnEmptyCollection(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, count on non-rendered group, empty collection", - Request: `query { + Actions: []any{ + testUtils.Request{ + Request: `query { Users(groupBy: [Age]) { Age _count(_group: {}) } }`, - Results: map[string]any{ - "Users": []map[string]any{}, + Results: map[string]any{ + "Users": []map[string]any{}, + }, + }, }, } @@ -125,53 +139,59 @@ func TestQuerySimpleWithGroupByNumberWithoutRenderedGroupAndChildCountOnEmptyCol } func TestQuerySimpleWithGroupByNumberWithRenderedGroupAndChildCount(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, count on rendered group", - Request: `query { - Users(groupBy: [Age]) { - Age - _count(_group: {}) - _group { - Name - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "_count": 2, - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + _count(_group: {}) + _group { + Name + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Name": "Bob", + "Age": int64(32), + "_count": 2, + "_group": []map[string]any{ + { + "Name": "Bob", + }, + { + "Name": "John", + }, + }, }, { - "Name": "John", - }, - }, - }, - { - "Age": int64(19), - "_count": 1, - "_group": []map[string]any{ - { - "Name": "Alice", + "Age": int64(19), + "_count": 1, + "_group": []map[string]any{ + { + "Name": "Alice", + }, + }, }, }, }, @@ -183,70 +203,82 @@ func TestQuerySimpleWithGroupByNumberWithRenderedGroupAndChildCount(t *testing.T } func TestQuerySimpleWithGroupByNumberWithUndefinedField(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, count on undefined field", - Request: `query { - Users(groupBy: [Age]) { - Age - _count - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + _count + } + }`, + ExpectedError: "aggregate must be provided with a property to aggregate", + }, }, - ExpectedError: "aggregate must be provided with a property to aggregate", } executeTestCase(t, test) } func TestQuerySimpleWithGroupByNumberWithoutRenderedGroupAndAliasesChildCount(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, aliased count on non-rendered group", - Request: `query { - Users(groupBy: [Age]) { - Age - Count: _count(_group: {}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "Count": 2, - }, - { - "Age": int64(19), - "Count": 1, + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + Count: _count(_group: {}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Age": int64(32), + "Count": 2, + }, + { + "Age": int64(19), + "Count": 1, + }, + }, }, }, }, @@ -258,42 +290,48 @@ func TestQuerySimpleWithGroupByNumberWithoutRenderedGroupAndAliasesChildCount(t func TestQuerySimpleWithGroupByNumberWithoutRenderedGroupAndDuplicatedAliasedChildCounts( t *testing.T, ) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, duplicated aliased count on non-rendered group", - Request: `query { - Users(groupBy: [Age]) { - Age - Count1: _count(_group: {}) - Count2: _count(_group: {}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "Count1": 2, - "Count2": 2, - }, - { - "Age": int64(19), - "Count1": 1, - "Count2": 1, + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + Count1: _count(_group: {}) + Count2: _count(_group: {}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Age": int64(32), + "Count1": 2, + "Count2": 2, + }, + { + "Age": int64(19), + "Count1": 1, + "Count2": 1, + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_group_doc_id_test.go b/tests/integration/query/simple/with_group_doc_id_test.go index 9529f7e3bd..336a64e351 100644 --- a/tests/integration/query/simple/with_group_doc_id_test.go +++ b/tests/integration/query/simple/with_group_doc_id_test.go @@ -17,47 +17,52 @@ import ( ) func TestQuerySimpleWithGroupByWithGroupWithDocID(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with docID filter on _group", - Request: `query { - Users(groupBy: [Age]) { - Age - _group(docID: "bae-d4303725-7db9-53d2-b324-f3ee44020e52") { - Name - } - } - }`, - Docs: map[int][]string{ - 0: { - // bae-d4303725-7db9-53d2-b324-f3ee44020e52 - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Fred", "Age": 21 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(21), - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + _group(docID: "bae-d4303725-7db9-53d2-b324-f3ee44020e52") { + Name + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Name": "John", + "Age": int64(21), + "_group": []map[string]any{ + { + "Name": "John", + }, + }, + }, + { + "Age": int64(32), + "_group": []map[string]any{}, }, }, }, - { - "Age": int64(32), - "_group": []map[string]any{}, - }, }, }, } diff --git a/tests/integration/query/simple/with_group_doc_ids_test.go b/tests/integration/query/simple/with_group_doc_ids_test.go index cafbb21481..5798bd387f 100644 --- a/tests/integration/query/simple/with_group_doc_ids_test.go +++ b/tests/integration/query/simple/with_group_doc_ids_test.go @@ -17,55 +17,61 @@ import ( ) func TestQuerySimpleWithGroupByWithGroupWithDocIDs(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with docIDs filter on _group", - Request: `query { - Users(groupBy: [Age]) { - Age - _group(docIDs: ["bae-d4303725-7db9-53d2-b324-f3ee44020e52", "bae-19b16890-5f24-5e5b-8822-ed2a97ebcc24"]) { - Name - } - } - }`, - Docs: map[int][]string{ - 0: { - // bae-d4303725-7db9-53d2-b324-f3ee44020e52 - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - // bae-19b16890-5f24-5e5b-8822-ed2a97ebcc24 - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Fred", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Shahzad", "Age": 21 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(21), - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + _group(docIDs: ["bae-d4303725-7db9-53d2-b324-f3ee44020e52", "bae-19b16890-5f24-5e5b-8822-ed2a97ebcc24"]) { + Name + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Name": "Fred", + "Age": int64(21), + "_group": []map[string]any{ + { + "Name": "Fred", + }, + { + "Name": "John", + }, + }, }, { - "Name": "John", + "Age": int64(32), + "_group": []map[string]any{}, }, }, }, - { - "Age": int64(32), - "_group": []map[string]any{}, - }, }, }, } diff --git a/tests/integration/query/simple/with_group_filter_test.go b/tests/integration/query/simple/with_group_filter_test.go index 3e3b5f32fe..3d9ecf4c36 100644 --- a/tests/integration/query/simple/with_group_filter_test.go +++ b/tests/integration/query/simple/with_group_filter_test.go @@ -17,58 +17,66 @@ import ( ) func TestQuerySimpleWithGroupByStringWithGroupNumberFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by with child filter", - Request: `query { - Users(groupBy: [Name]) { - Name - _group (filter: {Age: {_gt: 26}}){ - Age - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 25 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Carlo", - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _group (filter: {Age: {_gt: 26}}){ + Age + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Age": int64(55), + "Name": "Carlo", + "_group": []map[string]any{ + { + "Age": int64(55), + }, + }, }, - }, - }, - { - "Name": "John", - "_group": []map[string]any{ { - "Age": int64(32), + "Name": "John", + "_group": []map[string]any{ + { + "Age": int64(32), + }, + }, + }, + { + "Name": "Alice", + "_group": []map[string]any{}, }, }, }, - { - "Name": "Alice", - "_group": []map[string]any{}, - }, }, }, } @@ -77,51 +85,59 @@ func TestQuerySimpleWithGroupByStringWithGroupNumberFilter(t *testing.T) { } func TestQuerySimpleWithGroupByStringWithGroupNumberWithParentFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by with number filter", - Request: `query { - Users(groupBy: [Name], filter: {Age: {_gt: 26}}) { - Name - _group { - Age - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 25 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Carlo", - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Name], filter: {Age: {_gt: 26}}) { + Name + _group { + Age + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Age": int64(55), + "Name": "Carlo", + "_group": []map[string]any{ + { + "Age": int64(55), + }, + }, }, - }, - }, - { - "Name": "John", - "_group": []map[string]any{ { - "Age": int64(32), + "Name": "John", + "_group": []map[string]any{ + { + "Age": int64(32), + }, + }, }, }, }, @@ -133,40 +149,48 @@ func TestQuerySimpleWithGroupByStringWithGroupNumberWithParentFilter(t *testing. } func TestQuerySimpleWithGroupByStringWithUnrenderedGroupNumberWithParentFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by with number filter", - Request: `query { - Users(groupBy: [Name], filter: {Age: {_gt: 26}}) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 25 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Carlo", - }, - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(groupBy: [Name], filter: {Age: {_gt: 26}}) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Carlo", + }, + { + "Name": "John", + }, + }, }, }, }, @@ -178,78 +202,88 @@ func TestQuerySimpleWithGroupByStringWithUnrenderedGroupNumberWithParentFilter(t func TestQuerySimpleWithGroupByStringWithInnerGroupBooleanThenInnerNumberFilterThatExcludesAll( t *testing.T, ) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, with child group by boolean, with child number filter that excludes all records", - Request: `query { - Users(groupBy: [Name]) { - Name - _group (groupBy: [Verified]){ - Verified - _group (filter: {Age: {_gt: 260}}) { - Age - } - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 25, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 34, "Verified": false }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19, "Verified": false }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_group": []map[string]any{ - { - "Verified": true, - "_group": []map[string]any{}, - }, + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _group (groupBy: [Verified]){ + Verified + _group (filter: {Age: {_gt: 260}}) { + Age + } + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Verified": false, - "_group": []map[string]any{}, + "Name": "John", + "_group": []map[string]any{ + { + "Verified": true, + "_group": []map[string]any{}, + }, + { + "Verified": false, + "_group": []map[string]any{}, + }, + }, }, - }, - }, - { - "Name": "Carlo", - "_group": []map[string]any{ { - "Verified": true, - "_group": []map[string]any{}, + "Name": "Carlo", + "_group": []map[string]any{ + { + "Verified": true, + "_group": []map[string]any{}, + }, + }, }, - }, - }, - { - "Name": "Alice", - "_group": []map[string]any{ { - "Verified": false, - "_group": []map[string]any{}, + "Name": "Alice", + "_group": []map[string]any{ + { + "Verified": false, + "_group": []map[string]any{}, + }, + }, }, }, }, @@ -261,69 +295,77 @@ func TestQuerySimpleWithGroupByStringWithInnerGroupBooleanThenInnerNumberFilterT } func TestQuerySimpleWithGroupByStringWithMultipleGroupNumberFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by with child filter", - Request: `query { - Users(groupBy: [Name]) { - Name - G1: _group (filter: {Age: {_gt: 26}}){ - Age - } - G2: _group (filter: {Age: {_lt: 26}}){ - Age - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 25 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Carlo", - "G1": []map[string]any{ - { - "Age": int64(55), - }, - }, - "G2": []map[string]any{}, - }, - { - "Name": "John", - "G1": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + G1: _group (filter: {Age: {_gt: 26}}){ + Age + } + G2: _group (filter: {Age: {_lt: 26}}){ + Age + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Age": int64(32), + "Name": "Carlo", + "G1": []map[string]any{ + { + "Age": int64(55), + }, + }, + "G2": []map[string]any{}, }, - }, - "G2": []map[string]any{ { - "Age": int64(25), + "Name": "John", + "G1": []map[string]any{ + { + "Age": int64(32), + }, + }, + "G2": []map[string]any{ + { + "Age": int64(25), + }, + }, }, - }, - }, - { - "Name": "Alice", - "G1": []map[string]any{}, - "G2": []map[string]any{ { - "Age": int64(19), + "Name": "Alice", + "G1": []map[string]any{}, + "G2": []map[string]any{ + { + "Age": int64(19), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_group_limit_offset_test.go b/tests/integration/query/simple/with_group_limit_offset_test.go index ea4c2afc81..7c45c50559 100644 --- a/tests/integration/query/simple/with_group_limit_offset_test.go +++ b/tests/integration/query/simple/with_group_limit_offset_test.go @@ -17,46 +17,52 @@ import ( ) func TestQuerySimpleWithGroupByNumberWithGroupLimitAndOffset(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, rendered, limited and offset group", - Request: `query { - Users(groupBy: [Age]) { - Age - _group(limit: 1, offset: 1) { - Name - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + _group(limit: 1, offset: 1) { + Name + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Name": "John", + "Age": int64(32), + "_group": []map[string]any{ + { + "Name": "John", + }, + }, + }, + { + "Age": int64(19), + "_group": []map[string]any{}, }, }, }, - { - "Age": int64(19), - "_group": []map[string]any{}, - }, }, }, } @@ -65,37 +71,43 @@ func TestQuerySimpleWithGroupByNumberWithGroupLimitAndOffset(t *testing.T) { } func TestQuerySimpleWithGroupByNumberWithLimitAndOffsetAndWithGroupLimitAndOffset(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number with limit and offset, no children, rendered, limited and offset group", - Request: `query { - Users(groupBy: [Age], limit: 1, offset: 1) { - Age - _group(limit: 1, offset: 1) { - Name - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(19), - "_group": []map[string]any{}, + testUtils.Request{ + Request: `query { + Users(groupBy: [Age], limit: 1, offset: 1) { + Age + _group(limit: 1, offset: 1) { + Name + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Age": int64(19), + "_group": []map[string]any{}, + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_group_limit_test.go b/tests/integration/query/simple/with_group_limit_test.go index 2b7ac5d205..2f13f9dd3f 100644 --- a/tests/integration/query/simple/with_group_limit_test.go +++ b/tests/integration/query/simple/with_group_limit_test.go @@ -17,47 +17,53 @@ import ( ) func TestQuerySimpleWithGroupByNumberWithGroupLimit(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, rendered, limited group", - Request: `query { - Users(groupBy: [Age]) { - Age - _group(limit: 1) { - Name - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + _group(limit: 1) { + Name + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Name": "Bob", + "Age": int64(32), + "_group": []map[string]any{ + { + "Name": "Bob", + }, + }, }, - }, - }, - { - "Age": int64(19), - "_group": []map[string]any{ { - "Name": "Alice", + "Age": int64(19), + "_group": []map[string]any{ + { + "Name": "Alice", + }, + }, }, }, }, @@ -69,63 +75,69 @@ func TestQuerySimpleWithGroupByNumberWithGroupLimit(t *testing.T) { } func TestQuerySimpleWithGroupByNumberWithMultipleGroupsWithDifferentLimits(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, multiple rendered, limited groups", - Request: `query { - Users(groupBy: [Age]) { - Age - G1: _group(limit: 1) { - Name - } - G2: _group(limit: 2) { - Name - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "G1": []map[string]any{ - { - "Name": "Bob", - }, - }, - "G2": []map[string]any{ - { - "Name": "Bob", - }, - { - "Name": "John", - }, - }, - }, - { - "Age": int64(19), - "G1": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + G1: _group(limit: 1) { + Name + } + G2: _group(limit: 2) { + Name + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Name": "Alice", + "Age": int64(32), + "G1": []map[string]any{ + { + "Name": "Bob", + }, + }, + "G2": []map[string]any{ + { + "Name": "Bob", + }, + { + "Name": "John", + }, + }, }, - }, - "G2": []map[string]any{ { - "Name": "Alice", + "Age": int64(19), + "G1": []map[string]any{ + { + "Name": "Alice", + }, + }, + "G2": []map[string]any{ + { + "Name": "Alice", + }, + }, }, }, }, @@ -137,42 +149,48 @@ func TestQuerySimpleWithGroupByNumberWithMultipleGroupsWithDifferentLimits(t *te } func TestQuerySimpleWithGroupByNumberWithLimitAndGroupWithHigherLimit(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number and limit, no children, rendered, limited group", - Request: `query { - Users(groupBy: [Age], limit: 1) { - Age - _group(limit: 2) { - Name - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "_group": []map[string]any{ - { - "Name": "Bob", - }, + testUtils.Request{ + Request: `query { + Users(groupBy: [Age], limit: 1) { + Age + _group(limit: 2) { + Name + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Name": "John", + "Age": int64(32), + "_group": []map[string]any{ + { + "Name": "Bob", + }, + { + "Name": "John", + }, + }, }, }, }, @@ -184,51 +202,59 @@ func TestQuerySimpleWithGroupByNumberWithLimitAndGroupWithHigherLimit(t *testing } func TestQuerySimpleWithGroupByNumberWithLimitAndGroupWithLowerLimit(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number and limit, no children, rendered, limited group", - Request: `query { - Users(groupBy: [Age], limit: 2) { - Age - _group(limit: 1) { - Name - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 42 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Age], limit: 2) { + Age + _group(limit: 1) { + Name + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Name": "Bob", + "Age": int64(32), + "_group": []map[string]any{ + { + "Name": "Bob", + }, + }, }, - }, - }, - { - "Age": int64(42), - "_group": []map[string]any{ { - "Name": "Alice", + "Age": int64(42), + "_group": []map[string]any{ + { + "Name": "Alice", + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_group_order_test.go b/tests/integration/query/simple/with_group_order_test.go index b1ace46918..7e8a2cbf17 100644 --- a/tests/integration/query/simple/with_group_order_test.go +++ b/tests/integration/query/simple/with_group_order_test.go @@ -17,62 +17,70 @@ import ( ) func TestQuerySimpleWithGroupByStringWithGroupNumberWithGroupOrder(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, and child order ascending", - Request: `query { - Users(groupBy: [Name]) { - Name - _group (order: {Age: ASC}){ - Age - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 25 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Carlo", - "_group": []map[string]any{ - { - "Age": int64(55), - }, - }, - }, - { - "Name": "Alice", - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _group (order: {Age: ASC}){ + Age + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Age": int64(19), + "Name": "Carlo", + "_group": []map[string]any{ + { + "Age": int64(55), + }, + }, }, - }, - }, - { - "Name": "John", - "_group": []map[string]any{ { - "Age": int64(25), + "Name": "Alice", + "_group": []map[string]any{ + { + "Age": int64(19), + }, + }, }, { - "Age": int64(32), + "Name": "John", + "_group": []map[string]any{ + { + "Age": int64(25), + }, + { + "Age": int64(32), + }, + }, }, }, }, @@ -84,62 +92,70 @@ func TestQuerySimpleWithGroupByStringWithGroupNumberWithGroupOrder(t *testing.T) } func TestQuerySimpleWithGroupByStringWithGroupNumberWithGroupOrderDescending(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, and child order descending", - Request: `query { - Users(groupBy: [Name]) { - Name - _group (order: {Age: DESC}){ - Age - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 25 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Carlo", - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _group (order: {Age: DESC}){ + Age + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Age": int64(55), + "Name": "Carlo", + "_group": []map[string]any{ + { + "Age": int64(55), + }, + }, }, - }, - }, - { - "Name": "John", - "_group": []map[string]any{ { - "Age": int64(32), + "Name": "John", + "_group": []map[string]any{ + { + "Age": int64(32), + }, + { + "Age": int64(25), + }, + }, }, { - "Age": int64(25), - }, - }, - }, - { - "Name": "Alice", - "_group": []map[string]any{ - { - "Age": int64(19), + "Name": "Alice", + "_group": []map[string]any{ + { + "Age": int64(19), + }, + }, }, }, }, @@ -151,62 +167,70 @@ func TestQuerySimpleWithGroupByStringWithGroupNumberWithGroupOrderDescending(t * } func TestQuerySimpleWithGroupByStringAndOrderDescendingWithGroupNumberWithGroupOrder(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, and child order ascending", - Request: `query { - Users(groupBy: [Name], order: {Name: DESC}) { - Name - _group (order: {Age: ASC}){ - Age - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 25 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_group": []map[string]any{ - { - "Age": int64(25), - }, + testUtils.Request{ + Request: `query { + Users(groupBy: [Name], order: {Name: DESC}) { + Name + _group (order: {Age: ASC}){ + Age + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Age": int64(32), + "Name": "John", + "_group": []map[string]any{ + { + "Age": int64(25), + }, + { + "Age": int64(32), + }, + }, }, - }, - }, - { - "Name": "Carlo", - "_group": []map[string]any{ { - "Age": int64(55), + "Name": "Carlo", + "_group": []map[string]any{ + { + "Age": int64(55), + }, + }, }, - }, - }, - { - "Name": "Alice", - "_group": []map[string]any{ { - "Age": int64(19), + "Name": "Alice", + "_group": []map[string]any{ + { + "Age": int64(19), + }, + }, }, }, }, @@ -218,95 +242,105 @@ func TestQuerySimpleWithGroupByStringAndOrderDescendingWithGroupNumberWithGroupO } func TestQuerySimpleWithGroupByStringWithInnerGroupBooleanThenInnerOrderDescending(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, with child group by boolean, with child order desc", - Request: `query { - Users(groupBy: [Name]) { - Name - _group (groupBy: [Verified]){ - Verified - _group (order: {Age: DESC}) { - Age - } - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 25, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 34, "Verified": false }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19, "Verified": false }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _group (groupBy: [Verified]){ + Verified + _group (order: {Age: DESC}) { + Age + } + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Verified": true, + "Name": "John", "_group": []map[string]any{ { - "Age": int64(32), + "Verified": true, + "_group": []map[string]any{ + { + "Age": int64(32), + }, + { + "Age": int64(25), + }, + }, }, { - "Age": int64(25), + "Verified": false, + "_group": []map[string]any{ + { + "Age": int64(34), + }, + }, }, }, }, { - "Verified": false, + "Name": "Carlo", "_group": []map[string]any{ { - "Age": int64(34), + "Verified": true, + "_group": []map[string]any{ + { + "Age": int64(55), + }, + }, }, }, }, - }, - }, - { - "Name": "Carlo", - "_group": []map[string]any{ - { - "Verified": true, - "_group": []map[string]any{ - { - "Age": int64(55), - }, - }, - }, - }, - }, - { - "Name": "Alice", - "_group": []map[string]any{ { - "Verified": false, + "Name": "Alice", "_group": []map[string]any{ { - "Age": int64(19), + "Verified": false, + "_group": []map[string]any{ + { + "Age": int64(19), + }, + }, }, }, }, @@ -322,95 +356,105 @@ func TestQuerySimpleWithGroupByStringWithInnerGroupBooleanThenInnerOrderDescendi func TestQuerySimpleWithGroupByStringWithInnerGroupBooleanAndOrderAscendingThenInnerOrderDescending( t *testing.T, ) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, with child group by boolean, with child order desc", - Request: `query { - Users(groupBy: [Name]) { - Name - _group (groupBy: [Verified], order: {Verified: ASC}){ - Verified - _group (order: {Age: DESC}) { - Age - } - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 25, "Verified": false }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 34, "Verified": false }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19, "Verified": false }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _group (groupBy: [Verified], order: {Verified: ASC}){ + Verified + _group (order: {Age: DESC}) { + Age + } + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Verified": false, + "Name": "John", "_group": []map[string]any{ { - "Age": int64(34), + "Verified": false, + "_group": []map[string]any{ + { + "Age": int64(34), + }, + { + "Age": int64(25), + }, + }, }, { - "Age": int64(25), + "Verified": true, + "_group": []map[string]any{ + { + "Age": int64(32), + }, + }, }, }, }, { - "Verified": true, + "Name": "Alice", "_group": []map[string]any{ { - "Age": int64(32), + "Verified": false, + "_group": []map[string]any{ + { + "Age": int64(19), + }, + }, }, }, }, - }, - }, - { - "Name": "Alice", - "_group": []map[string]any{ { - "Verified": false, + "Name": "Carlo", "_group": []map[string]any{ { - "Age": int64(19), - }, - }, - }, - }, - }, - { - "Name": "Carlo", - "_group": []map[string]any{ - { - "Verified": true, - "_group": []map[string]any{ - { - "Age": int64(55), + "Verified": true, + "_group": []map[string]any{ + { + "Age": int64(55), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_group_sum_filter_test.go b/tests/integration/query/simple/with_group_sum_filter_test.go index cf9f8e3a0b..7ba39a1fda 100644 --- a/tests/integration/query/simple/with_group_sum_filter_test.go +++ b/tests/integration/query/simple/with_group_sum_filter_test.go @@ -17,39 +17,45 @@ import ( ) func TestQuerySimpleWithGroupByNumberWithoutRenderedGroupAndChildSumWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, sum on non-rendered, unfiltered group", - Request: `query { - Users(groupBy: [Age]) { - Age - _sum(_group: {field: Age, filter: {Age: {_gt: 26}}}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "_sum": int64(64), - }, - { - "Age": int64(19), - "_sum": int64(0), + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + _sum(_group: {field: Age, filter: {Age: {_gt: 26}}}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Age": int64(32), + "_sum": int64(64), + }, + { + "Age": int64(19), + "_sum": int64(0), + }, + }, }, }, }, @@ -59,53 +65,59 @@ func TestQuerySimpleWithGroupByNumberWithoutRenderedGroupAndChildSumWithFilter(t } func TestQuerySimpleWithGroupByNumberWithRenderedGroupAndChildSumWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, sum on rendered, unfiltered group", - Request: `query { - Users(groupBy: [Age]) { - Age - _sum(_group: {field: Age, filter: {Age: {_gt: 26}}}) - _group { - Name - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "_sum": int64(64), - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + _sum(_group: {field: Age, filter: {Age: {_gt: 26}}}) + _group { + Name + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Name": "Bob", + "Age": int64(32), + "_sum": int64(64), + "_group": []map[string]any{ + { + "Name": "Bob", + }, + { + "Name": "John", + }, + }, }, { - "Name": "John", - }, - }, - }, - { - "Age": int64(19), - "_sum": int64(0), - "_group": []map[string]any{ - { - "Name": "Alice", + "Age": int64(19), + "_sum": int64(0), + "_group": []map[string]any{ + { + "Name": "Alice", + }, + }, }, }, }, @@ -117,49 +129,55 @@ func TestQuerySimpleWithGroupByNumberWithRenderedGroupAndChildSumWithFilter(t *t } func TestQuerySimpleWithGroupByNumberWithRenderedGroupWithFilterAndChildSumWithMatchingFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, sum on rendered, matching filtered group", - Request: `query { - Users(groupBy: [Age]) { - Age - _sum(_group: {field: Age, filter: {Name: {_eq: "John"}}}) - _group(filter: {Name: {_eq: "John"}}) { - Name - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "_sum": int64(32), - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + _sum(_group: {field: Age, filter: {Name: {_eq: "John"}}}) + _group(filter: {Name: {_eq: "John"}}) { + Name + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Name": "John", + "Age": int64(32), + "_sum": int64(32), + "_group": []map[string]any{ + { + "Name": "John", + }, + }, + }, + { + "Age": int64(19), + "_sum": int64(0), + "_group": []map[string]any{}, }, }, }, - { - "Age": int64(19), - "_sum": int64(0), - "_group": []map[string]any{}, - }, }, }, } @@ -168,49 +186,55 @@ func TestQuerySimpleWithGroupByNumberWithRenderedGroupWithFilterAndChildSumWithM } func TestQuerySimpleWithGroupByNumberWithRenderedGroupWithFilterAndChildSumWithDifferentFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, sum on non-rendered, different filtered group", - Request: `query { - Users(groupBy: [Age]) { - Age - _sum(_group: {field: Age, filter: {Age: {_gt: 26}}}) - _group(filter: {Name: {_eq: "John"}}) { - Name - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "_sum": int64(64), - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + _sum(_group: {field: Age, filter: {Age: {_gt: 26}}}) + _group(filter: {Name: {_eq: "John"}}) { + Name + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Age": int64(32), + "_sum": int64(64), + "_group": []map[string]any{ + { + "Name": "John", + }, + }, + }, { - "Name": "John", + "Age": int64(19), + "_sum": int64(0), + "_group": []map[string]any{}, }, }, }, - { - "Age": int64(19), - "_sum": int64(0), - "_group": []map[string]any{}, - }, }, }, } @@ -219,42 +243,48 @@ func TestQuerySimpleWithGroupByNumberWithRenderedGroupWithFilterAndChildSumWithD } func TestQuerySimpleWithGroupByNumberWithoutRenderedGroupAndChildSumsWithDifferentFilters(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, sum on non-rendered, unfiltered group", - Request: `query { - Users(groupBy: [Age]) { - Age - S1: _sum(_group: {field: Age, filter: {Age: {_gt: 26}}}) - S2: _sum(_group: {field: Age, filter: {Age: {_lt: 26}}}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(32), - "S1": int64(64), - "S2": int64(0), - }, - { - "Age": int64(19), - "S1": int64(0), - "S2": int64(19), + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + S1: _sum(_group: {field: Age, filter: {Age: {_gt: 26}}}) + S2: _sum(_group: {field: Age, filter: {Age: {_lt: 26}}}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Age": int64(32), + "S1": int64(64), + "S2": int64(0), + }, + { + "Age": int64(19), + "S1": int64(0), + "S2": int64(19), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_group_sum_limit_offset_test.go b/tests/integration/query/simple/with_group_sum_limit_offset_test.go index 7ba181b3c5..2222b62966 100644 --- a/tests/integration/query/simple/with_group_sum_limit_offset_test.go +++ b/tests/integration/query/simple/with_group_sum_limit_offset_test.go @@ -17,44 +17,52 @@ import ( ) func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildIntegerSumWithLimitAndOffset(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, offsetted limited sum on non-rendered group integer value", - Request: `query { - Users(groupBy: [Name]) { - Name - _sum(_group: {field: Age, offset: 1, limit: 2}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 38 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 28 }`, + }, + testUtils.CreateDoc{ // It is important to test negative values here, due to the auto-typing of numbers - `{ + Doc: `{ "Name": "Alice", "Age": -19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_sum": int64(70), - }, - { - "Name": "Alice", - "_sum": int64(0), + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _sum(_group: {field: Age, offset: 1, limit: 2}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "_sum": int64(70), + }, + { + "Name": "Alice", + "_sum": int64(0), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_group_sum_limit_test.go b/tests/integration/query/simple/with_group_sum_limit_test.go index eda7ea131b..631a7914a2 100644 --- a/tests/integration/query/simple/with_group_sum_limit_test.go +++ b/tests/integration/query/simple/with_group_sum_limit_test.go @@ -17,44 +17,52 @@ import ( ) func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildIntegerSumWithLimit(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, limited sum on non-rendered group integer value", - Request: `query { - Users(groupBy: [Name]) { - Name - _sum(_group: {field: Age, limit: 2}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 38 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 28 }`, + }, + testUtils.CreateDoc{ // It is important to test negative values here, due to the auto-typing of numbers - `{ + Doc: `{ "Name": "Alice", "Age": -19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_sum": int64(66), - }, - { - "Name": "Alice", - "_sum": int64(-19), + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _sum(_group: {field: Age, limit: 2}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "_sum": int64(66), + }, + { + "Name": "Alice", + "_sum": int64(-19), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_group_sum_test.go b/tests/integration/query/simple/with_group_sum_test.go index 03bfb3e2de..a6a70b6b69 100644 --- a/tests/integration/query/simple/with_group_sum_test.go +++ b/tests/integration/query/simple/with_group_sum_test.go @@ -17,39 +17,45 @@ import ( ) func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndSumOfUndefined(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with sum on unspecified field", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 32 + }`, + }, + testUtils.Request{ + Request: `query { Users (groupBy: [Name]) { Name _sum } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 32 - }`, + ExpectedError: "aggregate must be provided with a property to aggregate", }, }, - ExpectedError: "aggregate must be provided with a property to aggregate", } executeTestCase(t, test) } func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildIntegerSumOnEmptyCollection(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, sum on non-rendered group, empty collection", - Request: `query { + Actions: []any{ + testUtils.Request{ + Request: `query { Users(groupBy: [Age]) { Age _sum(_group: {field: Age}) } }`, - Results: map[string]any{ - "Users": []map[string]any{}, + Results: map[string]any{ + "Users": []map[string]any{}, + }, + }, }, } @@ -57,40 +63,46 @@ func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildIntegerSumOnEmp } func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildIntegerSum(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, sum on non-rendered group integer value", - Request: `query { - Users(groupBy: [Name]) { - Name - _sum(_group: {field: Age}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 38 }`, + }, + testUtils.CreateDoc{ // It is important to test negative values here, due to the auto-typing of numbers - `{ + Doc: `{ "Name": "Alice", "Age": -19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_sum": int64(70), - }, - { - "Name": "Alice", - "_sum": int64(-19), + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _sum(_group: {field: Age}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "_sum": int64(70), + }, + { + "Name": "Alice", + "_sum": int64(-19), + }, + }, }, }, }, @@ -100,39 +112,45 @@ func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildIntegerSum(t *t } func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildNilSum(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, sum on non-rendered group nil and integer values", - Request: `query { - Users(groupBy: [Name]) { - Name - _sum(_group: {field: Age}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, + }, + testUtils.CreateDoc{ // Age is undefined here - `{ + Doc: `{ "Name": "John" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_sum": int64(32), - }, - { - "Name": "Alice", - "_sum": int64(19), + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _sum(_group: {field: Age}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "_sum": int64(32), + }, + { + "Name": "Alice", + "_sum": int64(19), + }, + }, }, }, }, @@ -142,80 +160,90 @@ func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildNilSum(t *testi } func TestQuerySimpleWithGroupByStringWithInnerGroupBooleanAndSumOfSumOfInt(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, with child group by boolean, and sum of sum on int", - Request: `query { - Users(groupBy: [Name]) { - Name - _sum(_group: {field: _sum}) - _group (groupBy: [Verified]){ - Verified - _sum(_group: {field: Age}) - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 25, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 34, "Verified": false }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19, "Verified": false }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_sum": int64(91), - "_group": []map[string]any{ - { - "Verified": true, - "_sum": int64(57), - }, + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _sum(_group: {field: _sum}) + _group (groupBy: [Verified]){ + Verified + _sum(_group: {field: Age}) + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Verified": false, - "_sum": int64(34), + "Name": "John", + "_sum": int64(91), + "_group": []map[string]any{ + { + "Verified": true, + "_sum": int64(57), + }, + { + "Verified": false, + "_sum": int64(34), + }, + }, }, - }, - }, - { - "Name": "Carlo", - "_sum": int64(55), - "_group": []map[string]any{ { - "Verified": true, - "_sum": int64(55), + "Name": "Carlo", + "_sum": int64(55), + "_group": []map[string]any{ + { + "Verified": true, + "_sum": int64(55), + }, + }, }, - }, - }, - { - "Name": "Alice", - "_sum": int64(19), - "_group": []map[string]any{ { - "Verified": false, - "_sum": int64(19), + "Name": "Alice", + "_sum": int64(19), + "_group": []map[string]any{ + { + "Verified": false, + "_sum": int64(19), + }, + }, }, }, }, @@ -227,38 +255,44 @@ func TestQuerySimpleWithGroupByStringWithInnerGroupBooleanAndSumOfSumOfInt(t *te } func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildEmptyFloatSum(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, sum on non-rendered group float (default) value", - Request: `query { - Users(groupBy: [Name]) { - Name - _sum(_group: {field: HeightM}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 1.82 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 1.89 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_sum": float64(3.71), - }, - { - "Name": "Alice", - "_sum": float64(0), + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _sum(_group: {field: HeightM}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "_sum": float64(3.71), + }, + { + "Name": "Alice", + "_sum": float64(0), + }, + }, }, }, }, @@ -268,39 +302,45 @@ func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildEmptyFloatSum(t } func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildFloatSum(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, sum on non-rendered group float value", - Request: `query { - Users(groupBy: [Name]) { - Name - _sum(_group: {field: HeightM}) - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 1.82 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 1.89 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "HeightM": 2.04 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_sum": float64(3.71), - }, - { - "Name": "Alice", - "_sum": float64(2.04), + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _sum(_group: {field: HeightM}) + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "_sum": float64(3.71), + }, + { + "Name": "Alice", + "_sum": float64(2.04), + }, + }, }, }, }, @@ -310,80 +350,90 @@ func TestQuerySimpleWithGroupByStringWithoutRenderedGroupAndChildFloatSum(t *tes } func TestQuerySimpleWithGroupByStringWithInnerGroupBooleanAndSumOfSumOfFloat(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, with child group by boolean, and sum of sum on float", - Request: `query { - Users(groupBy: [Name]) { - Name - _sum(_group: {field: _sum}) - _group (groupBy: [Verified]){ - Verified - _sum(_group: {field: HeightM}) - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 1.82, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 1.61, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.22, "Verified": false }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "HeightM": 1.74, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "HeightM": 2.04, "Verified": false }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Alice", - "_sum": float64(2.04), - "_group": []map[string]any{ - { - "Verified": false, - "_sum": float64(2.04), - }, - }, - }, - { - "Name": "John", - "_sum": float64(5.65), - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _sum(_group: {field: _sum}) + _group (groupBy: [Verified]){ + Verified + _sum(_group: {field: HeightM}) + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Verified": true, - "_sum": float64(3.43), + "Name": "Alice", + "_sum": float64(2.04), + "_group": []map[string]any{ + { + "Verified": false, + "_sum": float64(2.04), + }, + }, }, { - "Verified": false, - "_sum": float64(2.22), + "Name": "John", + "_sum": float64(5.65), + "_group": []map[string]any{ + { + "Verified": true, + "_sum": float64(3.43), + }, + { + "Verified": false, + "_sum": float64(2.22), + }, + }, }, - }, - }, - { - "Name": "Carlo", - "_sum": float64(1.74), - "_group": []map[string]any{ { - "Verified": true, - "_sum": float64(1.74), + "Name": "Carlo", + "_sum": float64(1.74), + "_group": []map[string]any{ + { + "Verified": true, + "_sum": float64(1.74), + }, + }, }, }, }, @@ -395,115 +445,125 @@ func TestQuerySimpleWithGroupByStringWithInnerGroupBooleanAndSumOfSumOfFloat(t * } func TestQuerySimpleWithGroupByStringWithInnerGroupBooleanAndSumOfSumOfSumOfFloat(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, with child group by boolean, and sum of sum of sum of float", - Request: `query { - Users(groupBy: [Name]) { - Name - _sum(_group: {field: _sum}) - _group (groupBy: [Verified]){ - Verified - _sum(_group: {field: HeightM}) - _group (groupBy: [Age]){ - Age - _sum(_group: {field: HeightM}) - } - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 1.82, "Age": 25, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 1.61, "Age": 32, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "HeightM": 2.22, "Age": 34, "Verified": false }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "HeightM": 1.74, "Age": 55, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "HeightM": 2.04, "Age": 19, "Verified": false }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Carlo", - "_sum": float64(1.74), - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _sum(_group: {field: _sum}) + _group (groupBy: [Verified]){ + Verified + _sum(_group: {field: HeightM}) + _group (groupBy: [Age]){ + Age + _sum(_group: {field: HeightM}) + } + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Verified": true, - "_sum": float64(1.74), + "Name": "Carlo", + "_sum": float64(1.74), "_group": []map[string]any{ { - "Age": int64(55), - "_sum": float64(1.74), + "Verified": true, + "_sum": float64(1.74), + "_group": []map[string]any{ + { + "Age": int64(55), + "_sum": float64(1.74), + }, + }, }, }, }, - }, - }, - { - "Name": "Alice", - "_sum": float64(2.04), - "_group": []map[string]any{ { - "Verified": false, - "_sum": float64(2.04), + "Name": "Alice", + "_sum": float64(2.04), "_group": []map[string]any{ { - "Age": int64(19), - "_sum": float64(2.04), + "Verified": false, + "_sum": float64(2.04), + "_group": []map[string]any{ + { + "Age": int64(19), + "_sum": float64(2.04), + }, + }, }, }, }, - }, - }, - { - "Name": "John", - "_sum": float64(5.65), - "_group": []map[string]any{ { - "Verified": true, - "_sum": float64(3.43), + "Name": "John", + "_sum": float64(5.65), "_group": []map[string]any{ { - "Age": int64(32), - "_sum": float64(1.61), - }, - { - "Age": int64(25), - "_sum": float64(1.82), + "Verified": true, + "_sum": float64(3.43), + "_group": []map[string]any{ + { + "Age": int64(32), + "_sum": float64(1.61), + }, + { + "Age": int64(25), + "_sum": float64(1.82), + }, + }, }, - }, - }, - { - "Verified": false, - "_sum": float64(2.22), - "_group": []map[string]any{ { - "Age": int64(34), - "_sum": float64(2.22), + "Verified": false, + "_sum": float64(2.22), + "_group": []map[string]any{ + { + "Age": int64(34), + "_sum": float64(2.22), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_group_test.go b/tests/integration/query/simple/with_group_test.go index 7b71ebf90f..ddb141afab 100644 --- a/tests/integration/query/simple/with_group_test.go +++ b/tests/integration/query/simple/with_group_test.go @@ -17,36 +17,40 @@ import ( ) func TestQuerySimpleWithGroupByEmpty(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by empty set, children", - Request: `query { - Users(groupBy: []) { - _group { - Name - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "_group": []map[string]any{ - { - "Name": "Bob", - }, + testUtils.Request{ + Request: `query { + Users(groupBy: []) { + _group { + Name + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Name": "John", + "_group": []map[string]any{ + { + "Name": "Bob", + }, + { + "Name": "John", + }, + }, }, }, }, @@ -58,43 +62,51 @@ func TestQuerySimpleWithGroupByEmpty(t *testing.T) { } func TestQuerySimpleWithGroupByNumber(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children", - Request: `query { - Users(groupBy: [Age]) { - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(55), - }, - { - "Age": int64(32), - }, - { - "Age": int64(19), + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Age": int64(55), + }, + { + "Age": int64(32), + }, + { + "Age": int64(19), + }, + }, }, }, }, @@ -104,43 +116,51 @@ func TestQuerySimpleWithGroupByNumber(t *testing.T) { } func TestQuerySimpleWithGroupByDateTime(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children", - Request: `query { - Users(groupBy: [CreatedAt]) { - CreatedAt - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "CreatedAt": "2011-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "CreatedAt": "2011-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "CreatedAt": "2012-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "CreatedAt": "2013-07-23T03:46:56-05:00" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "CreatedAt": testUtils.MustParseTime("2011-07-23T03:46:56-05:00"), - }, - { - "CreatedAt": testUtils.MustParseTime("2013-07-23T03:46:56-05:00"), - }, - { - "CreatedAt": testUtils.MustParseTime("2012-07-23T03:46:56-05:00"), + testUtils.Request{ + Request: `query { + Users(groupBy: [CreatedAt]) { + CreatedAt + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "CreatedAt": testUtils.MustParseTime("2011-07-23T03:46:56-05:00"), + }, + { + "CreatedAt": testUtils.MustParseTime("2013-07-23T03:46:56-05:00"), + }, + { + "CreatedAt": testUtils.MustParseTime("2012-07-23T03:46:56-05:00"), + }, + }, }, }, }, @@ -150,62 +170,70 @@ func TestQuerySimpleWithGroupByDateTime(t *testing.T) { } func TestQuerySimpleWithGroupByNumberWithGroupString(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, child string", - Request: `query { - Users(groupBy: [Age]) { - Age - _group { - Name - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": int64(55), - "_group": []map[string]any{ - { - "Name": "Carlo", - }, - }, - }, - { - "Age": int64(32), - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + _group { + Name + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Name": "Bob", + "Age": int64(55), + "_group": []map[string]any{ + { + "Name": "Carlo", + }, + }, }, { - "Name": "John", + "Age": int64(32), + "_group": []map[string]any{ + { + "Name": "Bob", + }, + { + "Name": "John", + }, + }, }, - }, - }, - { - "Age": int64(19), - "_group": []map[string]any{ { - "Name": "Alice", + "Age": int64(19), + "_group": []map[string]any{ + { + "Name": "Alice", + }, + }, }, }, }, @@ -217,62 +245,70 @@ func TestQuerySimpleWithGroupByNumberWithGroupString(t *testing.T) { } func TestQuerySimpleWithGroupByWithoutGroupedFieldSelectedWithInnerGroup(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with groupBy without selecting field grouped by, with inner _group.", - Request: `query { - Users(groupBy: [Name]) { - Name - _group { - Age - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 25 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Carlo", - "_group": []map[string]any{ - { - "Age": int64(55), - }, - }, - }, - { - "Name": "John", - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _group { + Age + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Age": int64(25), + "Name": "Carlo", + "_group": []map[string]any{ + { + "Age": int64(55), + }, + }, }, { - "Age": int64(32), + "Name": "John", + "_group": []map[string]any{ + { + "Age": int64(25), + }, + { + "Age": int64(32), + }, + }, }, - }, - }, - { - "Name": "Alice", - "_group": []map[string]any{ { - "Age": int64(19), + "Name": "Alice", + "_group": []map[string]any{ + { + "Age": int64(19), + }, + }, }, }, }, @@ -284,62 +320,70 @@ func TestQuerySimpleWithGroupByWithoutGroupedFieldSelectedWithInnerGroup(t *test } func TestQuerySimpleWithGroupByString(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string", - Request: `query { - Users(groupBy: [Name]) { - Name - _group { - Age - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 25 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Carlo", - "_group": []map[string]any{ - { - "Age": int64(55), - }, - }, - }, - { - "Name": "John", - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _group { + Age + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Age": int64(25), + "Name": "Carlo", + "_group": []map[string]any{ + { + "Age": int64(55), + }, + }, }, { - "Age": int64(32), + "Name": "John", + "_group": []map[string]any{ + { + "Age": int64(25), + }, + { + "Age": int64(32), + }, + }, }, - }, - }, - { - "Name": "Alice", - "_group": []map[string]any{ { - "Age": int64(19), + "Name": "Alice", + "_group": []map[string]any{ + { + "Age": int64(19), + }, + }, }, }, }, @@ -351,95 +395,105 @@ func TestQuerySimpleWithGroupByString(t *testing.T) { } func TestQuerySimpleWithGroupByStringWithInnerGroupBoolean(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string, with child group by boolean", - Request: `query { - Users(groupBy: [Name]) { - Name - _group (groupBy: [Verified]){ - Verified - _group { - Age - } - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 25, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 34, "Verified": false }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19, "Verified": false }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_group": []map[string]any{ + testUtils.Request{ + Request: `query { + Users(groupBy: [Name]) { + Name + _group (groupBy: [Verified]){ + Verified + _group { + Age + } + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Verified": true, + "Name": "John", "_group": []map[string]any{ { - "Age": int64(25), + "Verified": true, + "_group": []map[string]any{ + { + "Age": int64(25), + }, + { + "Age": int64(32), + }, + }, }, { - "Age": int64(32), + "Verified": false, + "_group": []map[string]any{ + { + "Age": int64(34), + }, + }, }, }, }, { - "Verified": false, - "_group": []map[string]any{ - { - "Age": int64(34), - }, - }, - }, - }, - }, - { - "Name": "Carlo", - "_group": []map[string]any{ - { - "Verified": true, + "Name": "Carlo", "_group": []map[string]any{ { - "Age": int64(55), + "Verified": true, + "_group": []map[string]any{ + { + "Age": int64(55), + }, + }, }, }, }, - }, - }, - { - "Name": "Alice", - "_group": []map[string]any{ { - "Verified": false, + "Name": "Alice", "_group": []map[string]any{ { - "Age": int64(19), + "Verified": false, + "_group": []map[string]any{ + { + "Age": int64(19), + }, + }, }, }, }, @@ -453,84 +507,94 @@ func TestQuerySimpleWithGroupByStringWithInnerGroupBoolean(t *testing.T) { } func TestQuerySimpleWithGroupByStringThenBoolean(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by string then by boolean", - Request: `query { - Users(groupBy: [Name, Verified]) { - Name - Verified - _group { - Age - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 25, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 34, "Verified": false }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19, "Verified": false }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Verified": true, - "_group": []map[string]any{ - { - "Age": int64(25), - }, + testUtils.Request{ + Request: `query { + Users(groupBy: [Name, Verified]) { + Name + Verified + _group { + Age + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Age": int64(32), + "Name": "John", + "Verified": true, + "_group": []map[string]any{ + { + "Age": int64(25), + }, + { + "Age": int64(32), + }, + }, }, - }, - }, - { - "Name": "John", - "Verified": false, - "_group": []map[string]any{ { - "Age": int64(34), + "Name": "John", + "Verified": false, + "_group": []map[string]any{ + { + "Age": int64(34), + }, + }, }, - }, - }, - { - "Name": "Carlo", - "Verified": true, - "_group": []map[string]any{ { - "Age": int64(55), + "Name": "Carlo", + "Verified": true, + "_group": []map[string]any{ + { + "Age": int64(55), + }, + }, }, - }, - }, - { - "Name": "Alice", - "Verified": false, - "_group": []map[string]any{ { - "Age": int64(19), + "Name": "Alice", + "Verified": false, + "_group": []map[string]any{ + { + "Age": int64(19), + }, + }, }, }, }, @@ -542,84 +606,94 @@ func TestQuerySimpleWithGroupByStringThenBoolean(t *testing.T) { } func TestQuerySimpleWithGroupByBooleanThenNumber(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by boolean then by string", - Request: `query { - Users(groupBy: [Verified, Name]) { - Name - Verified - _group { - Age - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 25, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 34, "Verified": false }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19, "Verified": false }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Verified": true, - "_group": []map[string]any{ - { - "Age": int64(25), - }, + testUtils.Request{ + Request: `query { + Users(groupBy: [Verified, Name]) { + Name + Verified + _group { + Age + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Age": int64(32), + "Name": "John", + "Verified": true, + "_group": []map[string]any{ + { + "Age": int64(25), + }, + { + "Age": int64(32), + }, + }, }, - }, - }, - { - "Name": "John", - "Verified": false, - "_group": []map[string]any{ { - "Age": int64(34), + "Name": "John", + "Verified": false, + "_group": []map[string]any{ + { + "Age": int64(34), + }, + }, }, - }, - }, - { - "Name": "Carlo", - "Verified": true, - "_group": []map[string]any{ { - "Age": int64(55), + "Name": "Carlo", + "Verified": true, + "_group": []map[string]any{ + { + "Age": int64(55), + }, + }, }, - }, - }, - { - "Name": "Alice", - "Verified": false, - "_group": []map[string]any{ { - "Age": int64(19), + "Name": "Alice", + "Verified": false, + "_group": []map[string]any{ + { + "Age": int64(19), + }, + }, }, }, }, @@ -631,34 +705,40 @@ func TestQuerySimpleWithGroupByBooleanThenNumber(t *testing.T) { } func TestQuerySimpleWithGroupByNumberOnUndefined(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children, undefined group value", - Request: `query { - Users(groupBy: [Age]) { - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": nil, - }, - { - "Age": int64(32), + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Age": nil, + }, + { + "Age": int64(32), + }, + }, }, }, }, @@ -668,48 +748,54 @@ func TestQuerySimpleWithGroupByNumberOnUndefined(t *testing.T) { } func TestQuerySimpleWithGroupByNumberOnUndefinedWithChildren(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, with children, undefined group value", - Request: `query { - Users(groupBy: [Age]) { - Age - _group { - Name - } - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Age": nil, - "_group": []map[string]any{ - { - "Name": "Alice", - }, + testUtils.Request{ + Request: `query { + Users(groupBy: [Age]) { + Age + _group { + Name + } + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ { - "Name": "Bob", + "Age": nil, + "_group": []map[string]any{ + { + "Name": "Alice", + }, + { + "Name": "Bob", + }, + }, }, - }, - }, - { - "Age": int64(32), - "_group": []map[string]any{ { - "Name": "John", + "Age": int64(32), + "_group": []map[string]any{ + { + "Name": "John", + }, + }, }, }, }, @@ -721,16 +807,19 @@ func TestQuerySimpleWithGroupByNumberOnUndefinedWithChildren(t *testing.T) { } func TestQuerySimpleErrorsWithNonGroupFieldsSelected(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with group by number, no children", - Request: `query { + Actions: []any{ + testUtils.Request{ + Request: `query { Users(groupBy: [Age]) { Age Name } }`, - Docs: map[int][]string{}, - ExpectedError: "cannot select a non-group-by field at group-level", + ExpectedError: "cannot select a non-group-by field at group-level", + }, + }, } executeTestCase(t, test) diff --git a/tests/integration/query/simple/with_group_typename_test.go b/tests/integration/query/simple/with_group_typename_test.go index d8179fc755..96078cf195 100644 --- a/tests/integration/query/simple/with_group_typename_test.go +++ b/tests/integration/query/simple/with_group_typename_test.go @@ -17,26 +17,28 @@ import ( ) func TestQuerySimpleWithGroupByWithTypeName(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query group by and parent typename", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John" + }`, + }, + testUtils.Request{ + Request: `query { Users(groupBy: [Name]) { Name __typename } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John" - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "__typename": "Users", + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "__typename": "Users", + }, + }, }, }, }, @@ -46,9 +48,16 @@ func TestQuerySimpleWithGroupByWithTypeName(t *testing.T) { } func TestQuerySimpleWithGroupByWithChildTypeName(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query group by and child typename", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John" + }`, + }, + testUtils.Request{ + Request: `query { Users(groupBy: [Name]) { Name _group { @@ -56,20 +65,15 @@ func TestQuerySimpleWithGroupByWithChildTypeName(t *testing.T) { } } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John" - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_group": []map[string]any{ + Results: map[string]any{ + "Users": []map[string]any{ { - "__typename": "Users", + "Name": "John", + "_group": []map[string]any{ + { + "__typename": "Users", + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_limit_offset_test.go b/tests/integration/query/simple/with_limit_offset_test.go index 458fc91cc9..aea6cb5b18 100644 --- a/tests/integration/query/simple/with_limit_offset_test.go +++ b/tests/integration/query/simple/with_limit_offset_test.go @@ -17,32 +17,36 @@ import ( ) func TestQuerySimpleWithLimit0(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with limit 0", - Request: `query { - Users(limit: 0) { - Name - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Bob", - }, - { - "Name": "John", + testUtils.Request{ + Request: `query { + Users(limit: 0) { + Name + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Bob", + }, + { + "Name": "John", + }, + }, }, }, }, @@ -52,73 +56,85 @@ func TestQuerySimpleWithLimit0(t *testing.T) { } func TestQuerySimpleWithLimit(t *testing.T) { - tests := []testUtils.RequestTestCase{ + tests := []testUtils.TestCase{ { Description: "Simple query with basic limit", - Request: `query { - Users(limit: 1) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Bob", - "Age": int64(32), + testUtils.Request{ + Request: `query { + Users(limit: 1) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Bob", + "Age": int64(32), + }, + }, }, }, }, }, { Description: "Simple query with basic limit, more rows", - Request: `query { - Users(limit: 2) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Carlo", - "Age": int64(55), - }, - { - "Name": "Bob", - "Age": int64(32), + testUtils.Request{ + Request: `query { + Users(limit: 2) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Carlo", + "Age": int64(55), + }, + { + "Name": "Bob", + "Age": int64(32), + }, + }, }, }, }, @@ -131,73 +147,85 @@ func TestQuerySimpleWithLimit(t *testing.T) { } func TestQuerySimpleWithLimitAndOffset(t *testing.T) { - tests := []testUtils.RequestTestCase{ + tests := []testUtils.TestCase{ { Description: "Simple query with basic limit & offset", - Request: `query { - Users(limit: 1, offset: 1) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Age": int64(21), + testUtils.Request{ + Request: `query { + Users(limit: 1, offset: 1) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "Age": int64(21), + }, + }, }, }, }, }, { Description: "Simple query with basic limit & offset, more rows", - Request: `query { - Users(limit: 2, offset: 2) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Age": int64(21), - }, - { - "Name": "Alice", - "Age": int64(19), + testUtils.Request{ + Request: `query { + Users(limit: 2, offset: 2) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "Age": int64(21), + }, + { + "Name": "Alice", + "Age": int64(19), + }, + }, }, }, }, @@ -210,81 +238,95 @@ func TestQuerySimpleWithLimitAndOffset(t *testing.T) { } func TestQuerySimpleWithOffset(t *testing.T) { - tests := []testUtils.RequestTestCase{ + tests := []testUtils.TestCase{ { Description: "Simple query with offset only", - Request: `query { - Users(offset: 1) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Age": int64(21), + testUtils.Request{ + Request: `query { + Users(offset: 1) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "Age": int64(21), + }, + }, }, }, }, }, { Description: "Simple query with offset only, more rows", - Request: `query { - Users(offset: 2) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Melynda", "Age": 30 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Melynda", - "Age": int64(30), - }, - { - "Name": "John", - "Age": int64(21), - }, - { - "Name": "Alice", - "Age": int64(19), + testUtils.Request{ + Request: `query { + Users(offset: 2) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Melynda", + "Age": int64(30), + }, + { + "Name": "John", + "Age": int64(21), + }, + { + "Name": "Alice", + "Age": int64(19), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_operation_alias_test.go b/tests/integration/query/simple/with_operation_alias_test.go index 5a1130c523..f8ee75b402 100644 --- a/tests/integration/query/simple/with_operation_alias_test.go +++ b/tests/integration/query/simple/with_operation_alias_test.go @@ -17,29 +17,31 @@ import ( ) func TestQuerySimpleWithOperationAlias(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with operation alias", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 21 + }`, + }, + testUtils.Request{ + Request: `query { allUsers: Users { _docID Name Age } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 21 - }`, - }, - }, - Results: map[string]any{ - "allUsers": []map[string]any{ - { - "_docID": "bae-d4303725-7db9-53d2-b324-f3ee44020e52", - "Name": "John", - "Age": int64(21), + Results: map[string]any{ + "allUsers": []map[string]any{ + { + "_docID": "bae-d4303725-7db9-53d2-b324-f3ee44020e52", + "Name": "John", + "Age": int64(21), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_order_filter_test.go b/tests/integration/query/simple/with_order_filter_test.go index cbee236ca2..c51ee88bd0 100644 --- a/tests/integration/query/simple/with_order_filter_test.go +++ b/tests/integration/query/simple/with_order_filter_test.go @@ -17,43 +17,51 @@ import ( ) func TestQuerySimpleWithNumericGreaterThanFilterAndNumericOrderDescending(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with order & filter", - Request: `query { - Users(filter: {Age: {_gt: 30}}, order: {Age: DESC}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Carlo", - "Age": int64(55), - }, - { - "Name": "Bob", - "Age": int64(32), + testUtils.Request{ + Request: `query { + Users(filter: {Age: {_gt: 30}}, order: {Age: DESC}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Carlo", + "Age": int64(55), + }, + { + "Name": "Bob", + "Age": int64(32), + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_order_test.go b/tests/integration/query/simple/with_order_test.go index 003b9a0a52..000e3ee391 100644 --- a/tests/integration/query/simple/with_order_test.go +++ b/tests/integration/query/simple/with_order_test.go @@ -17,43 +17,49 @@ import ( ) func TestQuerySimpleWithEmptyOrder(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with empty order", - Request: `query { - Users(order: {}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Carlo", - "Age": int64(55), - }, - { - "Name": "Bob", - "Age": int64(32), - }, - { - "Name": "John", - "Age": int64(21), + testUtils.Request{ + Request: `query { + Users(order: {}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Carlo", + "Age": int64(55), + }, + { + "Name": "Bob", + "Age": int64(32), + }, + { + "Name": "John", + "Age": int64(21), + }, + }, }, }, }, @@ -63,51 +69,59 @@ func TestQuerySimpleWithEmptyOrder(t *testing.T) { } func TestQuerySimpleWithNumericOrderAscending(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic order ASC", - Request: `query { - Users(order: {Age: ASC}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Alice", - "Age": int64(19), - }, - { - "Name": "John", - "Age": int64(21), - }, - { - "Name": "Bob", - "Age": int64(32), - }, - { - "Name": "Carlo", - "Age": int64(55), + testUtils.Request{ + Request: `query { + Users(order: {Age: ASC}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Alice", + "Age": int64(19), + }, + { + "Name": "John", + "Age": int64(21), + }, + { + "Name": "Bob", + "Age": int64(32), + }, + { + "Name": "Carlo", + "Age": int64(55), + }, + }, }, }, }, @@ -117,55 +131,63 @@ func TestQuerySimpleWithNumericOrderAscending(t *testing.T) { } func TestQuerySimpleWithDateTimeOrderAscending(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic order ASC", - Request: `query { - Users(order: {CreatedAt: ASC}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21, "CreatedAt": "2021-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32, "CreatedAt": "2032-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55, "CreatedAt": "2055-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19, "CreatedAt": "2019-07-23T03:46:56-05:00" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Alice", - "Age": int64(19), - }, - { - "Name": "John", - "Age": int64(21), - }, - { - "Name": "Bob", - "Age": int64(32), - }, - { - "Name": "Carlo", - "Age": int64(55), + testUtils.Request{ + Request: `query { + Users(order: {CreatedAt: ASC}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Alice", + "Age": int64(19), + }, + { + "Name": "John", + "Age": int64(21), + }, + { + "Name": "Bob", + "Age": int64(32), + }, + { + "Name": "Carlo", + "Age": int64(55), + }, + }, }, }, }, @@ -175,51 +197,59 @@ func TestQuerySimpleWithDateTimeOrderAscending(t *testing.T) { } func TestQuerySimpleWithNumericOrderDescending(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic order DESC", - Request: `query { - Users(order: {Age: DESC}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19 }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Carlo", - "Age": int64(55), - }, - { - "Name": "Bob", - "Age": int64(32), - }, - { - "Name": "John", - "Age": int64(21), - }, - { - "Name": "Alice", - "Age": int64(19), + testUtils.Request{ + Request: `query { + Users(order: {Age: DESC}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Carlo", + "Age": int64(55), + }, + { + "Name": "Bob", + "Age": int64(32), + }, + { + "Name": "John", + "Age": int64(21), + }, + { + "Name": "Alice", + "Age": int64(19), + }, + }, }, }, }, @@ -229,55 +259,63 @@ func TestQuerySimpleWithNumericOrderDescending(t *testing.T) { } func TestQuerySimpleWithDateTimeOrderDescending(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with basic order DESC", - Request: `query { - Users(order: {CreatedAt: DESC}) { - Name - Age - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21, "CreatedAt": "2021-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 32, "CreatedAt": "2032-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55, "CreatedAt": "2055-07-23T03:46:56-05:00" }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19, "CreatedAt": "2019-07-23T03:46:56-05:00" }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Carlo", - "Age": int64(55), - }, - { - "Name": "Bob", - "Age": int64(32), - }, - { - "Name": "John", - "Age": int64(21), - }, - { - "Name": "Alice", - "Age": int64(19), + testUtils.Request{ + Request: `query { + Users(order: {CreatedAt: DESC}) { + Name + Age + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Carlo", + "Age": int64(55), + }, + { + "Name": "Bob", + "Age": int64(32), + }, + { + "Name": "John", + "Age": int64(21), + }, + { + "Name": "Alice", + "Age": int64(19), + }, + }, }, }, }, @@ -287,60 +325,68 @@ func TestQuerySimpleWithDateTimeOrderDescending(t *testing.T) { } func TestQuerySimpleWithNumericOrderDescendingAndBooleanOrderAscending(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with compound order", - Request: `query { - Users(order: {Age: DESC, Verified: ASC}) { - Name - Age - Verified - } - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 21, "Verified": false }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Carlo", "Age": 55, "Verified": true }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 19, "Verified": false }`, }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "Carlo", - "Age": int64(55), - "Verified": true, - }, - { - "Name": "Bob", - "Age": int64(21), - "Verified": false, - }, - { - "Name": "John", - "Age": int64(21), - "Verified": true, - }, - { - "Name": "Alice", - "Age": int64(19), - "Verified": false, + testUtils.Request{ + Request: `query { + Users(order: {Age: DESC, Verified: ASC}) { + Name + Age + Verified + } + }`, + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "Carlo", + "Age": int64(55), + "Verified": true, + }, + { + "Name": "Bob", + "Age": int64(21), + "Verified": false, + }, + { + "Name": "John", + "Age": int64(21), + "Verified": true, + }, + { + "Name": "Alice", + "Age": int64(19), + "Verified": false, + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_sum_filter_test.go b/tests/integration/query/simple/with_sum_filter_test.go index 1c1515a769..8a947fdb54 100644 --- a/tests/integration/query/simple/with_sum_filter_test.go +++ b/tests/integration/query/simple/with_sum_filter_test.go @@ -17,29 +17,35 @@ import ( ) func TestQuerySimpleWithSumWithFilter(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query, sum with filter", - Request: `query { - _sum(Users: {field: Age, filter: {Age: {_gt: 26}}}) - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 30 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Alice", "Age": 32 }`, }, - }, - Results: map[string]any{ - "_sum": int64(62), + testUtils.Request{ + Request: `query { + _sum(Users: {field: Age, filter: {Age: {_gt: 26}}}) + }`, + Results: map[string]any{ + "_sum": int64(62), + }, + }, }, } diff --git a/tests/integration/query/simple/with_sum_test.go b/tests/integration/query/simple/with_sum_test.go index 34dde00e15..65da7d2ea3 100644 --- a/tests/integration/query/simple/with_sum_test.go +++ b/tests/integration/query/simple/with_sum_test.go @@ -17,37 +17,49 @@ import ( ) func TestQuerySimpleWithSumOnUndefinedObject(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query, sum on undefined object", - Request: `query { + Actions: []any{ + testUtils.Request{ + Request: `query { _sum }`, - ExpectedError: "aggregate must be provided with a property to aggregate", + ExpectedError: "aggregate must be provided with a property to aggregate", + }, + }, } executeTestCase(t, test) } func TestQuerySimpleWithSumOnUndefinedField(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query, sum on undefined field", - Request: `query { + Actions: []any{ + testUtils.Request{ + Request: `query { _sum(Users: {}) }`, - ExpectedError: "Argument \"Users\" has invalid value {}.\nIn field \"field\": Expected \"UsersNumericFieldsArg!\", found null.", + ExpectedError: "Argument \"Users\" has invalid value {}.\nIn field \"field\": Expected \"UsersNumericFieldsArg!\", found null.", + }, + }, } executeTestCase(t, test) } func TestQuerySimpleWithSumOnEmptyCollection(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query, sum on empty", - Request: `query { + Actions: []any{ + testUtils.Request{ + Request: `query { _sum(Users: {field: Age}) }`, - Results: map[string]any{ - "_sum": int64(0), + Results: map[string]any{ + "_sum": int64(0), + }, + }, }, } @@ -55,25 +67,29 @@ func TestQuerySimpleWithSumOnEmptyCollection(t *testing.T) { } func TestQuerySimpleWithSum(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query, sum", - Request: `query { - _sum(Users: {field: Age}) - }`, - Docs: map[int][]string{ - 0: { - `{ + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ "Name": "John", "Age": 21 }`, - `{ + }, + testUtils.CreateDoc{ + Doc: `{ "Name": "Bob", "Age": 30 }`, }, - }, - Results: map[string]any{ - "_sum": int64(51), + testUtils.Request{ + Request: `query { + _sum(Users: {field: Age}) + }`, + Results: map[string]any{ + "_sum": int64(51), + }, + }, }, } diff --git a/tests/integration/query/simple/with_typename_test.go b/tests/integration/query/simple/with_typename_test.go index 8f44ee60c0..8bf44d0fb7 100644 --- a/tests/integration/query/simple/with_typename_test.go +++ b/tests/integration/query/simple/with_typename_test.go @@ -17,26 +17,28 @@ import ( ) func TestQuerySimpleWithTypeName(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with typename", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John" + }`, + }, + testUtils.Request{ + Request: `query { Users { Name __typename } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John" - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "__typename": "Users", + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "__typename": "Users", + }, + }, }, }, }, @@ -46,28 +48,30 @@ func TestQuerySimpleWithTypeName(t *testing.T) { } func TestQuerySimpleWithAliasedTypeName(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Simple query with aliased typename", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John" + }`, + }, + testUtils.Request{ + Request: `query { Users { Name __typename t1: __typename } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John" - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "__typename": "Users", - "t1": "Users", + Results: map[string]any{ + "Users": []map[string]any{ + { + "Name": "John", + "__typename": "Users", + "t1": "Users", + }, + }, }, }, }, diff --git a/tests/integration/query/simple/with_version_test.go b/tests/integration/query/simple/with_version_test.go index aaf2092e61..d0eda9db43 100644 --- a/tests/integration/query/simple/with_version_test.go +++ b/tests/integration/query/simple/with_version_test.go @@ -17,9 +17,17 @@ import ( ) func TestQuerySimpleWithEmbeddedLatestCommit(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Embedded latest commits query within object query", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 21 + }`, + }, + testUtils.Request{ + Request: `query { Users { Name Age @@ -32,30 +40,24 @@ func TestQuerySimpleWithEmbeddedLatestCommit(t *testing.T) { } } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 21 - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Age": int64(21), - "_version": []map[string]any{ + Results: map[string]any{ + "Users": []map[string]any{ { - "cid": "bafyreiby7drdzfsg4wwo7f6vkdqhurbe74s4lhayn3k3226zvkgwjd2fbu", - "links": []map[string]any{ - { - "cid": "bafyreid4sasigytiflrh3rupyevo6wy43b6mlfi4jwkjjwvohgjcd3oscu", - "name": "Age", - }, + "Name": "John", + "Age": int64(21), + "_version": []map[string]any{ { - "cid": "bafyreieg3p2kpyxwiowskvb3pp35nedzawmapjuib7glrvszcgmv6z37fm", - "name": "Name", + "cid": "bafyreiby7drdzfsg4wwo7f6vkdqhurbe74s4lhayn3k3226zvkgwjd2fbu", + "links": []map[string]any{ + { + "cid": "bafyreid4sasigytiflrh3rupyevo6wy43b6mlfi4jwkjjwvohgjcd3oscu", + "name": "Age", + }, + { + "cid": "bafyreieg3p2kpyxwiowskvb3pp35nedzawmapjuib7glrvszcgmv6z37fm", + "name": "Name", + }, + }, }, }, }, @@ -69,9 +71,17 @@ func TestQuerySimpleWithEmbeddedLatestCommit(t *testing.T) { } func TestQuerySimpleWithEmbeddedLatestCommitWithSchemaVersionID(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Embedded commits query within object query with schema version id", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 21 + }`, + }, + testUtils.Request{ + Request: `query { Users { Name _version { @@ -79,21 +89,15 @@ func TestQuerySimpleWithEmbeddedLatestCommitWithSchemaVersionID(t *testing.T) { } } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 21 - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_version": []map[string]any{ + Results: map[string]any{ + "Users": []map[string]any{ { - "schemaVersionId": "bafkreigqmcqzkbg3elpe24vfza4rjle2r6cxu7ihzvg56aov57crhaebry", + "Name": "John", + "_version": []map[string]any{ + { + "schemaVersionId": "bafkreigqmcqzkbg3elpe24vfza4rjle2r6cxu7ihzvg56aov57crhaebry", + }, + }, }, }, }, @@ -107,9 +111,17 @@ func TestQuerySimpleWithEmbeddedLatestCommitWithSchemaVersionID(t *testing.T) { func TestQuerySimpleWithEmbeddedLatestCommitWithDocID(t *testing.T) { const docID = "bae-d4303725-7db9-53d2-b324-f3ee44020e52" - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Embedded commits query within object query with document ID", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 21 + }`, + }, + testUtils.Request{ + Request: `query { Users { Name _docID @@ -118,22 +130,16 @@ func TestQuerySimpleWithEmbeddedLatestCommitWithDocID(t *testing.T) { } } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 21 - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "_docID": docID, - "_version": []map[string]any{ + Results: map[string]any{ + "Users": []map[string]any{ { - "docID": docID, + "Name": "John", + "_docID": docID, + "_version": []map[string]any{ + { + "docID": docID, + }, + }, }, }, }, @@ -145,9 +151,17 @@ func TestQuerySimpleWithEmbeddedLatestCommitWithDocID(t *testing.T) { } func TestQuerySimpleWithMultipleAliasedEmbeddedLatestCommit(t *testing.T) { - test := testUtils.RequestTestCase{ + test := testUtils.TestCase{ Description: "Embedded, aliased, latest commits query within object query", - Request: `query { + Actions: []any{ + testUtils.CreateDoc{ + Doc: `{ + "Name": "John", + "Age": 21 + }`, + }, + testUtils.Request{ + Request: `query { Users { Name Age @@ -163,38 +177,32 @@ func TestQuerySimpleWithMultipleAliasedEmbeddedLatestCommit(t *testing.T) { } } }`, - Docs: map[int][]string{ - 0: { - `{ - "Name": "John", - "Age": 21 - }`, - }, - }, - Results: map[string]any{ - "Users": []map[string]any{ - { - "Name": "John", - "Age": int64(21), - "_version": []map[string]any{ + Results: map[string]any{ + "Users": []map[string]any{ { - "cid": "bafyreiby7drdzfsg4wwo7f6vkdqhurbe74s4lhayn3k3226zvkgwjd2fbu", - "L1": []map[string]any{ - { - "cid": "bafyreid4sasigytiflrh3rupyevo6wy43b6mlfi4jwkjjwvohgjcd3oscu", - "name": "Age", - }, - { - "cid": "bafyreieg3p2kpyxwiowskvb3pp35nedzawmapjuib7glrvszcgmv6z37fm", - "name": "Name", - }, - }, - "L2": []map[string]any{ - { - "name": "Age", - }, + "Name": "John", + "Age": int64(21), + "_version": []map[string]any{ { - "name": "Name", + "cid": "bafyreiby7drdzfsg4wwo7f6vkdqhurbe74s4lhayn3k3226zvkgwjd2fbu", + "L1": []map[string]any{ + { + "cid": "bafyreid4sasigytiflrh3rupyevo6wy43b6mlfi4jwkjjwvohgjcd3oscu", + "name": "Age", + }, + { + "cid": "bafyreieg3p2kpyxwiowskvb3pp35nedzawmapjuib7glrvszcgmv6z37fm", + "name": "Name", + }, + }, + "L2": []map[string]any{ + { + "name": "Age", + }, + { + "name": "Name", + }, + }, }, }, }, diff --git a/tests/integration/utils.go b/tests/integration/utils.go index 14f20b494d..5e4600ef7c 100644 --- a/tests/integration/utils.go +++ b/tests/integration/utils.go @@ -11,63 +11,2245 @@ package tests import ( + "context" + "encoding/json" + "fmt" + "os" + "reflect" + "strconv" + "strings" "testing" + "time" + + "github.com/bxcodec/faker/support/slice" + "github.com/fxamacker/cbor/v2" + "github.com/sourcenetwork/corelog" + "github.com/sourcenetwork/immutable" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/sourcenetwork/defradb/client" + "github.com/sourcenetwork/defradb/client/request" + "github.com/sourcenetwork/defradb/crypto" + "github.com/sourcenetwork/defradb/datastore" + "github.com/sourcenetwork/defradb/errors" + "github.com/sourcenetwork/defradb/internal/db" + "github.com/sourcenetwork/defradb/internal/encryption" + "github.com/sourcenetwork/defradb/internal/request/graphql" + "github.com/sourcenetwork/defradb/net" + changeDetector "github.com/sourcenetwork/defradb/tests/change_detector" + "github.com/sourcenetwork/defradb/tests/clients" + "github.com/sourcenetwork/defradb/tests/gen" + "github.com/sourcenetwork/defradb/tests/predefined" +) + +const ( + mutationTypeEnvName = "DEFRA_MUTATION_TYPE" + skipNetworkTestsEnvName = "DEFRA_SKIP_NETWORK_TESTS" +) + +// The MutationType that tests will run using. +// +// For example if set to [CollectionSaveMutationType], all supporting +// actions (such as [UpdateDoc]) will execute via [Collection.Save]. +// +// Defaults to CollectionSaveMutationType. +type MutationType string + +const ( + // CollectionSaveMutationType will cause all supporting actions + // to run their mutations via [Collection.Save]. + CollectionSaveMutationType MutationType = "collection-save" + + // CollectionNamedMutationType will cause all supporting actions + // to run their mutations via their corresponding named [Collection] + // call. + // + // For example, CreateDoc will call [Collection.Create], and + // UpdateDoc will call [Collection.Update]. + CollectionNamedMutationType MutationType = "collection-named" + + // GQLRequestMutationType will cause all supporting actions to + // run their mutations using GQL requests, typically these will + // include a `id` parameter to target the specified document. + GQLRequestMutationType MutationType = "gql" +) + +var ( + log = corelog.NewLogger("tests.integration") + mutationType MutationType + // skipNetworkTests will skip any tests that involve network actions + skipNetworkTests = false ) -type RequestTestCase struct { - Description string - Request string +const ( + // subscriptionTimeout is the maximum time to wait for subscription results to be returned. + subscriptionTimeout = 1 * time.Second + // Instantiating lenses is expensive, and our tests do not benefit from a large number of them, + // so we explicitly set it to a low value. + lensPoolSize = 2 +) + +const testJSONFile = "/test.json" + +func init() { + // We use environment variables instead of flags `go test ./...` throws for all packages + // that don't have the flag defined + if value, ok := os.LookupEnv(mutationTypeEnvName); ok { + mutationType = MutationType(value) + } else { + // Default to testing mutations via Collection.Save - it should be simpler and + // faster. We assume this is desirable when not explicitly testing any particular + // mutation type. + mutationType = CollectionSaveMutationType + } + if value, ok := os.LookupEnv(skipNetworkTestsEnvName); ok { + skipNetworkTests, _ = strconv.ParseBool(value) + } +} + +// AssertPanic asserts that the code inside the specified PanicTestFunc panics. +// +// This function is not supported by either the change detector, or the http-client. +// Calling this within either of them will result in the test being skipped. +// +// Usage: AssertPanic(t, func() { executeTestCase(t, test) }) +func AssertPanic(t *testing.T, f assert.PanicTestFunc) bool { + if changeDetector.Enabled { + // The `assert.Panics` call will falsely fail if this test is executed during + // a detect changes test run. + t.Skip("Assert panic with the change detector is not currently supported.") + } + + if httpClient || cliClient { + // The http / cli client will return an error instead of panicing at the moment. + t.Skip("Assert panic with the http client is not currently supported.") + } + + return assert.Panics(t, f, "expected a panic, but none found.") +} + +// ExecuteTestCase executes the given TestCase against the configured database +// instances. +// +// Will also attempt to detect incompatible changes in the persisted data if +// configured to do so (the CI will do so, but disabled by default as it is slow). +func ExecuteTestCase( + t testing.TB, + testCase TestCase, +) { + flattenActions(&testCase) + collectionNames := getCollectionNames(testCase) + changeDetector.PreTestChecks(t, collectionNames) + skipIfMutationTypeUnsupported(t, testCase.SupportedMutationTypes) + skipIfACPTypeUnsupported(t, testCase.SupportedACPTypes) + skipIfNetworkTest(t, testCase.Actions) + + var clients []ClientType + if httpClient { + clients = append(clients, HTTPClientType) + } + if goClient { + clients = append(clients, GoClientType) + } + if cliClient { + clients = append(clients, CLIClientType) + } + + var databases []DatabaseType + if badgerInMemory { + databases = append(databases, badgerIMType) + } + if badgerFile { + databases = append(databases, badgerFileType) + } + if inMemoryStore { + databases = append(databases, defraIMType) + } + + // Assert that these are not empty to protect against accidental mis-configurations, + // otherwise an empty set would silently pass all the tests. + require.NotEmpty(t, databases) + require.NotEmpty(t, clients) + + clients = skipIfClientTypeUnsupported(t, clients, testCase.SupportedClientTypes) + + ctx := context.Background() + for _, ct := range clients { + for _, dbt := range databases { + executeTestCase(ctx, t, collectionNames, testCase, dbt, ct) + } + } +} + +func executeTestCase( + ctx context.Context, + t testing.TB, + collectionNames []string, + testCase TestCase, + dbt DatabaseType, + clientType ClientType, +) { + log.InfoContext( + ctx, + testCase.Description, + corelog.Any("database", dbt), + corelog.Any("client", clientType), + corelog.Any("mutationType", mutationType), + corelog.String("databaseDir", databaseDir), + corelog.Bool("badgerEncryption", badgerEncryption), + corelog.Bool("skipNetworkTests", skipNetworkTests), + corelog.Bool("changeDetector.Enabled", changeDetector.Enabled), + corelog.Bool("changeDetector.SetupOnly", changeDetector.SetupOnly), + corelog.String("changeDetector.SourceBranch", changeDetector.SourceBranch), + corelog.String("changeDetector.TargetBranch", changeDetector.TargetBranch), + corelog.String("changeDetector.Repository", changeDetector.Repository), + ) + + startActionIndex, endActionIndex := getActionRange(t, testCase) + + s := newState(ctx, t, testCase, dbt, clientType, collectionNames) + setStartingNodes(s) + + // It is very important that the databases are always closed, otherwise resources will leak + // as tests run. This is particularly important for file based datastores. + defer closeNodes(s) + + // Documents and Collections may already exist in the database if actions have been split + // by the change detector so we should fetch them here at the start too (if they exist). + // collections are by node (index), as they are specific to nodes. + refreshCollections(s) + refreshDocuments(s, startActionIndex) + refreshIndexes(s) + + for i := startActionIndex; i <= endActionIndex; i++ { + performAction(s, i, testCase.Actions[i]) + } + + // Notify any active subscriptions that all requests have been sent. + close(s.allActionsDone) + + for _, resultsChan := range s.subscriptionResultsChans { + select { + case subscriptionAssert := <-resultsChan: + // We want to assert back in the main thread so failures get recorded properly + subscriptionAssert() + + // a safety in case the stream hangs - we don't want the tests to run forever. + case <-time.After(subscriptionTimeout): + assert.Fail(t, "timeout occurred while waiting for data stream", testCase.Description) + } + } +} + +func performAction( + s *state, + actionIndex int, + act any, +) { + switch action := act.(type) { + case ConfigureNode: + configureNode(s, action) + + case Restart: + restartNodes(s) + + case ConnectPeers: + connectPeers(s, action) + + case ConfigureReplicator: + configureReplicator(s, action) + + case DeleteReplicator: + deleteReplicator(s, action) + + case SubscribeToCollection: + subscribeToCollection(s, action) + + case UnsubscribeToCollection: + unsubscribeToCollection(s, action) + + case GetAllP2PCollections: + getAllP2PCollections(s, action) + + case SchemaUpdate: + updateSchema(s, action) + + case SchemaPatch: + patchSchema(s, action) + + case PatchCollection: + patchCollection(s, action) + + case GetSchema: + getSchema(s, action) + + case GetCollections: + getCollections(s, action) + + case SetActiveSchemaVersion: + setActiveSchemaVersion(s, action) + + case CreateView: + createView(s, action) + + case ConfigureMigration: + configureMigration(s, action) + + case AddPolicy: + addPolicyACP(s, action) + + case CreateDoc: + createDoc(s, action) + + case DeleteDoc: + deleteDoc(s, action) + + case UpdateDoc: + updateDoc(s, action) + + case UpdateWithFilter: + updateWithFilter(s, action) + + case CreateIndex: + createIndex(s, action) + + case DropIndex: + dropIndex(s, action) + + case GetIndexes: + getIndexes(s, action) + + case BackupExport: + backupExport(s, action) + + case BackupImport: + backupImport(s, action) + + case TransactionCommit: + commitTransaction(s, action) + + case SubscriptionRequest: + executeSubscriptionRequest(s, action) + + case Request: + executeRequest(s, action) + + case ExplainRequest: + executeExplainRequest(s, action) + + case IntrospectionRequest: + assertIntrospectionResults(s, action) + + case ClientIntrospectionRequest: + assertClientIntrospectionResults(s, action) + + case WaitForSync: + waitForSync(s, action) + + case Benchmark: + benchmarkAction(s, actionIndex, action) + + case GenerateDocs: + generateDocs(s, action) + + case CreatePredefinedDocs: + generatePredefinedDocs(s, action) + + case SetupComplete: + // no-op, just continue. + + default: + s.t.Fatalf("Unknown action type %T", action) + } +} + +func createGenerateDocs(s *state, docs []gen.GeneratedDoc, nodeID immutable.Option[int]) { + nameToInd := make(map[string]int) + for i, name := range s.collectionNames { + nameToInd[name] = i + } + for _, doc := range docs { + docJSON, err := doc.Doc.String() + if err != nil { + s.t.Fatalf("Failed to generate docs %s", err) + } + createDoc(s, CreateDoc{CollectionID: nameToInd[doc.Col.Description.Name.Value()], Doc: docJSON, NodeID: nodeID}) + } +} + +func generateDocs(s *state, action GenerateDocs) { + collections := getNodeCollections(action.NodeID, s.collections) + defs := make([]client.CollectionDefinition, 0, len(collections[0])) + for _, col := range collections[0] { + if len(action.ForCollections) == 0 || slice.Contains(action.ForCollections, col.Name().Value()) { + defs = append(defs, col.Definition()) + } + } + docs, err := gen.AutoGenerate(defs, action.Options...) + if err != nil { + s.t.Fatalf("Failed to generate docs %s", err) + } + createGenerateDocs(s, docs, action.NodeID) +} + +func generatePredefinedDocs(s *state, action CreatePredefinedDocs) { + collections := getNodeCollections(action.NodeID, s.collections) + defs := make([]client.CollectionDefinition, 0, len(collections[0])) + for _, col := range collections[0] { + defs = append(defs, col.Definition()) + } + docs, err := predefined.Create(defs, action.Docs) + if err != nil { + s.t.Fatalf("Failed to generate docs %s", err) + } + createGenerateDocs(s, docs, action.NodeID) +} + +func benchmarkAction( + s *state, + actionIndex int, + bench Benchmark, +) { + if s.dbt == defraIMType { + // Benchmarking makes no sense for test in-memory storage + return + } + if len(bench.FocusClients) > 0 { + isFound := false + for _, clientType := range bench.FocusClients { + if s.clientType == clientType { + isFound = true + break + } + } + if !isFound { + return + } + } + + runBench := func(benchCase any) time.Duration { + startTime := time.Now() + for i := 0; i < bench.Reps; i++ { + performAction(s, actionIndex, benchCase) + } + return time.Since(startTime) + } + + s.isBench = true + defer func() { s.isBench = false }() + + baseElapsedTime := runBench(bench.BaseCase) + optimizedElapsedTime := runBench(bench.OptimizedCase) + + factoredBaseTime := int64(float64(baseElapsedTime) / bench.Factor) + assert.Greater(s.t, factoredBaseTime, optimizedElapsedTime, + "Optimized case should be faster at least by factor of %.2f than the base case. Base: %d, Optimized: %d (μs)", + bench.Factor, optimizedElapsedTime.Microseconds(), baseElapsedTime.Microseconds()) +} + +// getCollectionNames gets an ordered, unique set of collection names across all nodes +// from the action set within the given test case. +// +// It preserves the order in which they are declared, and shares indexes across all nodes, so +// if a second node adds a collection of a name that was previously declared in another node +// the new node will respect the index originally assigned. This allows collections to be +// referenced across multiple nodes by a consistent, predictable index - allowing a single +// action to target the same collection across multiple nodes. +// +// WARNING: This will not work with schemas ending in `type`, e.g. `user_type` +func getCollectionNames(testCase TestCase) []string { + nextIndex := 0 + collectionIndexByName := map[string]int{} + + for _, a := range testCase.Actions { + switch action := a.(type) { + case SchemaUpdate: + if action.ExpectedError != "" { + // If an error is expected then no collections should result from this action + continue + } + + nextIndex = getCollectionNamesFromSchema(collectionIndexByName, action.Schema, nextIndex) + } + } + + collectionNames := make([]string, len(collectionIndexByName)) + for name, index := range collectionIndexByName { + collectionNames[index] = name + } + + return collectionNames +} + +func getCollectionNamesFromSchema(result map[string]int, schema string, nextIndex int) int { + // WARNING: This will not work with schemas ending in `type`, e.g. `user_type` + splitByType := strings.Split(schema, "type ") + // Skip the first, as that preceeds `type ` if `type ` is present, + // else there are no types. + for i := 1; i < len(splitByType); i++ { + wipSplit := strings.TrimLeft(splitByType[i], " ") + indexOfLastChar := strings.IndexAny(wipSplit, " {") + if indexOfLastChar <= 0 { + // This should never happen + continue + } + + collectionName := wipSplit[:indexOfLastChar] + if _, ok := result[collectionName]; ok { + // Collection name has already been added, possibly via another node + continue + } + + result[collectionName] = nextIndex + nextIndex++ + } + return nextIndex +} + +// closeNodes closes all the given nodes, ensuring that resources are properly released. +func closeNodes( + s *state, +) { + for _, node := range s.nodes { + node.Close() + } +} + +// getNodes gets the set of applicable nodes for the given nodeID. +// +// If nodeID has a value it will return that node only, otherwise all nodes will be returned. +func getNodes(nodeID immutable.Option[int], nodes []clients.Client) []clients.Client { + if !nodeID.HasValue() { + return nodes + } + + return []clients.Client{nodes[nodeID.Value()]} +} + +// getNodeCollections gets the set of applicable collections for the given nodeID. +// +// If nodeID has a value it will return collections for that node only, otherwise all collections across all +// nodes will be returned. +func getNodeCollections(nodeID immutable.Option[int], collections [][]client.Collection) [][]client.Collection { + if !nodeID.HasValue() { + return collections + } + + return [][]client.Collection{collections[nodeID.Value()]} +} + +func calculateLenForFlattenedActions(testCase *TestCase) int { + newLen := 0 + for _, a := range testCase.Actions { + actionGroup := reflect.ValueOf(a) + switch actionGroup.Kind() { + case reflect.Array, reflect.Slice: + newLen += actionGroup.Len() + default: + newLen++ + } + } + return newLen +} + +func flattenActions(testCase *TestCase) { + newLen := calculateLenForFlattenedActions(testCase) + if newLen == len(testCase.Actions) { + return + } + newActions := make([]any, 0, newLen) + + for _, a := range testCase.Actions { + actionGroup := reflect.ValueOf(a) + switch actionGroup.Kind() { + case reflect.Array, reflect.Slice: + for i := 0; i < actionGroup.Len(); i++ { + newActions = append( + newActions, + actionGroup.Index(i).Interface(), + ) + } + default: + newActions = append(newActions, a) + } + } + testCase.Actions = newActions +} + +// getActionRange returns the index of the first action to be run, and the last. +// +// Not all processes will run all actions - if this is a change detector run they +// will be split. +// +// If a SetupComplete action is provided, the actions will be split there, if not +// they will be split at the first non SchemaUpdate/CreateDoc/UpdateDoc action. +func getActionRange(t testing.TB, testCase TestCase) (int, int) { + startIndex := 0 + endIndex := len(testCase.Actions) - 1 + + if !changeDetector.Enabled { + return startIndex, endIndex + } + + setupCompleteIndex := -1 + firstNonSetupIndex := -1 + +ActionLoop: + for i := range testCase.Actions { + switch testCase.Actions[i].(type) { + case SetupComplete: + setupCompleteIndex = i + // We don't care about anything else if this has been explicitly provided + break ActionLoop + + case SchemaUpdate, CreateDoc, UpdateDoc, Restart: + continue + + default: + firstNonSetupIndex = i + break ActionLoop + } + } + + if changeDetector.SetupOnly { + if setupCompleteIndex > -1 { + endIndex = setupCompleteIndex + } else if firstNonSetupIndex > -1 { + // -1 to exclude this index + endIndex = firstNonSetupIndex - 1 + } + } else { + if setupCompleteIndex > -1 { + // +1 to exclude the SetupComplete action + startIndex = setupCompleteIndex + 1 + } else if firstNonSetupIndex > -1 { + // We must not set this to -1 :) + startIndex = firstNonSetupIndex + } else { + // if we don't have any non-mutation actions and the change detector is enabled + // skip this test as we will not gain anything from running (change detector would + // run an idential profile to a normal test run) + t.Skipf("no actions to execute") + } + } + + return startIndex, endIndex +} + +// setStartingNodes adds a set of initial Defra nodes for the test to execute against. +// +// If a node(s) has been explicitly configured via a `ConfigureNode` action then no new +// nodes will be added. +func setStartingNodes( + s *state, +) { + hasExplicitNode := false + for _, action := range s.testCase.Actions { + switch action.(type) { + case ConfigureNode: + hasExplicitNode = true + } + } + + // If nodes have not been explicitly configured via actions, setup a default one. + if !hasExplicitNode { + node, path, err := setupNode(s) + require.Nil(s.t, err) + + c, err := setupClient(s, node) + require.Nil(s.t, err) + + eventState, err := newEventState(c.Events()) + require.NoError(s.t, err) + + s.nodes = append(s.nodes, c) + s.nodeEvents = append(s.nodeEvents, eventState) + s.nodeP2P = append(s.nodeP2P, newP2PState()) + s.dbPaths = append(s.dbPaths, path) + } +} + +func restartNodes( + s *state, +) { + if s.dbt == badgerIMType || s.dbt == defraIMType { + return + } + closeNodes(s) + + // We need to restart the nodes in reverse order, to avoid dial backoff issues. + for i := len(s.nodes) - 1; i >= 0; i-- { + originalPath := databaseDir + databaseDir = s.dbPaths[i] + node, _, err := setupNode(s) + require.Nil(s.t, err) + databaseDir = originalPath + + if len(s.nodeConfigs) == 0 { + // If there are no explicit node configuration actions the node will be + // basic (i.e. no P2P stuff) and can be yielded now. + c, err := setupClient(s, node) + require.NoError(s.t, err) + s.nodes[i] = c + + eventState, err := newEventState(c.Events()) + require.NoError(s.t, err) + s.nodeEvents[i] = eventState + continue + } + + // We need to make sure the node is configured with its old address, otherwise + // a new one may be selected and reconnnection to it will fail. + var addresses []string + for _, addr := range s.nodeAddresses[i].Addrs { + addresses = append(addresses, addr.String()) + } + + nodeOpts := s.nodeConfigs[i] + nodeOpts = append(nodeOpts, net.WithListenAddresses(addresses...)) + + p, err := net.NewPeer(s.ctx, node.DB.Rootstore(), node.DB.Blockstore(), + node.DB.Encstore(), node.DB.Events(), nodeOpts...) + require.NoError(s.t, err) + + if err := p.Start(); err != nil { + p.Close() + require.NoError(s.t, err) + } + node.Peer = p + + c, err := setupClient(s, node) + require.NoError(s.t, err) + s.nodes[i] = c + + eventState, err := newEventState(c.Events()) + require.NoError(s.t, err) + s.nodeEvents[i] = eventState + + waitForNetworkSetupEvents(s, i) + } + + // If the db was restarted we need to refresh the collection definitions as the old instances + // will reference the old (closed) database instances. + refreshCollections(s) + refreshIndexes(s) +} + +// refreshCollections refreshes all the collections of the given names, preserving order. +// +// If a given collection is not present in the database the value at the corresponding +// result-index will be nil. +func refreshCollections( + s *state, +) { + s.collections = make([][]client.Collection, len(s.nodes)) + + for nodeID, node := range s.nodes { + s.collections[nodeID] = make([]client.Collection, len(s.collectionNames)) + allCollections, err := node.GetCollections(s.ctx, client.CollectionFetchOptions{}) + require.Nil(s.t, err) + + for i, collectionName := range s.collectionNames { + for _, collection := range allCollections { + if collection.Name().Value() == collectionName { + s.collections[nodeID][i] = collection + break + } + } + } + } +} + +// configureNode configures and starts a new Defra node using the provided configuration. +// +// It returns the new node, and its peer address. Any errors generated during configuration +// will result in a test failure. +func configureNode( + s *state, + action ConfigureNode, +) { + if changeDetector.Enabled { + // We do not yet support the change detector for tests running across multiple nodes. + s.t.SkipNow() + return + } + + node, path, err := setupNode(s) //disable change dector, or allow it? + require.NoError(s.t, err) + + privateKey, err := crypto.GenerateEd25519() + require.NoError(s.t, err) + + nodeOpts := action() + nodeOpts = append(nodeOpts, net.WithPrivateKey(privateKey)) + + p, err := net.NewPeer(s.ctx, node.DB.Rootstore(), node.DB.Blockstore(), node.DB.Encstore(), + node.DB.Events(), nodeOpts...) + require.NoError(s.t, err) + + log.InfoContext(s.ctx, "Starting P2P node", corelog.Any("P2P address", p.PeerInfo())) + if err := p.Start(); err != nil { + p.Close() + require.NoError(s.t, err) + } + + s.nodeAddresses = append(s.nodeAddresses, p.PeerInfo()) + s.nodeConfigs = append(s.nodeConfigs, nodeOpts) + + node.Peer = p + + c, err := setupClient(s, node) + require.NoError(s.t, err) + + eventState, err := newEventState(c.Events()) + require.NoError(s.t, err) + + s.nodes = append(s.nodes, c) + s.nodeEvents = append(s.nodeEvents, eventState) + s.nodeP2P = append(s.nodeP2P, newP2PState()) + s.dbPaths = append(s.dbPaths, path) +} + +func refreshDocuments( + s *state, + startActionIndex int, +) { + if len(s.collections) == 0 { + // This should only be possible at the moment for P2P testing, for which the + // change detector is currently disabled. We'll likely need some fancier logic + // here if/when we wish to enable it. + return + } + + // For now just do the initial setup using the collections on the first node, + // this may need to become more involved at a later date depending on testing + // requirements. + s.docIDs = make([][]client.DocID, len(s.collections[0])) + + for i := range s.collections[0] { + s.docIDs[i] = []client.DocID{} + } + + for i := 0; i < startActionIndex; i++ { + // We need to add the existing documents in the order in which the test case lists them + // otherwise they cannot be referenced correctly by other actions. + switch action := s.testCase.Actions[i].(type) { + case CreateDoc: + // Just use the collection from the first relevant node, as all will be the same for this + // purpose. + collection := getNodeCollections(action.NodeID, s.collections)[0][action.CollectionID] + + if action.DocMap != nil { + substituteRelations(s, action) + } + docs, err := parseCreateDocs(action, collection) + if err != nil { + // If an err has been returned, ignore it - it may be expected and if not + // the test will fail later anyway + continue + } + + for _, doc := range docs { + s.docIDs[action.CollectionID] = append(s.docIDs[action.CollectionID], doc.ID()) + } + } + } +} + +func refreshIndexes( + s *state, +) { + if len(s.collections) == 0 { + return + } + + s.indexes = make([][][]client.IndexDescription, len(s.collections)) + + for i, nodeCols := range s.collections { + s.indexes[i] = make([][]client.IndexDescription, len(nodeCols)) + + for j, col := range nodeCols { + if col == nil { + continue + } + colIndexes, err := col.GetIndexes(s.ctx) + if err != nil { + continue + } + + s.indexes[i][j] = colIndexes + } + } +} + +func getIndexes( + s *state, + action GetIndexes, +) { + if len(s.collections) == 0 { + return + } + + var expectedErrorRaised bool + actionNodes := getNodes(action.NodeID, s.nodes) + for nodeID, collections := range getNodeCollections(action.NodeID, s.collections) { + err := withRetry( + actionNodes, + nodeID, + func() error { + actualIndexes, err := collections[action.CollectionID].GetIndexes(s.ctx) + if err != nil { + return err + } + + assertIndexesListsEqual(action.ExpectedIndexes, + actualIndexes, s.t, s.testCase.Description) + + return nil + }, + ) + expectedErrorRaised = expectedErrorRaised || + AssertError(s.t, s.testCase.Description, err, action.ExpectedError) + } + + assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) +} + +func assertIndexesListsEqual( + expectedIndexes []client.IndexDescription, + actualIndexes []client.IndexDescription, + t testing.TB, + testDescription string, +) { + toNames := func(indexes []client.IndexDescription) []string { + names := make([]string, len(indexes)) + for i, index := range indexes { + names[i] = index.Name + } + return names + } + + require.ElementsMatch(t, toNames(expectedIndexes), toNames(actualIndexes), testDescription) + + toMap := func(indexes []client.IndexDescription) map[string]client.IndexDescription { + resultMap := map[string]client.IndexDescription{} + for _, index := range indexes { + resultMap[index.Name] = index + } + return resultMap + } + + expectedMap := toMap(expectedIndexes) + actualMap := toMap(actualIndexes) + for key := range expectedMap { + assertIndexesEqual(expectedMap[key], actualMap[key], t, testDescription) + } +} + +func assertIndexesEqual(expectedIndex, actualIndex client.IndexDescription, + t testing.TB, + testDescription string, +) { + assert.Equal(t, expectedIndex.Name, actualIndex.Name, testDescription) + assert.Equal(t, expectedIndex.ID, actualIndex.ID, testDescription) + + toNames := func(fields []client.IndexedFieldDescription) []string { + names := make([]string, len(fields)) + for i, field := range fields { + names[i] = field.Name + } + return names + } + + require.ElementsMatch(t, toNames(expectedIndex.Fields), toNames(actualIndex.Fields), testDescription) + + toMap := func(fields []client.IndexedFieldDescription) map[string]client.IndexedFieldDescription { + resultMap := map[string]client.IndexedFieldDescription{} + for _, field := range fields { + resultMap[field.Name] = field + } + return resultMap + } + + expectedMap := toMap(expectedIndex.Fields) + actualMap := toMap(actualIndex.Fields) + for key := range expectedMap { + assert.Equal(t, expectedMap[key], actualMap[key], testDescription) + } +} + +// updateSchema updates the schema using the given details. +func updateSchema( + s *state, + action SchemaUpdate, +) { + for _, node := range getNodes(action.NodeID, s.nodes) { + results, err := node.AddSchema(s.ctx, action.Schema) + expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError) + + assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) + + if action.ExpectedResults != nil { + assertCollectionDescriptions(s, action.ExpectedResults, results) + } + } + + // If the schema was updated we need to refresh the collection definitions. + refreshCollections(s) + refreshIndexes(s) +} + +func patchSchema( + s *state, + action SchemaPatch, +) { + for _, node := range getNodes(action.NodeID, s.nodes) { + var setAsDefaultVersion bool + if action.SetAsDefaultVersion.HasValue() { + setAsDefaultVersion = action.SetAsDefaultVersion.Value() + } else { + setAsDefaultVersion = true + } + + err := node.PatchSchema(s.ctx, action.Patch, action.Lens, setAsDefaultVersion) + expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError) + + assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) + } + + // If the schema was updated we need to refresh the collection definitions. + refreshCollections(s) + refreshIndexes(s) +} + +func patchCollection( + s *state, + action PatchCollection, +) { + for _, node := range getNodes(action.NodeID, s.nodes) { + err := node.PatchCollection(s.ctx, action.Patch) + expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError) + + assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) + } + + // If the schema was updated we need to refresh the collection definitions. + refreshCollections(s) + refreshIndexes(s) +} + +func getSchema( + s *state, + action GetSchema, +) { + for _, node := range getNodes(action.NodeID, s.nodes) { + var results []client.SchemaDescription + var err error + switch { + case action.VersionID.HasValue(): + result, e := node.GetSchemaByVersionID(s.ctx, action.VersionID.Value()) + err = e + results = []client.SchemaDescription{result} + default: + results, err = node.GetSchemas( + s.ctx, + client.SchemaFetchOptions{ + Root: action.Root, + Name: action.Name, + }, + ) + } + + expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError) + assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) + + if !expectedErrorRaised { + require.Equal(s.t, action.ExpectedResults, results) + } + } +} + +func getCollections( + s *state, + action GetCollections, +) { + for _, node := range getNodes(action.NodeID, s.nodes) { + txn := getTransaction(s, node, action.TransactionID, "") + ctx := db.SetContextTxn(s.ctx, txn) + results, err := node.GetCollections(ctx, action.FilterOptions) + resultDescriptions := make([]client.CollectionDescription, len(results)) + for i, col := range results { + resultDescriptions[i] = col.Description() + } + + expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError) + assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) + + if !expectedErrorRaised { + assertCollectionDescriptions(s, action.ExpectedResults, resultDescriptions) + } + } +} + +func setActiveSchemaVersion( + s *state, + action SetActiveSchemaVersion, +) { + for _, node := range getNodes(action.NodeID, s.nodes) { + err := node.SetActiveSchemaVersion(s.ctx, action.SchemaVersionID) + expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError) + + assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) + } + + refreshCollections(s) + refreshIndexes(s) +} + +func createView( + s *state, + action CreateView, +) { + for _, node := range getNodes(action.NodeID, s.nodes) { + _, err := node.AddView(s.ctx, action.Query, action.SDL, action.Transform) + expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError) + + assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) + } +} + +// createDoc creates a document using the chosen [mutationType] and caches it in the +// test state object. +func createDoc( + s *state, + action CreateDoc, +) { + if action.DocMap != nil { + substituteRelations(s, action) + } + + var mutation func(*state, CreateDoc, client.DB, int, client.Collection) ([]client.DocID, error) + switch mutationType { + case CollectionSaveMutationType: + mutation = createDocViaColSave + case CollectionNamedMutationType: + mutation = createDocViaColCreate + case GQLRequestMutationType: + mutation = createDocViaGQL + default: + s.t.Fatalf("invalid mutationType: %v", mutationType) + } + + var expectedErrorRaised bool + var docIDs []client.DocID + actionNodes := getNodes(action.NodeID, s.nodes) + for nodeID, collections := range getNodeCollections(action.NodeID, s.collections) { + err := withRetry( + actionNodes, + nodeID, + func() error { + var err error + docIDs, err = mutation(s, action, actionNodes[nodeID], nodeID, collections[action.CollectionID]) + return err + }, + ) + expectedErrorRaised = AssertError(s.t, s.testCase.Description, err, action.ExpectedError) + } + + assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) + + if action.CollectionID >= len(s.docIDs) { + // Expand the slice if required, so that the document can be accessed by collection index + s.docIDs = append(s.docIDs, make([][]client.DocID, action.CollectionID-len(s.docIDs)+1)...) + } + s.docIDs[action.CollectionID] = append(s.docIDs[action.CollectionID], docIDs...) + + if action.ExpectedError == "" { + waitForUpdateEvents(s, action.NodeID, getEventsForCreateDoc(s, action)) + } +} + +func createDocViaColSave( + s *state, + action CreateDoc, + node client.DB, + nodeIndex int, + collection client.Collection, +) ([]client.DocID, error) { + docs, err := parseCreateDocs(action, collection) + if err != nil { + return nil, err + } + + txn := getTransaction(s, node, immutable.None[int](), action.ExpectedError) + ctx := makeContextForDocCreate(s, db.SetContextTxn(s.ctx, txn), nodeIndex, &action) + + docIDs := make([]client.DocID, len(docs)) + for i, doc := range docs { + err := collection.Save(ctx, doc) + if err != nil { + return nil, err + } + docIDs[i] = doc.ID() + } + return docIDs, nil +} + +func makeContextForDocCreate(s *state, ctx context.Context, nodeIndex int, action *CreateDoc) context.Context { + identity := getIdentity(s, nodeIndex, action.Identity) + ctx = db.SetContextIdentity(ctx, identity) + ctx = encryption.SetContextConfigFromParams(ctx, action.IsDocEncrypted, action.EncryptedFields) + return ctx +} + +func createDocViaColCreate( + s *state, + action CreateDoc, + node client.DB, + nodeIndex int, + collection client.Collection, +) ([]client.DocID, error) { + docs, err := parseCreateDocs(action, collection) + if err != nil { + return nil, err + } + + txn := getTransaction(s, node, immutable.None[int](), action.ExpectedError) + ctx := makeContextForDocCreate(s, db.SetContextTxn(s.ctx, txn), nodeIndex, &action) + + switch { + case len(docs) > 1: + err := collection.CreateMany(ctx, docs) + if err != nil { + return nil, err + } + + default: + err := collection.Create(ctx, docs[0]) + if err != nil { + return nil, err + } + } + + docIDs := make([]client.DocID, len(docs)) + for i, doc := range docs { + docIDs[i] = doc.ID() + } + return docIDs, nil +} + +func createDocViaGQL( + s *state, + action CreateDoc, + node client.DB, + nodeIndex int, + collection client.Collection, +) ([]client.DocID, error) { + var input string + + paramName := request.Input + + var err error + if action.DocMap != nil { + input, err = valueToGQL(action.DocMap) + } else if client.IsJSONArray([]byte(action.Doc)) { + var docMaps []map[string]any + err = json.Unmarshal([]byte(action.Doc), &docMaps) + require.NoError(s.t, err) + paramName = request.Inputs + input, err = arrayToGQL(docMaps) + } else { + input, err = jsonToGQL(action.Doc) + } + require.NoError(s.t, err) + + params := paramName + ": " + input + + if action.IsDocEncrypted { + params = params + ", " + request.EncryptDocArgName + ": true" + } + if len(action.EncryptedFields) > 0 { + params = params + ", " + request.EncryptFieldsArgName + ": [" + + strings.Join(action.EncryptedFields, ", ") + "]" + } + + key := fmt.Sprintf("create_%s", collection.Name().Value()) + req := fmt.Sprintf(`mutation { %s(%s) { _docID } }`, key, params) + + txn := getTransaction(s, node, immutable.None[int](), action.ExpectedError) + ctx := db.SetContextIdentity(db.SetContextTxn(s.ctx, txn), getIdentity(s, nodeIndex, action.Identity)) - // docs is a map from Collection Index, to a list - // of docs in stringified JSON format - Docs map[int][]string + result := node.ExecRequest(ctx, req) + if len(result.GQL.Errors) > 0 { + return nil, result.GQL.Errors[0] + } + + resultData := result.GQL.Data.(map[string]any) + resultDocs := ConvertToArrayOfMaps(s.t, resultData[key]) - Results map[string]any + docIDs := make([]client.DocID, len(resultDocs)) + for i, docMap := range resultDocs { + docIDString := docMap[request.DocIDFieldName].(string) + docID, err := client.NewDocIDFromString(docIDString) + require.NoError(s.t, err) + docIDs[i] = docID + } - // The expected content of an expected error - ExpectedError string + return docIDs, nil } -func ExecuteRequestTestCase( - t *testing.T, - schema string, - collectionNames []string, - test RequestTestCase, +// substituteRelations scans the fields defined in [action.DocMap], if any are of type [DocIndex] +// it will substitute the [DocIndex] for the the corresponding document ID found in the state. +// +// If a document at that index is not found it will panic. +func substituteRelations( + s *state, + action CreateDoc, +) { + for k, v := range action.DocMap { + index, isIndex := v.(DocIndex) + if !isIndex { + continue + } + + docID := s.docIDs[index.CollectionIndex][index.Index] + action.DocMap[k] = docID.String() + } +} + +// deleteDoc deletes a document using the collection api and caches it in the +// given documents slice. +func deleteDoc( + s *state, + action DeleteDoc, +) { + docID := s.docIDs[action.CollectionID][action.DocID] + + var expectedErrorRaised bool + actionNodes := getNodes(action.NodeID, s.nodes) + for nodeID, collections := range getNodeCollections(action.NodeID, s.collections) { + identity := getIdentity(s, nodeID, action.Identity) + ctx := db.SetContextIdentity(s.ctx, identity) + + err := withRetry( + actionNodes, + nodeID, + func() error { + _, err := collections[action.CollectionID].Delete(ctx, docID) + return err + }, + ) + expectedErrorRaised = AssertError(s.t, s.testCase.Description, err, action.ExpectedError) + } + + assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) + + if action.ExpectedError == "" { + docIDs := map[string]struct{}{ + docID.String(): {}, + } + waitForUpdateEvents(s, action.NodeID, docIDs) + } +} + +// updateDoc updates a document using the chosen [mutationType]. +func updateDoc( + s *state, + action UpdateDoc, ) { - actions := []any{ - SchemaUpdate{ - Schema: schema, - }, + var mutation func(*state, UpdateDoc, client.DB, int, client.Collection) error + switch mutationType { + case CollectionSaveMutationType: + mutation = updateDocViaColSave + case CollectionNamedMutationType: + mutation = updateDocViaColUpdate + case GQLRequestMutationType: + mutation = updateDocViaGQL + default: + s.t.Fatalf("invalid mutationType: %v", mutationType) + } + + var expectedErrorRaised bool + actionNodes := getNodes(action.NodeID, s.nodes) + for nodeID, collections := range getNodeCollections(action.NodeID, s.collections) { + err := withRetry( + actionNodes, + nodeID, + func() error { + return mutation(s, action, actionNodes[nodeID], nodeID, collections[action.CollectionID]) + }, + ) + expectedErrorRaised = AssertError(s.t, s.testCase.Description, err, action.ExpectedError) + } + + assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) + + if action.ExpectedError == "" && !action.SkipLocalUpdateEvent { + waitForUpdateEvents(s, action.NodeID, getEventsForUpdateDoc(s, action)) + } +} + +func updateDocViaColSave( + s *state, + action UpdateDoc, + node client.DB, + nodeIndex int, + collection client.Collection, +) error { + identity := getIdentity(s, nodeIndex, action.Identity) + ctx := db.SetContextIdentity(s.ctx, identity) + + doc, err := collection.Get(ctx, s.docIDs[action.CollectionID][action.DocID], true) + if err != nil { + return err + } + err = doc.SetWithJSON([]byte(action.Doc)) + if err != nil { + return err + } + return collection.Save(ctx, doc) +} + +func updateDocViaColUpdate( + s *state, + action UpdateDoc, + node client.DB, + nodeIndex int, + collection client.Collection, +) error { + identity := getIdentity(s, nodeIndex, action.Identity) + ctx := db.SetContextIdentity(s.ctx, identity) + + doc, err := collection.Get(ctx, s.docIDs[action.CollectionID][action.DocID], true) + if err != nil { + return err + } + err = doc.SetWithJSON([]byte(action.Doc)) + if err != nil { + return err + } + return collection.Update(ctx, doc) +} + +func updateDocViaGQL( + s *state, + action UpdateDoc, + node client.DB, + nodeIndex int, + collection client.Collection, +) error { + docID := s.docIDs[action.CollectionID][action.DocID] + + input, err := jsonToGQL(action.Doc) + require.NoError(s.t, err) + + request := fmt.Sprintf( + `mutation { + update_%s(docID: "%s", input: %s) { + _docID + } + }`, + collection.Name().Value(), + docID.String(), + input, + ) + + identity := getIdentity(s, nodeIndex, action.Identity) + ctx := db.SetContextIdentity(s.ctx, identity) + + result := node.ExecRequest(ctx, request) + if len(result.GQL.Errors) > 0 { + return result.GQL.Errors[0] } + return nil +} + +// updateWithFilter updates the set of matched documents. +func updateWithFilter(s *state, action UpdateWithFilter) { + var res *client.UpdateResult + var expectedErrorRaised bool + actionNodes := getNodes(action.NodeID, s.nodes) + for nodeID, collections := range getNodeCollections(action.NodeID, s.collections) { + identity := getIdentity(s, nodeID, action.Identity) + ctx := db.SetContextIdentity(s.ctx, identity) + + err := withRetry( + actionNodes, + nodeID, + func() error { + var err error + res, err = collections[action.CollectionID].UpdateWithFilter(ctx, action.Filter, action.Updater) + return err + }, + ) + expectedErrorRaised = AssertError(s.t, s.testCase.Description, err, action.ExpectedError) + } + + assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) + + if action.ExpectedError == "" && !action.SkipLocalUpdateEvent { + waitForUpdateEvents(s, action.NodeID, getEventsForUpdateWithFilter(s, action, res)) + } +} - for collectionIndex, docs := range test.Docs { - for _, doc := range docs { - actions = append( - actions, - CreateDoc{ - CollectionID: collectionIndex, - Doc: doc, +// createIndex creates a secondary index using the collection api. +func createIndex( + s *state, + action CreateIndex, +) { + if action.CollectionID >= len(s.indexes) { + // Expand the slice if required, so that the index can be accessed by collection index + s.indexes = append(s.indexes, + make([][][]client.IndexDescription, action.CollectionID-len(s.indexes)+1)...) + } + actionNodes := getNodes(action.NodeID, s.nodes) + for nodeID, collections := range getNodeCollections(action.NodeID, s.collections) { + indexDesc := client.IndexDescription{ + Name: action.IndexName, + } + if action.FieldName != "" { + indexDesc.Fields = []client.IndexedFieldDescription{ + { + Name: action.FieldName, }, - ) + } + } else if len(action.Fields) > 0 { + for i := range action.Fields { + indexDesc.Fields = append(indexDesc.Fields, client.IndexedFieldDescription{ + Name: action.Fields[i].Name, + Descending: action.Fields[i].Descending, + }) + } + } + indexDesc.Unique = action.Unique + err := withRetry( + actionNodes, + nodeID, + func() error { + desc, err := collections[action.CollectionID].CreateIndex(s.ctx, indexDesc) + if err != nil { + return err + } + s.indexes[nodeID][action.CollectionID] = + append(s.indexes[nodeID][action.CollectionID], desc) + return nil + }, + ) + if AssertError(s.t, s.testCase.Description, err, action.ExpectedError) { + return } } - if test.Request != "" { - actions = append( - actions, - Request{ - ExpectedError: test.ExpectedError, - Request: test.Request, - Results: test.Results, + assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, false) +} + +// dropIndex drops the secondary index using the collection api. +func dropIndex( + s *state, + action DropIndex, +) { + var expectedErrorRaised bool + actionNodes := getNodes(action.NodeID, s.nodes) + for nodeID, collections := range getNodeCollections(action.NodeID, s.collections) { + indexName := action.IndexName + if indexName == "" { + indexName = s.indexes[nodeID][action.CollectionID][action.IndexID].Name + } + + err := withRetry( + actionNodes, + nodeID, + func() error { + return collections[action.CollectionID].DropIndex(s.ctx, indexName) }, ) + expectedErrorRaised = AssertError(s.t, s.testCase.Description, err, action.ExpectedError) + } + + assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) +} + +// backupExport generates a backup using the db api. +func backupExport( + s *state, + action BackupExport, +) { + if action.Config.Filepath == "" { + action.Config.Filepath = s.t.TempDir() + testJSONFile + } + + var expectedErrorRaised bool + actionNodes := getNodes(action.NodeID, s.nodes) + for nodeID, node := range actionNodes { + err := withRetry( + actionNodes, + nodeID, + func() error { return node.BasicExport(s.ctx, &action.Config) }, + ) + expectedErrorRaised = AssertError(s.t, s.testCase.Description, err, action.ExpectedError) + + if !expectedErrorRaised { + assertBackupContent(s.t, action.ExpectedContent, action.Config.Filepath) + } + } + assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) +} + +// backupImport imports data from a backup using the db api. +func backupImport( + s *state, + action BackupImport, +) { + if action.Filepath == "" { + action.Filepath = s.t.TempDir() + testJSONFile + } + + // we can avoid checking the error here as this would mean the filepath is invalid + // and we want to make sure that `BasicImport` fails in this case. + _ = os.WriteFile(action.Filepath, []byte(action.ImportContent), 0664) + + var expectedErrorRaised bool + actionNodes := getNodes(action.NodeID, s.nodes) + for nodeID, node := range actionNodes { + err := withRetry( + actionNodes, + nodeID, + func() error { return node.BasicImport(s.ctx, action.Filepath) }, + ) + expectedErrorRaised = AssertError(s.t, s.testCase.Description, err, action.ExpectedError) + } + assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) +} + +// withRetry attempts to perform the given action, retrying up to a DB-defined +// maximum attempt count if a transaction conflict error is returned. +// +// If a P2P-sync commit for the given document is already in progress this +// Save call can fail as the transaction will conflict. We dont want to worry +// about this in our tests so we just retry a few times until it works (or the +// retry limit is breached - important incase this is a different error) +func withRetry( + nodes []clients.Client, + nodeID int, + action func() error, +) error { + for i := 0; i < nodes[nodeID].MaxTxnRetries(); i++ { + err := action() + if errors.Is(err, datastore.ErrTxnConflict) { + time.Sleep(100 * time.Millisecond) + continue + } + return err + } + return nil +} + +func getTransaction( + s *state, + db client.DB, + transactionSpecifier immutable.Option[int], + expectedError string, +) datastore.Txn { + if !transactionSpecifier.HasValue() { + return nil + } + + transactionID := transactionSpecifier.Value() + + if transactionID >= len(s.txns) { + // Extend the txn slice so this txn can fit and be accessed by TransactionId + s.txns = append(s.txns, make([]datastore.Txn, transactionID-len(s.txns)+1)...) + } + + if s.txns[transactionID] == nil { + // Create a new transaction if one does not already exist. + txn, err := db.NewTxn(s.ctx, false) + if AssertError(s.t, s.testCase.Description, err, expectedError) { + txn.Discard(s.ctx) + return nil + } + + s.txns[transactionID] = txn + } + + return s.txns[transactionID] +} + +// commitTransaction commits the given transaction. +// +// Will panic if the given transaction does not exist. Discards the transaction if +// an error is returned on commit. +func commitTransaction( + s *state, + action TransactionCommit, +) { + err := s.txns[action.TransactionID].Commit(s.ctx) + if err != nil { + s.txns[action.TransactionID].Discard(s.ctx) + } + + expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError) + + assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) +} + +// executeRequest executes the given request. +func executeRequest( + s *state, + action Request, +) { + var expectedErrorRaised bool + for nodeID, node := range getNodes(action.NodeID, s.nodes) { + txn := getTransaction(s, node, action.TransactionID, action.ExpectedError) + + ctx := db.SetContextTxn(s.ctx, txn) + identity := getIdentity(s, nodeID, action.Identity) + ctx = db.SetContextIdentity(ctx, identity) + + result := node.ExecRequest(ctx, action.Request) + + anyOfByFieldKey := map[docFieldKey][]any{} + expectedErrorRaised = assertRequestResults( + s, + &result.GQL, + action.Results, + action.ExpectedError, + action.Asserter, + nodeID, + anyOfByFieldKey, + ) + } + + assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) +} + +// executeSubscriptionRequest executes the given subscription request, returning +// a channel that will receive a single event once the subscription has been completed. +// +// The returned channel will receive a function that asserts that +// the subscription received all its expected results and no more. +// It should be called from the main test routine to ensure that +// failures are recorded properly. It will only yield once, once +// the subscription has terminated. +func executeSubscriptionRequest( + s *state, + action SubscriptionRequest, +) { + subscriptionAssert := make(chan func()) + + for _, node := range getNodes(action.NodeID, s.nodes) { + result := node.ExecRequest(s.ctx, action.Request) + if AssertErrors(s.t, s.testCase.Description, result.GQL.Errors, action.ExpectedError) { + return + } + + go func() { + var results []*client.GQLResult + allActionsAreDone := false + for !allActionsAreDone || len(results) < len(action.Results) { + select { + case s := <-result.Subscription: + results = append(results, &s) + + case <-s.allActionsDone: + allActionsAreDone = true + } + } + + subscriptionAssert <- func() { + for i, r := range action.Results { + // This assert should be executed from the main test routine + // so that failures will be properly handled. + expectedErrorRaised := assertRequestResults( + s, + results[i], + r, + action.ExpectedError, + nil, + // anyof is not yet supported by subscription requests + 0, + map[docFieldKey][]any{}, + ) + + assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) + } + } + }() + } + + s.subscriptionResultsChans = append(s.subscriptionResultsChans, subscriptionAssert) +} + +// Asserts as to whether an error has been raised as expected (or not). If an expected +// error has been raised it will return true, returns false in all other cases. +func AssertError(t testing.TB, description string, err error, expectedError string) bool { + if err == nil { + return false + } + + if expectedError == "" { + require.NoError(t, err, description) + return false + } else { + if !strings.Contains(err.Error(), expectedError) { + // Must be require instead of assert, otherwise will show a fake "error not raised". + require.ErrorIs(t, err, errors.New(expectedError)) + return false + } + return true + } +} + +// Asserts as to whether an error has been raised as expected (or not). If an expected +// error has been raised it will return true, returns false in all other cases. +func AssertErrors( + t testing.TB, + description string, + errs []error, + expectedError string, +) bool { + if expectedError == "" { + require.Empty(t, errs, description) + } else { + for _, e := range errs { + // This is always a string at the moment, add support for other types as and when needed + errorString := e.Error() + if !strings.Contains(errorString, expectedError) { + // We use ErrorIs for clearer failures (is a error comparison even if it is just a string) + require.ErrorIs(t, errors.New(errorString), errors.New(expectedError)) + continue + } + return true + } + } + return false +} + +// docFieldKey is an internal key type that wraps docIndex and fieldName +type docFieldKey struct { + docIndex int + fieldName string +} + +func assertRequestResults( + s *state, + result *client.GQLResult, + expectedResults map[string]any, + expectedError string, + asserter ResultAsserter, + nodeID int, + anyOfByField map[docFieldKey][]any, +) bool { + // we skip assertion benchmark because you don't specify expected result for benchmark. + if AssertErrors(s.t, s.testCase.Description, result.Errors, expectedError) || s.isBench { + return true + } + + if expectedResults == nil && result.Data == nil { + return true + } + + // Note: if result.Data == nil this panics (the panic seems useful while testing). + resultantData := result.Data.(map[string]any) + log.InfoContext(s.ctx, "", corelog.Any("RequestResults", result.Data)) + + if asserter != nil { + asserter.Assert(s.t, resultantData) + return true + } + + // merge all keys so we can check for missing values + keys := make(map[string]struct{}) + for key := range resultantData { + keys[key] = struct{}{} + } + for key := range expectedResults { + keys[key] = struct{}{} + } + + stack := &assertStack{} + for key := range keys { + stack.pushMap(key) + expect, ok := expectedResults[key] + require.True(s.t, ok, "expected key not found: %s", key) + + actual, ok := resultantData[key] + require.True(s.t, ok, "result key not found: %s", key) + + expectDocs, ok := expect.([]map[string]any) + if ok { + actualDocs := ConvertToArrayOfMaps(s.t, actual) + assertRequestResultDocs( + s, + nodeID, + expectDocs, + actualDocs, + anyOfByField, + stack, + ) + } else { + assertResultsEqual( + s.t, + s.clientType, + expect, + actual, + fmt.Sprintf("node: %v, path: %s", nodeID, stack), + ) + } + stack.pop() + } + + return false +} + +func assertRequestResultDocs( + s *state, + nodeID int, + expectedResults []map[string]any, + actualResults []map[string]any, + anyOfByField map[docFieldKey][]any, + stack *assertStack, +) bool { + // compare results + require.Equal(s.t, len(expectedResults), len(actualResults), + s.testCase.Description+" \n(number of results don't match)") + + for actualDocIndex, actualDoc := range actualResults { + stack.pushArray(actualDocIndex) + expectedDoc := expectedResults[actualDocIndex] + + require.Equal( + s.t, + len(expectedDoc), + len(actualDoc), + fmt.Sprintf( + "%s \n(number of properties for item at index %v don't match)", + s.testCase.Description, + actualDocIndex, + ), + ) + + for field, actualValue := range actualDoc { + stack.pushMap(field) + switch expectedValue := expectedDoc[field].(type) { + case AnyOf: + assertResultsAnyOf(s.t, s.clientType, expectedValue, actualValue) + + dfk := docFieldKey{actualDocIndex, field} + valueSet := anyOfByField[dfk] + valueSet = append(valueSet, actualValue) + anyOfByField[dfk] = valueSet + case DocIndex: + expectedDocID := s.docIDs[expectedValue.CollectionIndex][expectedValue.Index].String() + assertResultsEqual( + s.t, + s.clientType, + expectedDocID, + actualValue, + fmt.Sprintf("node: %v, path: %s", nodeID, stack), + ) + case []map[string]any: + actualValueMap := ConvertToArrayOfMaps(s.t, actualValue) + + assertRequestResultDocs( + s, + nodeID, + expectedValue, + actualValueMap, + anyOfByField, + stack, + ) + + default: + assertResultsEqual( + s.t, + s.clientType, + expectedValue, + actualValue, + fmt.Sprintf("node: %v, path: %s", nodeID, stack), + ) + } + stack.pop() + } + stack.pop() + } + + return false +} + +func ConvertToArrayOfMaps(t testing.TB, value any) []map[string]any { + valueArrayMap, ok := value.([]map[string]any) + if ok { + return valueArrayMap + } + valueArray, ok := value.([]any) + require.True(t, ok, "expected value to be an array of maps %v", value) + + valueArrayMap = make([]map[string]any, len(valueArray)) + for i, v := range valueArray { + valueArrayMap[i], ok = v.(map[string]any) + require.True(t, ok, "expected value to be an array of maps %v", value) + } + return valueArrayMap +} + +func assertExpectedErrorRaised(t testing.TB, description string, expectedError string, wasRaised bool) { + if expectedError != "" && !wasRaised { + assert.Fail(t, "Expected an error however none was raised.", description) + } +} + +func assertIntrospectionResults( + s *state, + action IntrospectionRequest, +) bool { + for _, node := range getNodes(action.NodeID, s.nodes) { + result := node.ExecRequest(s.ctx, action.Request) + + if AssertErrors(s.t, s.testCase.Description, result.GQL.Errors, action.ExpectedError) { + return true + } + resultantData := result.GQL.Data.(map[string]any) + + if len(action.ExpectedData) == 0 && len(action.ContainsData) == 0 { + require.Equal(s.t, action.ExpectedData, resultantData) + } + + if len(action.ExpectedData) == 0 && len(action.ContainsData) > 0 { + assertContains(s.t, action.ContainsData, resultantData) + } else { + require.Equal(s.t, len(action.ExpectedData), len(resultantData)) + + for k, result := range resultantData { + assert.Equal(s.t, action.ExpectedData[k], result) + } + } + } + + return false +} + +// Asserts that the client introspection results conform to our expectations. +func assertClientIntrospectionResults( + s *state, + action ClientIntrospectionRequest, +) bool { + for _, node := range getNodes(action.NodeID, s.nodes) { + result := node.ExecRequest(s.ctx, action.Request) + + if AssertErrors(s.t, s.testCase.Description, result.GQL.Errors, action.ExpectedError) { + return true + } + resultantData := result.GQL.Data.(map[string]any) + + if len(resultantData) == 0 { + return false + } + + // Iterate through all types, validating each type definition. + // Inspired from buildClientSchema.ts from graphql-js, + // which is one way that clients do validate the schema. + types := resultantData["__schema"].(map[string]any)["types"].([]any) + + for _, typeData := range types { + typeDef := typeData.(map[string]any) + kind := typeDef["kind"].(string) + + switch kind { + case "SCALAR", "INTERFACE", "UNION", "ENUM": + // No validation for these types in this test + case "OBJECT": + fields := typeDef["fields"] + if fields == nil { + s.t.Errorf("Fields are missing for OBJECT type %v", typeDef["name"]) + } + case "INPUT_OBJECT": + inputFields := typeDef["inputFields"] + if inputFields == nil { + s.t.Errorf("InputFields are missing for INPUT_OBJECT type %v", typeDef["name"]) + } + default: + // t.Errorf("Unknown type kind: %v", kind) + } + } + } + + return true +} + +// Asserts that the `actual` contains the given `contains` value according to the logic +// described on the [RequestTestCase.ContainsData] property. +func assertContains(t testing.TB, contains map[string]any, actual map[string]any) { + for k, expected := range contains { + innerActual := actual[k] + if innerExpected, innerIsMap := expected.(map[string]any); innerIsMap { + if innerActual == nil { + assert.Equal(t, innerExpected, innerActual) + } else if innerActualMap, isMap := innerActual.(map[string]any); isMap { + // If the inner is another map then we continue down the chain + assertContains(t, innerExpected, innerActualMap) + } else { + // If the types don't match then we use assert.Equal for a clean failure message + assert.Equal(t, innerExpected, innerActual) + } + } else if innerExpected, innerIsArray := expected.([]any); innerIsArray { + if actualArray, isActualArray := innerActual.([]any); isActualArray { + // If the inner is an array/slice, then assert that each expected item is present + // in the actual. Note how the actual may contain additional items - this should + // not result in a test failure. + for _, innerExpectedItem := range innerExpected { + assert.Contains(t, actualArray, innerExpectedItem) + } + } else { + // If the types don't match then we use assert.Equal for a clean failure message + assert.Equal(t, expected, innerActual) + } + } else { + assert.Equal(t, expected, innerActual) + } } +} - ExecuteTestCase( +func assertBackupContent(t testing.TB, expectedContent, filepath string) { + b, err := os.ReadFile(filepath) + assert.NoError(t, err) + assert.Equal( t, - TestCase{ - Description: test.Description, - Actions: actions, - }, + expectedContent, + string(b), ) } + +// skipIfMutationTypeUnsupported skips the current test if the given supportedMutationTypes option has value +// and the active mutation type is not contained within that value set. +func skipIfMutationTypeUnsupported(t testing.TB, supportedMutationTypes immutable.Option[[]MutationType]) { + if supportedMutationTypes.HasValue() { + var isTypeSupported bool + for _, supportedMutationType := range supportedMutationTypes.Value() { + if supportedMutationType == mutationType { + isTypeSupported = true + break + } + } + + if !isTypeSupported { + t.Skipf("test does not support given mutation type. Type: %s", mutationType) + } + } +} + +// skipIfClientTypeUnsupported returns a new set of client types that match the given supported set. +// +// If supportedClientTypes is none no filtering will take place and the input client set will be returned. +// If the resultant filtered set is empty the test will be skipped. +func skipIfClientTypeUnsupported( + t testing.TB, + clients []ClientType, + supportedClientTypes immutable.Option[[]ClientType], +) []ClientType { + if !supportedClientTypes.HasValue() { + return clients + } + + filteredClients := []ClientType{} + for _, supportedMutationType := range supportedClientTypes.Value() { + for _, client := range clients { + if supportedMutationType == client { + filteredClients = append(filteredClients, client) + break + } + } + } + + if len(filteredClients) == 0 { + t.Skipf("test does not support any given client type. Type: %v", supportedClientTypes) + } + + return filteredClients +} + +func skipIfACPTypeUnsupported(t testing.TB, supporteACPTypes immutable.Option[[]ACPType]) { + if supporteACPTypes.HasValue() { + var isTypeSupported bool + for _, supportedType := range supporteACPTypes.Value() { + if supportedType == acpType { + isTypeSupported = true + break + } + } + + if !isTypeSupported { + t.Skipf("test does not support given acp type. Type: %s", acpType) + } + } +} + +// skipIfNetworkTest skips the current test if the given actions +// contain network actions and skipNetworkTests is true. +func skipIfNetworkTest(t testing.TB, actions []any) { + hasNetworkAction := false + for _, act := range actions { + switch act.(type) { + case ConfigureNode: + hasNetworkAction = true + } + } + if skipNetworkTests && hasNetworkAction { + t.Skip("test involves network actions") + } +} + +func ParseSDL(gqlSDL string) (map[string]client.CollectionDefinition, error) { + parser, err := graphql.NewParser() + if err != nil { + return nil, err + } + cols, err := parser.ParseSDL(context.Background(), gqlSDL) + if err != nil { + return nil, err + } + result := make(map[string]client.CollectionDefinition) + for _, col := range cols { + result[col.Description.Name.Value()] = col + } + return result, nil +} + +func MustParseTime(timeString string) time.Time { + t, err := time.Parse(time.RFC3339, timeString) + if err != nil { + panic(err) + } + return t +} + +func CBORValue(value any) []byte { + enc, err := cbor.Marshal(value) + if err != nil { + panic(err) + } + return enc +} + +// parseCreateDocs parses and returns documents from a CreateDoc action. +func parseCreateDocs(action CreateDoc, collection client.Collection) ([]*client.Document, error) { + switch { + case action.DocMap != nil: + val, err := client.NewDocFromMap(action.DocMap, collection.Definition()) + if err != nil { + return nil, err + } + return []*client.Document{val}, nil + + case client.IsJSONArray([]byte(action.Doc)): + return client.NewDocsFromJSON([]byte(action.Doc), collection.Definition()) + + default: + val, err := client.NewDocFromJSON([]byte(action.Doc), collection.Definition()) + if err != nil { + return nil, err + } + return []*client.Document{val}, nil + } +} diff --git a/tests/integration/utils2.go b/tests/integration/utils2.go deleted file mode 100644 index c5e90bb706..0000000000 --- a/tests/integration/utils2.go +++ /dev/null @@ -1,2253 +0,0 @@ -// Copyright 2022 Democratized Data Foundation -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -package tests - -import ( - "context" - "encoding/json" - "fmt" - "os" - "reflect" - "strconv" - "strings" - "testing" - "time" - - "github.com/bxcodec/faker/support/slice" - "github.com/fxamacker/cbor/v2" - "github.com/sourcenetwork/corelog" - "github.com/sourcenetwork/immutable" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/sourcenetwork/defradb/client" - "github.com/sourcenetwork/defradb/client/request" - "github.com/sourcenetwork/defradb/crypto" - "github.com/sourcenetwork/defradb/datastore" - "github.com/sourcenetwork/defradb/errors" - "github.com/sourcenetwork/defradb/internal/db" - "github.com/sourcenetwork/defradb/internal/encryption" - "github.com/sourcenetwork/defradb/internal/request/graphql" - "github.com/sourcenetwork/defradb/net" - changeDetector "github.com/sourcenetwork/defradb/tests/change_detector" - "github.com/sourcenetwork/defradb/tests/clients" - "github.com/sourcenetwork/defradb/tests/gen" - "github.com/sourcenetwork/defradb/tests/predefined" -) - -const ( - mutationTypeEnvName = "DEFRA_MUTATION_TYPE" - skipNetworkTestsEnvName = "DEFRA_SKIP_NETWORK_TESTS" -) - -// The MutationType that tests will run using. -// -// For example if set to [CollectionSaveMutationType], all supporting -// actions (such as [UpdateDoc]) will execute via [Collection.Save]. -// -// Defaults to CollectionSaveMutationType. -type MutationType string - -const ( - // CollectionSaveMutationType will cause all supporting actions - // to run their mutations via [Collection.Save]. - CollectionSaveMutationType MutationType = "collection-save" - - // CollectionNamedMutationType will cause all supporting actions - // to run their mutations via their corresponding named [Collection] - // call. - // - // For example, CreateDoc will call [Collection.Create], and - // UpdateDoc will call [Collection.Update]. - CollectionNamedMutationType MutationType = "collection-named" - - // GQLRequestMutationType will cause all supporting actions to - // run their mutations using GQL requests, typically these will - // include a `id` parameter to target the specified document. - GQLRequestMutationType MutationType = "gql" -) - -var ( - log = corelog.NewLogger("tests.integration") - mutationType MutationType - // skipNetworkTests will skip any tests that involve network actions - skipNetworkTests = false -) - -const ( - // subscriptionTimeout is the maximum time to wait for subscription results to be returned. - subscriptionTimeout = 1 * time.Second - // Instantiating lenses is expensive, and our tests do not benefit from a large number of them, - // so we explicitly set it to a low value. - lensPoolSize = 2 -) - -const testJSONFile = "/test.json" - -func init() { - // We use environment variables instead of flags `go test ./...` throws for all packages - // that don't have the flag defined - if value, ok := os.LookupEnv(mutationTypeEnvName); ok { - mutationType = MutationType(value) - } else { - // Default to testing mutations via Collection.Save - it should be simpler and - // faster. We assume this is desirable when not explicitly testing any particular - // mutation type. - mutationType = CollectionSaveMutationType - } - if value, ok := os.LookupEnv(skipNetworkTestsEnvName); ok { - skipNetworkTests, _ = strconv.ParseBool(value) - } -} - -// AssertPanic asserts that the code inside the specified PanicTestFunc panics. -// -// This function is not supported by either the change detector, or the http-client. -// Calling this within either of them will result in the test being skipped. -// -// Usage: AssertPanic(t, func() { executeTestCase(t, test) }) -func AssertPanic(t *testing.T, f assert.PanicTestFunc) bool { - if changeDetector.Enabled { - // The `assert.Panics` call will falsely fail if this test is executed during - // a detect changes test run. - t.Skip("Assert panic with the change detector is not currently supported.") - } - - if httpClient || cliClient { - // The http / cli client will return an error instead of panicing at the moment. - t.Skip("Assert panic with the http client is not currently supported.") - } - - return assert.Panics(t, f, "expected a panic, but none found.") -} - -// ExecuteTestCase executes the given TestCase against the configured database -// instances. -// -// Will also attempt to detect incompatible changes in the persisted data if -// configured to do so (the CI will do so, but disabled by default as it is slow). -func ExecuteTestCase( - t testing.TB, - testCase TestCase, -) { - flattenActions(&testCase) - collectionNames := getCollectionNames(testCase) - changeDetector.PreTestChecks(t, collectionNames) - skipIfMutationTypeUnsupported(t, testCase.SupportedMutationTypes) - skipIfACPTypeUnsupported(t, testCase.SupportedACPTypes) - skipIfNetworkTest(t, testCase.Actions) - - var clients []ClientType - if httpClient { - clients = append(clients, HTTPClientType) - } - if goClient { - clients = append(clients, GoClientType) - } - if cliClient { - clients = append(clients, CLIClientType) - } - - var databases []DatabaseType - if badgerInMemory { - databases = append(databases, badgerIMType) - } - if badgerFile { - databases = append(databases, badgerFileType) - } - if inMemoryStore { - databases = append(databases, defraIMType) - } - - // Assert that these are not empty to protect against accidental mis-configurations, - // otherwise an empty set would silently pass all the tests. - require.NotEmpty(t, databases) - require.NotEmpty(t, clients) - - clients = skipIfClientTypeUnsupported(t, clients, testCase.SupportedClientTypes) - - ctx := context.Background() - for _, ct := range clients { - for _, dbt := range databases { - executeTestCase(ctx, t, collectionNames, testCase, dbt, ct) - } - } -} - -func executeTestCase( - ctx context.Context, - t testing.TB, - collectionNames []string, - testCase TestCase, - dbt DatabaseType, - clientType ClientType, -) { - log.InfoContext( - ctx, - testCase.Description, - corelog.Any("database", dbt), - corelog.Any("client", clientType), - corelog.Any("mutationType", mutationType), - corelog.String("databaseDir", databaseDir), - corelog.Bool("badgerEncryption", badgerEncryption), - corelog.Bool("skipNetworkTests", skipNetworkTests), - corelog.Bool("changeDetector.Enabled", changeDetector.Enabled), - corelog.Bool("changeDetector.SetupOnly", changeDetector.SetupOnly), - corelog.String("changeDetector.SourceBranch", changeDetector.SourceBranch), - corelog.String("changeDetector.TargetBranch", changeDetector.TargetBranch), - corelog.String("changeDetector.Repository", changeDetector.Repository), - ) - - startActionIndex, endActionIndex := getActionRange(t, testCase) - - s := newState(ctx, t, testCase, dbt, clientType, collectionNames) - setStartingNodes(s) - - // It is very important that the databases are always closed, otherwise resources will leak - // as tests run. This is particularly important for file based datastores. - defer closeNodes(s) - - // Documents and Collections may already exist in the database if actions have been split - // by the change detector so we should fetch them here at the start too (if they exist). - // collections are by node (index), as they are specific to nodes. - refreshCollections(s) - refreshDocuments(s, startActionIndex) - refreshIndexes(s) - - for i := startActionIndex; i <= endActionIndex; i++ { - performAction(s, i, testCase.Actions[i]) - } - - // Notify any active subscriptions that all requests have been sent. - close(s.allActionsDone) - - for _, resultsChan := range s.subscriptionResultsChans { - select { - case subscriptionAssert := <-resultsChan: - // We want to assert back in the main thread so failures get recorded properly - subscriptionAssert() - - // a safety in case the stream hangs - we don't want the tests to run forever. - case <-time.After(subscriptionTimeout): - assert.Fail(t, "timeout occurred while waiting for data stream", testCase.Description) - } - } -} - -func performAction( - s *state, - actionIndex int, - act any, -) { - switch action := act.(type) { - case ConfigureNode: - configureNode(s, action) - - case Restart: - restartNodes(s) - - case ConnectPeers: - connectPeers(s, action) - - case ConfigureReplicator: - configureReplicator(s, action) - - case DeleteReplicator: - deleteReplicator(s, action) - - case SubscribeToCollection: - subscribeToCollection(s, action) - - case UnsubscribeToCollection: - unsubscribeToCollection(s, action) - - case GetAllP2PCollections: - getAllP2PCollections(s, action) - - case SchemaUpdate: - updateSchema(s, action) - - case SchemaPatch: - patchSchema(s, action) - - case PatchCollection: - patchCollection(s, action) - - case GetSchema: - getSchema(s, action) - - case GetCollections: - getCollections(s, action) - - case SetActiveSchemaVersion: - setActiveSchemaVersion(s, action) - - case CreateView: - createView(s, action) - - case ConfigureMigration: - configureMigration(s, action) - - case AddPolicy: - addPolicyACP(s, action) - - case CreateDoc: - createDoc(s, action) - - case DeleteDoc: - deleteDoc(s, action) - - case UpdateDoc: - updateDoc(s, action) - - case UpdateWithFilter: - updateWithFilter(s, action) - - case CreateIndex: - createIndex(s, action) - - case DropIndex: - dropIndex(s, action) - - case GetIndexes: - getIndexes(s, action) - - case BackupExport: - backupExport(s, action) - - case BackupImport: - backupImport(s, action) - - case TransactionCommit: - commitTransaction(s, action) - - case SubscriptionRequest: - executeSubscriptionRequest(s, action) - - case Request: - executeRequest(s, action) - - case ExplainRequest: - executeExplainRequest(s, action) - - case IntrospectionRequest: - assertIntrospectionResults(s, action) - - case ClientIntrospectionRequest: - assertClientIntrospectionResults(s, action) - - case WaitForSync: - waitForSync(s, action) - - case Benchmark: - benchmarkAction(s, actionIndex, action) - - case GenerateDocs: - generateDocs(s, action) - - case CreatePredefinedDocs: - generatePredefinedDocs(s, action) - - case SetupComplete: - // no-op, just continue. - - default: - s.t.Fatalf("Unknown action type %T", action) - } -} - -func createGenerateDocs(s *state, docs []gen.GeneratedDoc, nodeID immutable.Option[int]) { - nameToInd := make(map[string]int) - for i, name := range s.collectionNames { - nameToInd[name] = i - } - for _, doc := range docs { - docJSON, err := doc.Doc.String() - if err != nil { - s.t.Fatalf("Failed to generate docs %s", err) - } - createDoc(s, CreateDoc{CollectionID: nameToInd[doc.Col.Description.Name.Value()], Doc: docJSON, NodeID: nodeID}) - } -} - -func generateDocs(s *state, action GenerateDocs) { - collections := getNodeCollections(action.NodeID, s.collections) - defs := make([]client.CollectionDefinition, 0, len(collections[0])) - for _, col := range collections[0] { - if len(action.ForCollections) == 0 || slice.Contains(action.ForCollections, col.Name().Value()) { - defs = append(defs, col.Definition()) - } - } - docs, err := gen.AutoGenerate(defs, action.Options...) - if err != nil { - s.t.Fatalf("Failed to generate docs %s", err) - } - createGenerateDocs(s, docs, action.NodeID) -} - -func generatePredefinedDocs(s *state, action CreatePredefinedDocs) { - collections := getNodeCollections(action.NodeID, s.collections) - defs := make([]client.CollectionDefinition, 0, len(collections[0])) - for _, col := range collections[0] { - defs = append(defs, col.Definition()) - } - docs, err := predefined.Create(defs, action.Docs) - if err != nil { - s.t.Fatalf("Failed to generate docs %s", err) - } - createGenerateDocs(s, docs, action.NodeID) -} - -func benchmarkAction( - s *state, - actionIndex int, - bench Benchmark, -) { - if s.dbt == defraIMType { - // Benchmarking makes no sense for test in-memory storage - return - } - if len(bench.FocusClients) > 0 { - isFound := false - for _, clientType := range bench.FocusClients { - if s.clientType == clientType { - isFound = true - break - } - } - if !isFound { - return - } - } - - runBench := func(benchCase any) time.Duration { - startTime := time.Now() - for i := 0; i < bench.Reps; i++ { - performAction(s, actionIndex, benchCase) - } - return time.Since(startTime) - } - - s.isBench = true - defer func() { s.isBench = false }() - - baseElapsedTime := runBench(bench.BaseCase) - optimizedElapsedTime := runBench(bench.OptimizedCase) - - factoredBaseTime := int64(float64(baseElapsedTime) / bench.Factor) - assert.Greater(s.t, factoredBaseTime, optimizedElapsedTime, - "Optimized case should be faster at least by factor of %.2f than the base case. Base: %d, Optimized: %d (μs)", - bench.Factor, optimizedElapsedTime.Microseconds(), baseElapsedTime.Microseconds()) -} - -// getCollectionNames gets an ordered, unique set of collection names across all nodes -// from the action set within the given test case. -// -// It preserves the order in which they are declared, and shares indexes across all nodes, so -// if a second node adds a collection of a name that was previously declared in another node -// the new node will respect the index originally assigned. This allows collections to be -// referenced across multiple nodes by a consistent, predictable index - allowing a single -// action to target the same collection across multiple nodes. -// -// WARNING: This will not work with schemas ending in `type`, e.g. `user_type` -func getCollectionNames(testCase TestCase) []string { - nextIndex := 0 - collectionIndexByName := map[string]int{} - - for _, a := range testCase.Actions { - switch action := a.(type) { - case SchemaUpdate: - if action.ExpectedError != "" { - // If an error is expected then no collections should result from this action - continue - } - - nextIndex = getCollectionNamesFromSchema(collectionIndexByName, action.Schema, nextIndex) - } - } - - collectionNames := make([]string, len(collectionIndexByName)) - for name, index := range collectionIndexByName { - collectionNames[index] = name - } - - return collectionNames -} - -func getCollectionNamesFromSchema(result map[string]int, schema string, nextIndex int) int { - // WARNING: This will not work with schemas ending in `type`, e.g. `user_type` - splitByType := strings.Split(schema, "type ") - // Skip the first, as that preceeds `type ` if `type ` is present, - // else there are no types. - for i := 1; i < len(splitByType); i++ { - wipSplit := strings.TrimLeft(splitByType[i], " ") - indexOfLastChar := strings.IndexAny(wipSplit, " {") - if indexOfLastChar <= 0 { - // This should never happen - continue - } - - collectionName := wipSplit[:indexOfLastChar] - if _, ok := result[collectionName]; ok { - // Collection name has already been added, possibly via another node - continue - } - - result[collectionName] = nextIndex - nextIndex++ - } - return nextIndex -} - -// closeNodes closes all the given nodes, ensuring that resources are properly released. -func closeNodes( - s *state, -) { - for _, node := range s.nodes { - node.Close() - } -} - -// getNodes gets the set of applicable nodes for the given nodeID. -// -// If nodeID has a value it will return that node only, otherwise all nodes will be returned. -func getNodes(nodeID immutable.Option[int], nodes []clients.Client) []clients.Client { - if !nodeID.HasValue() { - return nodes - } - - return []clients.Client{nodes[nodeID.Value()]} -} - -// getNodeCollections gets the set of applicable collections for the given nodeID. -// -// If nodeID has a value it will return collections for that node only, otherwise all collections across all -// nodes will be returned. -func getNodeCollections(nodeID immutable.Option[int], collections [][]client.Collection) [][]client.Collection { - if !nodeID.HasValue() { - return collections - } - - return [][]client.Collection{collections[nodeID.Value()]} -} - -func calculateLenForFlattenedActions(testCase *TestCase) int { - newLen := 0 - for _, a := range testCase.Actions { - actionGroup := reflect.ValueOf(a) - switch actionGroup.Kind() { - case reflect.Array, reflect.Slice: - newLen += actionGroup.Len() - default: - newLen++ - } - } - return newLen -} - -func flattenActions(testCase *TestCase) { - newLen := calculateLenForFlattenedActions(testCase) - if newLen == len(testCase.Actions) { - return - } - newActions := make([]any, 0, newLen) - - for _, a := range testCase.Actions { - actionGroup := reflect.ValueOf(a) - switch actionGroup.Kind() { - case reflect.Array, reflect.Slice: - for i := 0; i < actionGroup.Len(); i++ { - newActions = append( - newActions, - actionGroup.Index(i).Interface(), - ) - } - default: - newActions = append(newActions, a) - } - } - testCase.Actions = newActions -} - -// getActionRange returns the index of the first action to be run, and the last. -// -// Not all processes will run all actions - if this is a change detector run they -// will be split. -// -// If a SetupComplete action is provided, the actions will be split there, if not -// they will be split at the first non SchemaUpdate/CreateDoc/UpdateDoc action. -func getActionRange(t testing.TB, testCase TestCase) (int, int) { - startIndex := 0 - endIndex := len(testCase.Actions) - 1 - - if !changeDetector.Enabled { - return startIndex, endIndex - } - - setupCompleteIndex := -1 - firstNonSetupIndex := -1 - -ActionLoop: - for i := range testCase.Actions { - switch testCase.Actions[i].(type) { - case SetupComplete: - setupCompleteIndex = i - // We don't care about anything else if this has been explicitly provided - break ActionLoop - - case SchemaUpdate, CreateDoc, UpdateDoc, Restart: - continue - - default: - firstNonSetupIndex = i - break ActionLoop - } - } - - if changeDetector.SetupOnly { - if setupCompleteIndex > -1 { - endIndex = setupCompleteIndex - } else if firstNonSetupIndex > -1 { - // -1 to exclude this index - endIndex = firstNonSetupIndex - 1 - } - } else { - if setupCompleteIndex > -1 { - // +1 to exclude the SetupComplete action - startIndex = setupCompleteIndex + 1 - } else if firstNonSetupIndex > -1 { - // We must not set this to -1 :) - startIndex = firstNonSetupIndex - } else { - // if we don't have any non-mutation actions and the change detector is enabled - // skip this test as we will not gain anything from running (change detector would - // run an idential profile to a normal test run) - t.Skipf("no actions to execute") - } - } - - return startIndex, endIndex -} - -// setStartingNodes adds a set of initial Defra nodes for the test to execute against. -// -// If a node(s) has been explicitly configured via a `ConfigureNode` action then no new -// nodes will be added. -func setStartingNodes( - s *state, -) { - hasExplicitNode := false - for _, action := range s.testCase.Actions { - switch action.(type) { - case ConfigureNode: - hasExplicitNode = true - } - } - - // If nodes have not been explicitly configured via actions, setup a default one. - if !hasExplicitNode { - node, path, err := setupNode(s) - require.Nil(s.t, err) - - c, err := setupClient(s, node) - require.Nil(s.t, err) - - eventState, err := newEventState(c.Events()) - require.NoError(s.t, err) - - s.nodes = append(s.nodes, c) - s.nodeEvents = append(s.nodeEvents, eventState) - s.nodeP2P = append(s.nodeP2P, newP2PState()) - s.dbPaths = append(s.dbPaths, path) - } -} - -func restartNodes( - s *state, -) { - if s.dbt == badgerIMType || s.dbt == defraIMType { - return - } - closeNodes(s) - - // We need to restart the nodes in reverse order, to avoid dial backoff issues. - for i := len(s.nodes) - 1; i >= 0; i-- { - originalPath := databaseDir - databaseDir = s.dbPaths[i] - node, _, err := setupNode(s) - require.Nil(s.t, err) - databaseDir = originalPath - - if len(s.nodeConfigs) == 0 { - // If there are no explicit node configuration actions the node will be - // basic (i.e. no P2P stuff) and can be yielded now. - c, err := setupClient(s, node) - require.NoError(s.t, err) - s.nodes[i] = c - - eventState, err := newEventState(c.Events()) - require.NoError(s.t, err) - s.nodeEvents[i] = eventState - continue - } - - // We need to make sure the node is configured with its old address, otherwise - // a new one may be selected and reconnnection to it will fail. - var addresses []string - for _, addr := range s.nodeAddresses[i].Addrs { - addresses = append(addresses, addr.String()) - } - - nodeOpts := s.nodeConfigs[i] - nodeOpts = append(nodeOpts, net.WithListenAddresses(addresses...)) - - p, err := net.NewPeer(s.ctx, node.DB.Rootstore(), node.DB.Blockstore(), node.DB.Encstore(), node.DB.Events(), nodeOpts...) - require.NoError(s.t, err) - - if err := p.Start(); err != nil { - p.Close() - require.NoError(s.t, err) - } - node.Peer = p - - c, err := setupClient(s, node) - require.NoError(s.t, err) - s.nodes[i] = c - - eventState, err := newEventState(c.Events()) - require.NoError(s.t, err) - s.nodeEvents[i] = eventState - - waitForNetworkSetupEvents(s, i) - } - - // If the db was restarted we need to refresh the collection definitions as the old instances - // will reference the old (closed) database instances. - refreshCollections(s) - refreshIndexes(s) -} - -// refreshCollections refreshes all the collections of the given names, preserving order. -// -// If a given collection is not present in the database the value at the corresponding -// result-index will be nil. -func refreshCollections( - s *state, -) { - s.collections = make([][]client.Collection, len(s.nodes)) - - for nodeID, node := range s.nodes { - s.collections[nodeID] = make([]client.Collection, len(s.collectionNames)) - allCollections, err := node.GetCollections(s.ctx, client.CollectionFetchOptions{}) - require.Nil(s.t, err) - - for i, collectionName := range s.collectionNames { - for _, collection := range allCollections { - if collection.Name().Value() == collectionName { - s.collections[nodeID][i] = collection - break - } - } - } - } -} - -// configureNode configures and starts a new Defra node using the provided configuration. -// -// It returns the new node, and its peer address. Any errors generated during configuration -// will result in a test failure. -func configureNode( - s *state, - action ConfigureNode, -) { - if changeDetector.Enabled { - // We do not yet support the change detector for tests running across multiple nodes. - s.t.SkipNow() - return - } - - node, path, err := setupNode(s) //disable change dector, or allow it? - require.NoError(s.t, err) - - privateKey, err := crypto.GenerateEd25519() - require.NoError(s.t, err) - - nodeOpts := action() - nodeOpts = append(nodeOpts, net.WithPrivateKey(privateKey)) - - p, err := net.NewPeer(s.ctx, node.DB.Rootstore(), node.DB.Blockstore(), node.DB.Encstore(), node.DB.Events(), nodeOpts...) - require.NoError(s.t, err) - - log.InfoContext(s.ctx, "Starting P2P node", corelog.Any("P2P address", p.PeerInfo())) - if err := p.Start(); err != nil { - p.Close() - require.NoError(s.t, err) - } - - s.nodeAddresses = append(s.nodeAddresses, p.PeerInfo()) - s.nodeConfigs = append(s.nodeConfigs, nodeOpts) - - node.Peer = p - - c, err := setupClient(s, node) - require.NoError(s.t, err) - - eventState, err := newEventState(c.Events()) - require.NoError(s.t, err) - - s.nodes = append(s.nodes, c) - s.nodeEvents = append(s.nodeEvents, eventState) - s.nodeP2P = append(s.nodeP2P, newP2PState()) - s.dbPaths = append(s.dbPaths, path) -} - -func refreshDocuments( - s *state, - startActionIndex int, -) { - if len(s.collections) == 0 { - // This should only be possible at the moment for P2P testing, for which the - // change detector is currently disabled. We'll likely need some fancier logic - // here if/when we wish to enable it. - return - } - - // For now just do the initial setup using the collections on the first node, - // this may need to become more involved at a later date depending on testing - // requirements. - s.docIDs = make([][]client.DocID, len(s.collections[0])) - - for i := range s.collections[0] { - s.docIDs[i] = []client.DocID{} - } - - for i := 0; i < startActionIndex; i++ { - // We need to add the existing documents in the order in which the test case lists them - // otherwise they cannot be referenced correctly by other actions. - switch action := s.testCase.Actions[i].(type) { - case CreateDoc: - // Just use the collection from the first relevant node, as all will be the same for this - // purpose. - collection := getNodeCollections(action.NodeID, s.collections)[0][action.CollectionID] - - if action.DocMap != nil { - substituteRelations(s, action) - } - docs, err := parseCreateDocs(action, collection) - if err != nil { - // If an err has been returned, ignore it - it may be expected and if not - // the test will fail later anyway - continue - } - - for _, doc := range docs { - s.docIDs[action.CollectionID] = append(s.docIDs[action.CollectionID], doc.ID()) - } - } - } -} - -func refreshIndexes( - s *state, -) { - if len(s.collections) == 0 { - return - } - - s.indexes = make([][][]client.IndexDescription, len(s.collections)) - - for i, nodeCols := range s.collections { - s.indexes[i] = make([][]client.IndexDescription, len(nodeCols)) - - for j, col := range nodeCols { - if col == nil { - continue - } - colIndexes, err := col.GetIndexes(s.ctx) - if err != nil { - continue - } - - s.indexes[i][j] = colIndexes - } - } -} - -func getIndexes( - s *state, - action GetIndexes, -) { - if len(s.collections) == 0 { - return - } - - var expectedErrorRaised bool - actionNodes := getNodes(action.NodeID, s.nodes) - for nodeID, collections := range getNodeCollections(action.NodeID, s.collections) { - err := withRetry( - actionNodes, - nodeID, - func() error { - actualIndexes, err := collections[action.CollectionID].GetIndexes(s.ctx) - if err != nil { - return err - } - - assertIndexesListsEqual(action.ExpectedIndexes, - actualIndexes, s.t, s.testCase.Description) - - return nil - }, - ) - expectedErrorRaised = expectedErrorRaised || - AssertError(s.t, s.testCase.Description, err, action.ExpectedError) - } - - assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) -} - -func assertIndexesListsEqual( - expectedIndexes []client.IndexDescription, - actualIndexes []client.IndexDescription, - t testing.TB, - testDescription string, -) { - toNames := func(indexes []client.IndexDescription) []string { - names := make([]string, len(indexes)) - for i, index := range indexes { - names[i] = index.Name - } - return names - } - - require.ElementsMatch(t, toNames(expectedIndexes), toNames(actualIndexes), testDescription) - - toMap := func(indexes []client.IndexDescription) map[string]client.IndexDescription { - resultMap := map[string]client.IndexDescription{} - for _, index := range indexes { - resultMap[index.Name] = index - } - return resultMap - } - - expectedMap := toMap(expectedIndexes) - actualMap := toMap(actualIndexes) - for key := range expectedMap { - assertIndexesEqual(expectedMap[key], actualMap[key], t, testDescription) - } -} - -func assertIndexesEqual(expectedIndex, actualIndex client.IndexDescription, - t testing.TB, - testDescription string, -) { - assert.Equal(t, expectedIndex.Name, actualIndex.Name, testDescription) - assert.Equal(t, expectedIndex.ID, actualIndex.ID, testDescription) - - toNames := func(fields []client.IndexedFieldDescription) []string { - names := make([]string, len(fields)) - for i, field := range fields { - names[i] = field.Name - } - return names - } - - require.ElementsMatch(t, toNames(expectedIndex.Fields), toNames(actualIndex.Fields), testDescription) - - toMap := func(fields []client.IndexedFieldDescription) map[string]client.IndexedFieldDescription { - resultMap := map[string]client.IndexedFieldDescription{} - for _, field := range fields { - resultMap[field.Name] = field - } - return resultMap - } - - expectedMap := toMap(expectedIndex.Fields) - actualMap := toMap(actualIndex.Fields) - for key := range expectedMap { - assert.Equal(t, expectedMap[key], actualMap[key], testDescription) - } -} - -// updateSchema updates the schema using the given details. -func updateSchema( - s *state, - action SchemaUpdate, -) { - for _, node := range getNodes(action.NodeID, s.nodes) { - results, err := node.AddSchema(s.ctx, action.Schema) - expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError) - - assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) - - if action.ExpectedResults != nil { - assertCollectionDescriptions(s, action.ExpectedResults, results) - } - } - - // If the schema was updated we need to refresh the collection definitions. - refreshCollections(s) - refreshIndexes(s) -} - -func patchSchema( - s *state, - action SchemaPatch, -) { - for _, node := range getNodes(action.NodeID, s.nodes) { - var setAsDefaultVersion bool - if action.SetAsDefaultVersion.HasValue() { - setAsDefaultVersion = action.SetAsDefaultVersion.Value() - } else { - setAsDefaultVersion = true - } - - err := node.PatchSchema(s.ctx, action.Patch, action.Lens, setAsDefaultVersion) - expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError) - - assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) - } - - // If the schema was updated we need to refresh the collection definitions. - refreshCollections(s) - refreshIndexes(s) -} - -func patchCollection( - s *state, - action PatchCollection, -) { - for _, node := range getNodes(action.NodeID, s.nodes) { - err := node.PatchCollection(s.ctx, action.Patch) - expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError) - - assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) - } - - // If the schema was updated we need to refresh the collection definitions. - refreshCollections(s) - refreshIndexes(s) -} - -func getSchema( - s *state, - action GetSchema, -) { - for _, node := range getNodes(action.NodeID, s.nodes) { - var results []client.SchemaDescription - var err error - switch { - case action.VersionID.HasValue(): - result, e := node.GetSchemaByVersionID(s.ctx, action.VersionID.Value()) - err = e - results = []client.SchemaDescription{result} - default: - results, err = node.GetSchemas( - s.ctx, - client.SchemaFetchOptions{ - Root: action.Root, - Name: action.Name, - }, - ) - } - - expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError) - assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) - - if !expectedErrorRaised { - require.Equal(s.t, action.ExpectedResults, results) - } - } -} - -func getCollections( - s *state, - action GetCollections, -) { - for _, node := range getNodes(action.NodeID, s.nodes) { - txn := getTransaction(s, node, action.TransactionID, "") - ctx := db.SetContextTxn(s.ctx, txn) - results, err := node.GetCollections(ctx, action.FilterOptions) - resultDescriptions := make([]client.CollectionDescription, len(results)) - for i, col := range results { - resultDescriptions[i] = col.Description() - } - - expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError) - assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) - - if !expectedErrorRaised { - assertCollectionDescriptions(s, action.ExpectedResults, resultDescriptions) - } - } -} - -func setActiveSchemaVersion( - s *state, - action SetActiveSchemaVersion, -) { - for _, node := range getNodes(action.NodeID, s.nodes) { - err := node.SetActiveSchemaVersion(s.ctx, action.SchemaVersionID) - expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError) - - assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) - } - - refreshCollections(s) - refreshIndexes(s) -} - -func createView( - s *state, - action CreateView, -) { - for _, node := range getNodes(action.NodeID, s.nodes) { - _, err := node.AddView(s.ctx, action.Query, action.SDL, action.Transform) - expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError) - - assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) - } -} - -// createDoc creates a document using the chosen [mutationType] and caches it in the -// test state object. -func createDoc( - s *state, - action CreateDoc, -) { - if action.DocMap != nil { - substituteRelations(s, action) - } - - var mutation func(*state, CreateDoc, client.DB, int, client.Collection) ([]client.DocID, error) - switch mutationType { - case CollectionSaveMutationType: - mutation = createDocViaColSave - case CollectionNamedMutationType: - mutation = createDocViaColCreate - case GQLRequestMutationType: - mutation = createDocViaGQL - default: - s.t.Fatalf("invalid mutationType: %v", mutationType) - } - - var expectedErrorRaised bool - var docIDs []client.DocID - actionNodes := getNodes(action.NodeID, s.nodes) - for nodeID, collections := range getNodeCollections(action.NodeID, s.collections) { - err := withRetry( - actionNodes, - nodeID, - func() error { - var err error - docIDs, err = mutation(s, action, actionNodes[nodeID], nodeID, collections[action.CollectionID]) - return err - }, - ) - expectedErrorRaised = AssertError(s.t, s.testCase.Description, err, action.ExpectedError) - } - - assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) - - if action.CollectionID >= len(s.docIDs) { - // Expand the slice if required, so that the document can be accessed by collection index - s.docIDs = append(s.docIDs, make([][]client.DocID, action.CollectionID-len(s.docIDs)+1)...) - } - s.docIDs[action.CollectionID] = append(s.docIDs[action.CollectionID], docIDs...) - - if action.ExpectedError == "" { - waitForUpdateEvents(s, action.NodeID, getEventsForCreateDoc(s, action)) - } -} - -func createDocViaColSave( - s *state, - action CreateDoc, - node client.DB, - nodeIndex int, - collection client.Collection, -) ([]client.DocID, error) { - docs, err := parseCreateDocs(action, collection) - if err != nil { - return nil, err - } - - txn := getTransaction(s, node, immutable.None[int](), action.ExpectedError) - ctx := makeContextForDocCreate(s, db.SetContextTxn(s.ctx, txn), nodeIndex, &action) - - docIDs := make([]client.DocID, len(docs)) - for i, doc := range docs { - err := collection.Save(ctx, doc) - if err != nil { - return nil, err - } - docIDs[i] = doc.ID() - } - return docIDs, nil -} - -func makeContextForDocCreate(s *state, ctx context.Context, nodeIndex int, action *CreateDoc) context.Context { - identity := getIdentity(s, nodeIndex, action.Identity) - ctx = db.SetContextIdentity(ctx, identity) - ctx = encryption.SetContextConfigFromParams(ctx, action.IsDocEncrypted, action.EncryptedFields) - return ctx -} - -func createDocViaColCreate( - s *state, - action CreateDoc, - node client.DB, - nodeIndex int, - collection client.Collection, -) ([]client.DocID, error) { - docs, err := parseCreateDocs(action, collection) - if err != nil { - return nil, err - } - - txn := getTransaction(s, node, immutable.None[int](), action.ExpectedError) - ctx := makeContextForDocCreate(s, db.SetContextTxn(s.ctx, txn), nodeIndex, &action) - - switch { - case len(docs) > 1: - err := collection.CreateMany(ctx, docs) - if err != nil { - return nil, err - } - - default: - err := collection.Create(ctx, docs[0]) - if err != nil { - return nil, err - } - } - - docIDs := make([]client.DocID, len(docs)) - for i, doc := range docs { - docIDs[i] = doc.ID() - } - return docIDs, nil -} - -func createDocViaGQL( - s *state, - action CreateDoc, - node client.DB, - nodeIndex int, - collection client.Collection, -) ([]client.DocID, error) { - var input string - - paramName := request.Input - - var err error - if action.DocMap != nil { - input, err = valueToGQL(action.DocMap) - } else if client.IsJSONArray([]byte(action.Doc)) { - var docMaps []map[string]any - err = json.Unmarshal([]byte(action.Doc), &docMaps) - require.NoError(s.t, err) - paramName = request.Inputs - input, err = arrayToGQL(docMaps) - } else { - input, err = jsonToGQL(action.Doc) - } - require.NoError(s.t, err) - - params := paramName + ": " + input - - if action.IsDocEncrypted { - params = params + ", " + request.EncryptDocArgName + ": true" - } - if len(action.EncryptedFields) > 0 { - params = params + ", " + request.EncryptFieldsArgName + ": [" + - strings.Join(action.EncryptedFields, ", ") + "]" - } - - key := fmt.Sprintf("create_%s", collection.Name().Value()) - req := fmt.Sprintf(`mutation { %s(%s) { _docID } }`, key, params) - - txn := getTransaction(s, node, immutable.None[int](), action.ExpectedError) - ctx := db.SetContextIdentity(db.SetContextTxn(s.ctx, txn), getIdentity(s, nodeIndex, action.Identity)) - - result := node.ExecRequest(ctx, req) - if len(result.GQL.Errors) > 0 { - return nil, result.GQL.Errors[0] - } - - resultData := result.GQL.Data.(map[string]any) - resultDocs := ConvertToArrayOfMaps(s.t, resultData[key]) - - docIDs := make([]client.DocID, len(resultDocs)) - for i, docMap := range resultDocs { - docIDString := docMap[request.DocIDFieldName].(string) - docID, err := client.NewDocIDFromString(docIDString) - require.NoError(s.t, err) - docIDs[i] = docID - } - - return docIDs, nil -} - -// substituteRelations scans the fields defined in [action.DocMap], if any are of type [DocIndex] -// it will substitute the [DocIndex] for the the corresponding document ID found in the state. -// -// If a document at that index is not found it will panic. -func substituteRelations( - s *state, - action CreateDoc, -) { - for k, v := range action.DocMap { - index, isIndex := v.(DocIndex) - if !isIndex { - continue - } - - docID := s.docIDs[index.CollectionIndex][index.Index] - action.DocMap[k] = docID.String() - } -} - -// deleteDoc deletes a document using the collection api and caches it in the -// given documents slice. -func deleteDoc( - s *state, - action DeleteDoc, -) { - docID := s.docIDs[action.CollectionID][action.DocID] - - var expectedErrorRaised bool - actionNodes := getNodes(action.NodeID, s.nodes) - for nodeID, collections := range getNodeCollections(action.NodeID, s.collections) { - identity := getIdentity(s, nodeID, action.Identity) - ctx := db.SetContextIdentity(s.ctx, identity) - - err := withRetry( - actionNodes, - nodeID, - func() error { - _, err := collections[action.CollectionID].Delete(ctx, docID) - return err - }, - ) - expectedErrorRaised = AssertError(s.t, s.testCase.Description, err, action.ExpectedError) - } - - assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) - - if action.ExpectedError == "" { - docIDs := map[string]struct{}{ - docID.String(): {}, - } - waitForUpdateEvents(s, action.NodeID, docIDs) - } -} - -// updateDoc updates a document using the chosen [mutationType]. -func updateDoc( - s *state, - action UpdateDoc, -) { - var mutation func(*state, UpdateDoc, client.DB, int, client.Collection) error - switch mutationType { - case CollectionSaveMutationType: - mutation = updateDocViaColSave - case CollectionNamedMutationType: - mutation = updateDocViaColUpdate - case GQLRequestMutationType: - mutation = updateDocViaGQL - default: - s.t.Fatalf("invalid mutationType: %v", mutationType) - } - - var expectedErrorRaised bool - actionNodes := getNodes(action.NodeID, s.nodes) - for nodeID, collections := range getNodeCollections(action.NodeID, s.collections) { - err := withRetry( - actionNodes, - nodeID, - func() error { - return mutation(s, action, actionNodes[nodeID], nodeID, collections[action.CollectionID]) - }, - ) - expectedErrorRaised = AssertError(s.t, s.testCase.Description, err, action.ExpectedError) - } - - assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) - - if action.ExpectedError == "" && !action.SkipLocalUpdateEvent { - waitForUpdateEvents(s, action.NodeID, getEventsForUpdateDoc(s, action)) - } -} - -func updateDocViaColSave( - s *state, - action UpdateDoc, - node client.DB, - nodeIndex int, - collection client.Collection, -) error { - identity := getIdentity(s, nodeIndex, action.Identity) - ctx := db.SetContextIdentity(s.ctx, identity) - - doc, err := collection.Get(ctx, s.docIDs[action.CollectionID][action.DocID], true) - if err != nil { - return err - } - err = doc.SetWithJSON([]byte(action.Doc)) - if err != nil { - return err - } - return collection.Save(ctx, doc) -} - -func updateDocViaColUpdate( - s *state, - action UpdateDoc, - node client.DB, - nodeIndex int, - collection client.Collection, -) error { - identity := getIdentity(s, nodeIndex, action.Identity) - ctx := db.SetContextIdentity(s.ctx, identity) - - doc, err := collection.Get(ctx, s.docIDs[action.CollectionID][action.DocID], true) - if err != nil { - return err - } - err = doc.SetWithJSON([]byte(action.Doc)) - if err != nil { - return err - } - return collection.Update(ctx, doc) -} - -func updateDocViaGQL( - s *state, - action UpdateDoc, - node client.DB, - nodeIndex int, - collection client.Collection, -) error { - docID := s.docIDs[action.CollectionID][action.DocID] - - input, err := jsonToGQL(action.Doc) - require.NoError(s.t, err) - - request := fmt.Sprintf( - `mutation { - update_%s(docID: "%s", input: %s) { - _docID - } - }`, - collection.Name().Value(), - docID.String(), - input, - ) - - identity := getIdentity(s, nodeIndex, action.Identity) - ctx := db.SetContextIdentity(s.ctx, identity) - - result := node.ExecRequest(ctx, request) - if len(result.GQL.Errors) > 0 { - return result.GQL.Errors[0] - } - return nil -} - -// updateWithFilter updates the set of matched documents. -func updateWithFilter(s *state, action UpdateWithFilter) { - var res *client.UpdateResult - var expectedErrorRaised bool - actionNodes := getNodes(action.NodeID, s.nodes) - for nodeID, collections := range getNodeCollections(action.NodeID, s.collections) { - identity := getIdentity(s, nodeID, action.Identity) - ctx := db.SetContextIdentity(s.ctx, identity) - - err := withRetry( - actionNodes, - nodeID, - func() error { - var err error - res, err = collections[action.CollectionID].UpdateWithFilter(ctx, action.Filter, action.Updater) - return err - }, - ) - expectedErrorRaised = AssertError(s.t, s.testCase.Description, err, action.ExpectedError) - } - - assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) - - if action.ExpectedError == "" && !action.SkipLocalUpdateEvent { - waitForUpdateEvents(s, action.NodeID, getEventsForUpdateWithFilter(s, action, res)) - } -} - -// createIndex creates a secondary index using the collection api. -func createIndex( - s *state, - action CreateIndex, -) { - if action.CollectionID >= len(s.indexes) { - // Expand the slice if required, so that the index can be accessed by collection index - s.indexes = append(s.indexes, - make([][][]client.IndexDescription, action.CollectionID-len(s.indexes)+1)...) - } - actionNodes := getNodes(action.NodeID, s.nodes) - for nodeID, collections := range getNodeCollections(action.NodeID, s.collections) { - indexDesc := client.IndexDescription{ - Name: action.IndexName, - } - if action.FieldName != "" { - indexDesc.Fields = []client.IndexedFieldDescription{ - { - Name: action.FieldName, - }, - } - } else if len(action.Fields) > 0 { - for i := range action.Fields { - indexDesc.Fields = append(indexDesc.Fields, client.IndexedFieldDescription{ - Name: action.Fields[i].Name, - Descending: action.Fields[i].Descending, - }) - } - } - indexDesc.Unique = action.Unique - err := withRetry( - actionNodes, - nodeID, - func() error { - desc, err := collections[action.CollectionID].CreateIndex(s.ctx, indexDesc) - if err != nil { - return err - } - s.indexes[nodeID][action.CollectionID] = - append(s.indexes[nodeID][action.CollectionID], desc) - return nil - }, - ) - if AssertError(s.t, s.testCase.Description, err, action.ExpectedError) { - return - } - } - - assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, false) -} - -// dropIndex drops the secondary index using the collection api. -func dropIndex( - s *state, - action DropIndex, -) { - var expectedErrorRaised bool - actionNodes := getNodes(action.NodeID, s.nodes) - for nodeID, collections := range getNodeCollections(action.NodeID, s.collections) { - indexName := action.IndexName - if indexName == "" { - indexName = s.indexes[nodeID][action.CollectionID][action.IndexID].Name - } - - err := withRetry( - actionNodes, - nodeID, - func() error { - return collections[action.CollectionID].DropIndex(s.ctx, indexName) - }, - ) - expectedErrorRaised = AssertError(s.t, s.testCase.Description, err, action.ExpectedError) - } - - assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) -} - -// backupExport generates a backup using the db api. -func backupExport( - s *state, - action BackupExport, -) { - if action.Config.Filepath == "" { - action.Config.Filepath = s.t.TempDir() + testJSONFile - } - - var expectedErrorRaised bool - actionNodes := getNodes(action.NodeID, s.nodes) - for nodeID, node := range actionNodes { - err := withRetry( - actionNodes, - nodeID, - func() error { return node.BasicExport(s.ctx, &action.Config) }, - ) - expectedErrorRaised = AssertError(s.t, s.testCase.Description, err, action.ExpectedError) - - if !expectedErrorRaised { - assertBackupContent(s.t, action.ExpectedContent, action.Config.Filepath) - } - } - assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) -} - -// backupImport imports data from a backup using the db api. -func backupImport( - s *state, - action BackupImport, -) { - if action.Filepath == "" { - action.Filepath = s.t.TempDir() + testJSONFile - } - - // we can avoid checking the error here as this would mean the filepath is invalid - // and we want to make sure that `BasicImport` fails in this case. - _ = os.WriteFile(action.Filepath, []byte(action.ImportContent), 0664) - - var expectedErrorRaised bool - actionNodes := getNodes(action.NodeID, s.nodes) - for nodeID, node := range actionNodes { - err := withRetry( - actionNodes, - nodeID, - func() error { return node.BasicImport(s.ctx, action.Filepath) }, - ) - expectedErrorRaised = AssertError(s.t, s.testCase.Description, err, action.ExpectedError) - } - assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) -} - -// withRetry attempts to perform the given action, retrying up to a DB-defined -// maximum attempt count if a transaction conflict error is returned. -// -// If a P2P-sync commit for the given document is already in progress this -// Save call can fail as the transaction will conflict. We dont want to worry -// about this in our tests so we just retry a few times until it works (or the -// retry limit is breached - important incase this is a different error) -func withRetry( - nodes []clients.Client, - nodeID int, - action func() error, -) error { - for i := 0; i < nodes[nodeID].MaxTxnRetries(); i++ { - err := action() - if errors.Is(err, datastore.ErrTxnConflict) { - time.Sleep(100 * time.Millisecond) - continue - } - return err - } - return nil -} - -func getTransaction( - s *state, - db client.DB, - transactionSpecifier immutable.Option[int], - expectedError string, -) datastore.Txn { - if !transactionSpecifier.HasValue() { - return nil - } - - transactionID := transactionSpecifier.Value() - - if transactionID >= len(s.txns) { - // Extend the txn slice so this txn can fit and be accessed by TransactionId - s.txns = append(s.txns, make([]datastore.Txn, transactionID-len(s.txns)+1)...) - } - - if s.txns[transactionID] == nil { - // Create a new transaction if one does not already exist. - txn, err := db.NewTxn(s.ctx, false) - if AssertError(s.t, s.testCase.Description, err, expectedError) { - txn.Discard(s.ctx) - return nil - } - - s.txns[transactionID] = txn - } - - return s.txns[transactionID] -} - -// commitTransaction commits the given transaction. -// -// Will panic if the given transaction does not exist. Discards the transaction if -// an error is returned on commit. -func commitTransaction( - s *state, - action TransactionCommit, -) { - err := s.txns[action.TransactionID].Commit(s.ctx) - if err != nil { - s.txns[action.TransactionID].Discard(s.ctx) - } - - expectedErrorRaised := AssertError(s.t, s.testCase.Description, err, action.ExpectedError) - - assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) -} - -// executeRequest executes the given request. -func executeRequest( - s *state, - action Request, -) { - var expectedErrorRaised bool - for nodeID, node := range getNodes(action.NodeID, s.nodes) { - txn := getTransaction(s, node, action.TransactionID, action.ExpectedError) - - ctx := db.SetContextTxn(s.ctx, txn) - identity := getIdentity(s, nodeID, action.Identity) - ctx = db.SetContextIdentity(ctx, identity) - - result := node.ExecRequest(ctx, action.Request) - - anyOfByFieldKey := map[docFieldKey][]any{} - expectedErrorRaised = assertRequestResults( - s, - &result.GQL, - action.Results, - action.ExpectedError, - action.Asserter, - nodeID, - anyOfByFieldKey, - ) - } - - assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) -} - -// executeSubscriptionRequest executes the given subscription request, returning -// a channel that will receive a single event once the subscription has been completed. -// -// The returned channel will receive a function that asserts that -// the subscription received all its expected results and no more. -// It should be called from the main test routine to ensure that -// failures are recorded properly. It will only yield once, once -// the subscription has terminated. -func executeSubscriptionRequest( - s *state, - action SubscriptionRequest, -) { - subscriptionAssert := make(chan func()) - - for _, node := range getNodes(action.NodeID, s.nodes) { - result := node.ExecRequest(s.ctx, action.Request) - if AssertErrors(s.t, s.testCase.Description, result.GQL.Errors, action.ExpectedError) { - return - } - - go func() { - var results []*client.GQLResult - allActionsAreDone := false - for !allActionsAreDone || len(results) < len(action.Results) { - select { - case s := <-result.Subscription: - results = append(results, &s) - - case <-s.allActionsDone: - allActionsAreDone = true - } - } - - subscriptionAssert <- func() { - for i, r := range action.Results { - // This assert should be executed from the main test routine - // so that failures will be properly handled. - expectedErrorRaised := assertRequestResults( - s, - results[i], - r, - action.ExpectedError, - nil, - // anyof is not yet supported by subscription requests - 0, - map[docFieldKey][]any{}, - ) - - assertExpectedErrorRaised(s.t, s.testCase.Description, action.ExpectedError, expectedErrorRaised) - } - } - }() - } - - s.subscriptionResultsChans = append(s.subscriptionResultsChans, subscriptionAssert) -} - -// Asserts as to whether an error has been raised as expected (or not). If an expected -// error has been raised it will return true, returns false in all other cases. -func AssertError(t testing.TB, description string, err error, expectedError string) bool { - if err == nil { - return false - } - - if expectedError == "" { - require.NoError(t, err, description) - return false - } else { - if !strings.Contains(err.Error(), expectedError) { - // Must be require instead of assert, otherwise will show a fake "error not raised". - require.ErrorIs(t, err, errors.New(expectedError)) - return false - } - return true - } -} - -// Asserts as to whether an error has been raised as expected (or not). If an expected -// error has been raised it will return true, returns false in all other cases. -func AssertErrors( - t testing.TB, - description string, - errs []error, - expectedError string, -) bool { - if expectedError == "" { - require.Empty(t, errs, description) - } else { - for _, e := range errs { - // This is always a string at the moment, add support for other types as and when needed - errorString := e.Error() - if !strings.Contains(errorString, expectedError) { - // We use ErrorIs for clearer failures (is a error comparison even if it is just a string) - require.ErrorIs(t, errors.New(errorString), errors.New(expectedError)) - continue - } - return true - } - } - return false -} - -// docFieldKey is an internal key type that wraps docIndex and fieldName -type docFieldKey struct { - docIndex int - fieldName string -} - -func assertRequestResults( - s *state, - result *client.GQLResult, - expectedResults map[string]any, - expectedError string, - asserter ResultAsserter, - nodeID int, - anyOfByField map[docFieldKey][]any, -) bool { - // we skip assertion benchmark because you don't specify expected result for benchmark. - if AssertErrors(s.t, s.testCase.Description, result.Errors, expectedError) || s.isBench { - return true - } - - if expectedResults == nil && result.Data == nil { - return true - } - - // Note: if result.Data == nil this panics (the panic seems useful while testing). - resultantData := result.Data.(map[string]any) - log.InfoContext(s.ctx, "", corelog.Any("RequestResults", result.Data)) - - if asserter != nil { - asserter.Assert(s.t, resultantData) - return true - } - - // merge all keys so we can check for missing values - keys := make(map[string]struct{}) - for key := range resultantData { - keys[key] = struct{}{} - } - for key := range expectedResults { - keys[key] = struct{}{} - } - - stack := &assertStack{} - for key := range keys { - stack.pushMap(key) - expect, ok := expectedResults[key] - require.True(s.t, ok, "expected key not found: %s", key) - - actual, ok := resultantData[key] - require.True(s.t, ok, "result key not found: %s", key) - - expectDocs, ok := expect.([]map[string]any) - if ok { - actualDocs := ConvertToArrayOfMaps(s.t, actual) - assertRequestResultDocs( - s, - nodeID, - expectDocs, - actualDocs, - anyOfByField, - stack, - ) - } else { - assertResultsEqual( - s.t, - s.clientType, - expect, - actual, - fmt.Sprintf("node: %v, path: %s", nodeID, stack), - ) - } - stack.pop() - } - - return false -} - -func assertRequestResultDocs( - s *state, - nodeID int, - expectedResults []map[string]any, - actualResults []map[string]any, - anyOfByField map[docFieldKey][]any, - stack *assertStack, -) bool { - // compare results - require.Equal(s.t, len(expectedResults), len(actualResults), - s.testCase.Description+" \n(number of results don't match)") - - for actualDocIndex, actualDoc := range actualResults { - stack.pushArray(actualDocIndex) - expectedDoc := expectedResults[actualDocIndex] - - require.Equal( - s.t, - len(expectedDoc), - len(actualDoc), - fmt.Sprintf( - "%s \n(number of properties for item at index %v don't match)", - s.testCase.Description, - actualDocIndex, - ), - ) - - for field, actualValue := range actualDoc { - stack.pushMap(field) - switch expectedValue := expectedDoc[field].(type) { - case AnyOf: - assertResultsAnyOf(s.t, s.clientType, expectedValue, actualValue) - - dfk := docFieldKey{actualDocIndex, field} - valueSet := anyOfByField[dfk] - valueSet = append(valueSet, actualValue) - anyOfByField[dfk] = valueSet - case DocIndex: - expectedDocID := s.docIDs[expectedValue.CollectionIndex][expectedValue.Index].String() - assertResultsEqual( - s.t, - s.clientType, - expectedDocID, - actualValue, - fmt.Sprintf("node: %v, path: %s", nodeID, stack), - ) - case []map[string]any: - actualValueMap := ConvertToArrayOfMaps(s.t, actualValue) - - assertRequestResultDocs( - s, - nodeID, - expectedValue, - actualValueMap, - anyOfByField, - stack, - ) - - default: - assertResultsEqual( - s.t, - s.clientType, - expectedValue, - actualValue, - fmt.Sprintf("node: %v, path: %s", nodeID, stack), - ) - } - stack.pop() - } - stack.pop() - } - - return false -} - -func ConvertToArrayOfMaps(t testing.TB, value any) []map[string]any { - valueArrayMap, ok := value.([]map[string]any) - if ok { - return valueArrayMap - } - valueArray, ok := value.([]any) - require.True(t, ok, "expected value to be an array of maps %v", value) - - valueArrayMap = make([]map[string]any, len(valueArray)) - for i, v := range valueArray { - valueArrayMap[i], ok = v.(map[string]any) - require.True(t, ok, "expected value to be an array of maps %v", value) - } - return valueArrayMap -} - -func assertExpectedErrorRaised(t testing.TB, description string, expectedError string, wasRaised bool) { - if expectedError != "" && !wasRaised { - assert.Fail(t, "Expected an error however none was raised.", description) - } -} - -func assertIntrospectionResults( - s *state, - action IntrospectionRequest, -) bool { - for _, node := range getNodes(action.NodeID, s.nodes) { - result := node.ExecRequest(s.ctx, action.Request) - - if AssertErrors(s.t, s.testCase.Description, result.GQL.Errors, action.ExpectedError) { - return true - } - resultantData := result.GQL.Data.(map[string]any) - - if len(action.ExpectedData) == 0 && len(action.ContainsData) == 0 { - require.Equal(s.t, action.ExpectedData, resultantData) - } - - if len(action.ExpectedData) == 0 && len(action.ContainsData) > 0 { - assertContains(s.t, action.ContainsData, resultantData) - } else { - require.Equal(s.t, len(action.ExpectedData), len(resultantData)) - - for k, result := range resultantData { - assert.Equal(s.t, action.ExpectedData[k], result) - } - } - } - - return false -} - -// Asserts that the client introspection results conform to our expectations. -func assertClientIntrospectionResults( - s *state, - action ClientIntrospectionRequest, -) bool { - for _, node := range getNodes(action.NodeID, s.nodes) { - result := node.ExecRequest(s.ctx, action.Request) - - if AssertErrors(s.t, s.testCase.Description, result.GQL.Errors, action.ExpectedError) { - return true - } - resultantData := result.GQL.Data.(map[string]any) - - if len(resultantData) == 0 { - return false - } - - // Iterate through all types, validating each type definition. - // Inspired from buildClientSchema.ts from graphql-js, - // which is one way that clients do validate the schema. - types := resultantData["__schema"].(map[string]any)["types"].([]any) - - for _, typeData := range types { - typeDef := typeData.(map[string]any) - kind := typeDef["kind"].(string) - - switch kind { - case "SCALAR", "INTERFACE", "UNION", "ENUM": - // No validation for these types in this test - case "OBJECT": - fields := typeDef["fields"] - if fields == nil { - s.t.Errorf("Fields are missing for OBJECT type %v", typeDef["name"]) - } - case "INPUT_OBJECT": - inputFields := typeDef["inputFields"] - if inputFields == nil { - s.t.Errorf("InputFields are missing for INPUT_OBJECT type %v", typeDef["name"]) - } - default: - // t.Errorf("Unknown type kind: %v", kind) - } - } - } - - return true -} - -// Asserts that the `actual` contains the given `contains` value according to the logic -// described on the [RequestTestCase.ContainsData] property. -func assertContains(t testing.TB, contains map[string]any, actual map[string]any) { - for k, expected := range contains { - innerActual := actual[k] - if innerExpected, innerIsMap := expected.(map[string]any); innerIsMap { - if innerActual == nil { - assert.Equal(t, innerExpected, innerActual) - } else if innerActualMap, isMap := innerActual.(map[string]any); isMap { - // If the inner is another map then we continue down the chain - assertContains(t, innerExpected, innerActualMap) - } else { - // If the types don't match then we use assert.Equal for a clean failure message - assert.Equal(t, innerExpected, innerActual) - } - } else if innerExpected, innerIsArray := expected.([]any); innerIsArray { - if actualArray, isActualArray := innerActual.([]any); isActualArray { - // If the inner is an array/slice, then assert that each expected item is present - // in the actual. Note how the actual may contain additional items - this should - // not result in a test failure. - for _, innerExpectedItem := range innerExpected { - assert.Contains(t, actualArray, innerExpectedItem) - } - } else { - // If the types don't match then we use assert.Equal for a clean failure message - assert.Equal(t, expected, innerActual) - } - } else { - assert.Equal(t, expected, innerActual) - } - } -} - -func assertBackupContent(t testing.TB, expectedContent, filepath string) { - b, err := os.ReadFile(filepath) - assert.NoError(t, err) - assert.Equal( - t, - expectedContent, - string(b), - ) -} - -// skipIfMutationTypeUnsupported skips the current test if the given supportedMutationTypes option has value -// and the active mutation type is not contained within that value set. -func skipIfMutationTypeUnsupported(t testing.TB, supportedMutationTypes immutable.Option[[]MutationType]) { - if supportedMutationTypes.HasValue() { - var isTypeSupported bool - for _, supportedMutationType := range supportedMutationTypes.Value() { - if supportedMutationType == mutationType { - isTypeSupported = true - break - } - } - - if !isTypeSupported { - t.Skipf("test does not support given mutation type. Type: %s", mutationType) - } - } -} - -// skipIfClientTypeUnsupported returns a new set of client types that match the given supported set. -// -// If supportedClientTypes is none no filtering will take place and the input client set will be returned. -// If the resultant filtered set is empty the test will be skipped. -func skipIfClientTypeUnsupported( - t testing.TB, - clients []ClientType, - supportedClientTypes immutable.Option[[]ClientType], -) []ClientType { - if !supportedClientTypes.HasValue() { - return clients - } - - filteredClients := []ClientType{} - for _, supportedMutationType := range supportedClientTypes.Value() { - for _, client := range clients { - if supportedMutationType == client { - filteredClients = append(filteredClients, client) - break - } - } - } - - if len(filteredClients) == 0 { - t.Skipf("test does not support any given client type. Type: %v", supportedClientTypes) - } - - return filteredClients -} - -func skipIfACPTypeUnsupported(t testing.TB, supporteACPTypes immutable.Option[[]ACPType]) { - if supporteACPTypes.HasValue() { - var isTypeSupported bool - for _, supportedType := range supporteACPTypes.Value() { - if supportedType == acpType { - isTypeSupported = true - break - } - } - - if !isTypeSupported { - t.Skipf("test does not support given acp type. Type: %s", acpType) - } - } -} - -// skipIfNetworkTest skips the current test if the given actions -// contain network actions and skipNetworkTests is true. -func skipIfNetworkTest(t testing.TB, actions []any) { - hasNetworkAction := false - for _, act := range actions { - switch act.(type) { - case ConfigureNode: - hasNetworkAction = true - } - } - if skipNetworkTests && hasNetworkAction { - t.Skip("test involves network actions") - } -} - -func ParseSDL(gqlSDL string) (map[string]client.CollectionDefinition, error) { - parser, err := graphql.NewParser() - if err != nil { - return nil, err - } - cols, err := parser.ParseSDL(context.Background(), gqlSDL) - if err != nil { - return nil, err - } - result := make(map[string]client.CollectionDefinition) - for _, col := range cols { - result[col.Description.Name.Value()] = col - } - return result, nil -} - -func MustParseTime(timeString string) time.Time { - t, err := time.Parse(time.RFC3339, timeString) - if err != nil { - panic(err) - } - return t -} - -func CBORValue(value any) []byte { - enc, err := cbor.Marshal(value) - if err != nil { - panic(err) - } - return enc -} - -// parseCreateDocs parses and returns documents from a CreateDoc action. -func parseCreateDocs(action CreateDoc, collection client.Collection) ([]*client.Document, error) { - switch { - case action.DocMap != nil: - val, err := client.NewDocFromMap(action.DocMap, collection.Definition()) - if err != nil { - return nil, err - } - return []*client.Document{val}, nil - - case client.IsJSONArray([]byte(action.Doc)): - return client.NewDocsFromJSON([]byte(action.Doc), collection.Definition()) - - default: - val, err := client.NewDocFromJSON([]byte(action.Doc), collection.Definition()) - if err != nil { - return nil, err - } - return []*client.Document{val}, nil - } -}