Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
haskell-gargantext
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Christian Merten
haskell-gargantext
Commits
c5a8606f
Unverified
Commit
c5a8606f
authored
Feb 05, 2024
by
Przemyslaw Kaminski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[test] tests for graphql errors, some fixes as well
parent
24aa4afa
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
53 additions
and
25 deletions
+53
-25
Errors.hs
src/Gargantext/API/Errors.hs
+1
-1
GraphQL.hs
test/Test/API/GraphQL.hs
+30
-4
Private.hs
test/Test/API/Private.hs
+6
-5
Utils.hs
test/Test/Utils.hs
+16
-15
No files found.
src/Gargantext/API/Errors.hs
View file @
c5a8606f
...
...
@@ -79,7 +79,7 @@ frontendErrorToGQLServerError fe@(FrontendError diag ty _) =
ServerError
{
errHTTPCode
=
HTTP
.
statusCode
$
backendErrorTypeToErrStatus
ty
,
errReasonPhrase
=
T
.
unpack
diag
,
errBody
=
JSON
.
encode
(
GraphQLError
fe
)
,
errHeaders
=
mempty
,
errHeaders
=
[(
"Content-Type"
,
"application/json"
)]
}
authErrorToFrontendError
::
AuthenticationError
->
FrontendError
...
...
test/Test/API/GraphQL.hs
View file @
c5a8606f
...
...
@@ -10,10 +10,11 @@ module Test.API.GraphQL (
import
Gargantext.Core.Types.Individu
import
Prelude
import
Servant.Auth.Client
()
import
Test.API.Private
(
withValidLogin
,
protected
)
import
Test.API.Private
(
withValidLogin
,
protected
,
protectedNewError
)
import
Test.API.Setup
(
withTestDBAndPort
,
setupEnvironment
,
createAliceAndBob
)
import
Test.Hspec
import
Test.Hspec.Wai.Internal
(
withApplication
)
import
Test.Hspec.Wai.JSON
(
json
)
import
Test.Utils
import
Text.RawString.QQ
(
r
)
...
...
@@ -30,6 +31,31 @@ tests = sequential $ aroundAll withTestDBAndPort $ do
withApplication
app
$
do
withValidLogin
port
"alice"
(
GargPassword
"alice"
)
$
\
token
->
do
protected
token
"POST"
"/gql"
[
r
|
{
"query": "{ user_infos(user_id: 2) { ui_id, ui_email } }"
}
|]
`
shouldRespondWithFragment
`
[
jsonFragment
|
{"data":{"user_infos":[{"ui_id":2,"ui_email":"alice@gargan.text"}]}}
|]
let
query
=
[
r
|
{ "query": "{ user_infos(user_id: 2) { ui_id, ui_email } }" }
|]
let
expected
=
[
json
|
{"data":{"user_infos":[{"ui_id":2,"ui_email":"alice@gargan.text"}]}}
|]
protected
token
"POST"
"/gql"
query
`
shouldRespondWithFragment
`
expected
describe
"check error format"
$
do
it
"returns the new error if header X-Garg-Error-Scheme: new is passed"
$
\
((
_testEnv
,
port
),
app
)
->
do
withApplication
app
$
do
withValidLogin
port
"gargantua"
(
GargPassword
"secret_key"
)
$
\
token
->
do
let
query
=
[
r
|
{ "query": "{ languages(id:5) { lt_lang } }" }
|]
let
expected
=
[
json
|
{"errors": [{"locations":[{"column":13,"line":1}],"message":"Unknown Argument \"id\" on Field \"languages\"."}] }
|]
protectedNewError
token
"POST"
"/gql"
query
`
shouldRespondWithFragment
`
expected
it
"returns the old error (though this is deprecated)"
$
\
((
_testEnv
,
port
),
app
)
->
do
withApplication
app
$
do
withValidLogin
port
"gargantua"
(
GargPassword
"secret_key"
)
$
\
token
->
do
let
query
=
[
r
|
{ "query": "{ languages(id:5) { lt_lang } }" }
|]
let
expected
=
[
json
|
{"errors": [{"locations":[{"column":13,"line":1}],"message":"Unknown Argument \"id\" on Field \"languages\"."}] }
|]
protected
token
"POST"
"/gql"
query
`
shouldRespondWithFragment
`
expected
it
"check new errors with 'type'"
$
\
((
_testEnv
,
port
),
app
)
->
do
withApplication
app
$
do
withValidLogin
port
"gargantua"
(
GargPassword
"secret_key"
)
$
\
token
->
do
let
query
=
[
r
|
{ "query": "mutation { delete_team_membership(shared_folder_id:1, team_node_id:1, token:\"abc\") }" }
|]
let
expected
=
[
json
|
{"errors":[{"extensions":{"data":{"msg":"This user is not team owner","user_id":1},"diagnostic":"User not authorized. ","type":"EC_403__user_not_authorized"},"message":"User not authorized. "}]}
|]
shouldRespondWithFragmentCustomStatus
403
(
protectedNewError
token
"POST"
"/gql"
query
)
expected
test/Test/API/Private.hs
View file @
c5a8606f
...
...
@@ -18,7 +18,9 @@ module Test.API.Private (
import
Data.Aeson
qualified
as
JSON
import
Data.ByteString.Lazy
qualified
as
L
import
Data.ByteString.Lazy.Char8
qualified
as
C8L
import
Data.CaseInsensitive
qualified
as
CI
import
Data.Map.Strict
qualified
as
Map
import
Data.Text.Encoding
qualified
as
TE
import
Gargantext.API.Admin.Auth.Types
import
Gargantext.API.Routes
...
...
@@ -38,9 +40,8 @@ import Test.API.Setup (withTestDBAndPort, setupEnvironment, mkUrl, createAliceAn
import
Test.Hspec
import
Test.Hspec.Wai
hiding
(
pendingWith
)
import
Test.Hspec.Wai.Internal
(
withApplication
)
import
Test.Utils
(
jsonFragment
,
shouldRespondWithFragment
)
import
qualified
Data.Map.Strict
as
Map
import
qualified
Data.ByteString.Lazy.Char8
as
C8L
import
Test.Hspec.Wai.JSON
(
json
)
import
Test.Utils
(
shouldRespondWithFragment
)
-- | Issue a request with a valid 'Authorization: Bearer' inside.
protected
::
HasCallStack
...
...
@@ -161,7 +162,7 @@ tests = sequential $ aroundAll withTestDBAndPort $ do
withApplication
app
$
do
withValidLogin
port
"alice"
(
GargPassword
"alice"
)
$
\
token
->
do
protected
token
"GET"
(
mkUrl
port
"/node/8"
)
""
`
shouldRespondWithFragment
`
[
json
Fragment
|
{"id":8,"user_id":2,"name":"alice" }
|]
`
shouldRespondWithFragment
`
[
json
|
{"id":8,"user_id":2,"name":"alice" }
|]
it
"forbids 'alice' to see others node private info"
$
\
((
_testEnv
,
port
),
app
)
->
do
withApplication
app
$
do
...
...
@@ -177,7 +178,7 @@ tests = sequential $ aroundAll withTestDBAndPort $ do
withApplication
app
$
do
withValidLogin
port
"alice"
(
GargPassword
"alice"
)
$
\
token
->
do
protected
token
"GET"
(
mkUrl
port
"/tree/8"
)
""
`
shouldRespondWithFragment
`
[
json
Fragment
|
{ "node": {"id":8, "name":"alice", "type": "NodeUser" } }
|]
`
shouldRespondWithFragment
`
[
json
|
{ "node": {"id":8, "name":"alice", "type": "NodeUser" } }
|]
it
"forbids 'alice' to see others node private info"
$
\
((
_testEnv
,
port
),
app
)
->
do
withApplication
app
$
do
...
...
test/Test/Utils.hs
View file @
c5a8606f
...
...
@@ -7,18 +7,16 @@ module Test.Utils where
import
Control.Exception
import
Control.Monad
import
Data.Aeson
import
Data.Aeson.QQ.Simple
(
aesonQQ
)
import
Data.Aeson
qualified
as
JSON
import
Data.Aeson.KeyMap
qualified
as
KM
import
Data.ByteString.Char8
qualified
as
B
import
Data.Char
(
isSpace
)
import
Language.Haskell.TH.Quote
import
Network.HTTP.Types
import
Network.Wai.Test
import
Prelude
import
qualified
Data.Aeson
as
JSON
import
qualified
Data.Aeson.KeyMap
as
KM
import
qualified
Data.ByteString.Char8
as
B
import
Test.Hspec.Expectations
import
Test.Hspec.Wai
import
Test.Hspec.Wai.JSON
import
Test.Hspec.Wai.JSON
(
FromValue
(
..
))
import
Test.Hspec.Wai.Matcher
import
Test.Tasty.HUnit
...
...
@@ -29,15 +27,6 @@ pending reason act = act `catch` (\(e :: SomeException) -> do
putStrLn
$
"PENDING: "
<>
reason
putStrLn
(
displayException
e
))
-- | Similar to 'json' from the 'Test.Hspec.Wai.JSON' package,
-- but allows matching on a /fragment/ of the body.
jsonFragment
::
QuasiQuoter
jsonFragment
=
QuasiQuoter
{
quoteExp
=
\
input
->
[
|
fromValue
$
(
quoteExp
aesonQQ
input
)
|
]
,
quotePat
=
const
$
error
"No quotePat defined for jsonFragment"
,
quoteType
=
const
$
error
"No quoteType defined for jsonFragment"
,
quoteDec
=
const
$
error
"No quoteDec defined for jsonFragment"
}
newtype
JsonFragmentResponseMatcher
=
JsonFragmentResponseMatcher
{
getJsonMatcher
::
ResponseMatcher
}
...
...
@@ -52,6 +41,18 @@ shouldRespondWithFragment action matcher = do
r
<-
action
forM_
(
match
r
(
getJsonMatcher
matcher
))
(
liftIO
.
expectationFailure
)
-- | Same as above, but with custom status code
shouldRespondWithFragmentCustomStatus
::
HasCallStack
=>
Int
->
WaiSession
st
SResponse
->
JsonFragmentResponseMatcher
->
WaiExpectation
st
shouldRespondWithFragmentCustomStatus
status
action
matcher
=
do
let
m
=
(
getJsonMatcher
matcher
)
{
matchStatus
=
status
}
r
<-
action
forM_
(
match
r
(
getJsonMatcher
$
JsonFragmentResponseMatcher
m
))
(
liftIO
.
expectationFailure
)
instance
FromValue
JsonFragmentResponseMatcher
where
fromValue
=
JsonFragmentResponseMatcher
.
ResponseMatcher
200
[
matchHeader
]
.
containsJSON
where
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment