Skip to content

Add fixtures for API responses #211

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/.travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ install:
- npm install
- bower install --production
script:
- npm run -s build
- npm run -s bundle
4 changes: 3 additions & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
},
"scripts": {
"clean": "rimraf output",
"build": "spago bundle-app --path $npm_package_config_configpath --purs-args '--censor-lib --strict' --to public/js/index.js"
"test": "spago test --path $npm_package_config_configpath",
"build": "spago build --path $npm_package_config_configpath",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we switch this environment variable to something a little shorter? Perhaps TRY_CONFIG?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason we have the npm_package_config_ prefix is so that it can pick up the values from the config key in package.json by default if they haven't been explicitly overridden (e.g. like we do in CI:

npm config set trypurescript-client:configpath "config/prod/*.purs"
). We have to include the npm_package_config_ prefix for this to work. If there's another way to make npm run build Just Work in development and for the production config to be used in CI I'm happy to consider that.

"bundle": "spago bundle-app --path $npm_package_config_configpath --purs-args '--censor-lib --strict' --to public/js/index.js"
},
"devDependencies": {
"purescript": "^0.13.6",
Expand Down
4 changes: 3 additions & 1 deletion client/spago.dhall
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ You can edit this file as you like.
[ "aff"
, "affjax"
, "arrays"
, "assert"
, "bifunctors"
, "console"
, "const"
Expand Down Expand Up @@ -35,6 +36,7 @@ You can edit this file as you like.
, "lazy"
, "math"
, "maybe"
, "node-fs"
, "ordered-collections"
, "parallel"
, "prelude"
Expand All @@ -56,5 +58,5 @@ You can edit this file as you like.
, "web-html"
]
, packages = ./packages.dhall
, sources = [ "src/**/*.purs" ]
, sources = [ "src/**/*.purs", "test/**/*.purs" ]
}
36 changes: 36 additions & 0 deletions client/test/Fixture.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
module Test.Fixture.Json where

import Prelude

import Data.Argonaut.Core (Json)
import Data.Argonaut.Parser as Json
import Data.Either (either)
import Effect (Effect)
import Effect.Exception (throw)
import Node.Buffer as Buffer
import Node.Encoding as Encoding
import Node.FS.Sync as FS.Sync

type Fixtures =
{ compileFailure :: Json
, compileOtherError :: Json
, compileSuccess :: Json
}

readFile :: String -> Effect Json
readFile path = do
buffer <- FS.Sync.readFile path
file <- Buffer.toString Encoding.UTF8 buffer
Json.jsonParser file # either (throw <<< append "Malformed fixture: ") pure

readFixtures :: Effect Fixtures
readFixtures = do
compileFailure <- readFile "test/Fixture/compile-failure.json"
compileOtherError <- readFile "test/Fixture/compile-other-error.json"
compileSuccess <- readFile "test/Fixture/compile-success.json"

pure
{ compileFailure
, compileOtherError
, compileSuccess
}
22 changes: 22 additions & 0 deletions client/test/Fixture/compile-failure.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"error": {
"tag": "CompilerErrors",
"contents": [
{
"suggestion": null,
"moduleName": null,
"errorLink": "https://github.com/purescript/documentation/blob/master/errors/ErrorParsingModule.md",
"errorCode": "ErrorParsingModule",
"message": " Unable to parse module:\n Unexpected token 'String'\n",
"allSpans": [{ "start": [10, 28], "name": "<file>", "end": [10, 34] }],
"filename": "<file>",
"position": {
"startLine": 10,
"endLine": 10,
"startColumn": 28,
"endColumn": 34
}
}
]
}
}
6 changes: 6 additions & 0 deletions client/test/Fixture/compile-other-error.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"error": {
"tag": "OtherError",
"contents": "The name of the main module should be Main."
}
}
28 changes: 28 additions & 0 deletions client/test/Fixture/compile-success.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"js": "\"use strict\";\nvar Control_Bind = require(\"../Control.Bind/index.js\");\nvar Data_Eq = require(\"../Data.Eq/index.js\");\nvar Data_Map_Internal = require(\"../Data.Map.Internal/index.js\");\nvar Data_Maybe = require(\"../Data.Maybe/index.js\");\nvar Data_Ord = require(\"../Data.Ord/index.js\");\nvar Data_Ordering = require(\"../Data.Ordering/index.js\");\nvar Data_Show = require(\"../Data.Show/index.js\");\nvar Effect = require(\"../Effect/index.js\");\nvar Effect_Console = require(\"../Effect.Console/index.js\");\nvar TryPureScript = require(\"../TryPureScript/index.js\");\n\n// | A Name consists of a first name and a last name\nvar Name = (function () {\n function Name(value0, value1) {\n this.value0 = value0;\n this.value1 = value1;\n };\n Name.create = function (value0) {\n return function (value1) {\n return new Name(value0, value1);\n };\n };\n return Name;\n})();\n\n// | The Ord instance allows us to use Names as the\n// | keys in a Map.\nvar phoneBook = Data_Map_Internal.singleton(new Name(\"John\", \"Smith\"))(\"555-555-1234\");\n\n// | With compiler versions >= 0.8.2, we can derive \n// | instances for Eq and Ord, making names comparable.\nvar eqName = new Data_Eq.Eq(function (x) {\n return function (y) {\n return x.value0 === y.value0 && x.value1 === y.value1;\n };\n});\nvar ordName = new Data_Ord.Ord(function () {\n return eqName;\n}, function (x) {\n return function (y) {\n var $20 = Data_Ord.compare(Data_Ord.ordString)(x.value0)(y.value0);\n if ($20 instanceof Data_Ordering.LT) {\n return Data_Ordering.LT.value;\n };\n if ($20 instanceof Data_Ordering.GT) {\n return Data_Ordering.GT.value;\n };\n return Data_Ord.compare(Data_Ord.ordString)(x.value1)(y.value1);\n };\n});\nvar main = Control_Bind.bindFlipped(Effect.bindEffect)(TryPureScript.render)(TryPureScript.withConsole(Effect_Console.logShow(Data_Maybe.showMaybe(Data_Show.showString))(Data_Map_Internal.lookup(ordName)(new Name(\"John\", \"Smith\"))(phoneBook))));\nmodule.exports = {\n Name: Name,\n phoneBook: phoneBook,\n main: main,\n eqName: eqName,\n ordName: ordName\n};",
"warnings": [
{
"suggestion": {
"replaceRange": {
"startLine": 22,
"endLine": 22,
"startColumn": 1,
"endColumn": 1
},
"replacement": "main :: Effect Unit\n\n"
},
"moduleName": "Main",
"errorLink": "https://github.com/purescript/documentation/blob/master/errors/MissingTypeDeclaration.md",
"errorCode": "MissingTypeDeclaration",
"message": " No type declaration was provided for the top-level declaration of main.\n It is good practice to provide type declarations as a form of documentation.\n The inferred type of main was:\n\n Effect Unit\n\n\nin value declaration main\n",
"allSpans": [{ "start": [22, 1], "name": "<file>", "end": [23, 51] }],
"filename": "<file>",
"position": {
"startLine": 22,
"endLine": 23,
"startColumn": 1,
"endColumn": 51
}
}
]
}
43 changes: 43 additions & 0 deletions client/test/Main.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
module Test.Main where

import Prelude

import Control.Monad.Except (runExceptT)
import Data.Argonaut.Core (Json)
import Data.Bitraversable (ltraverse)
import Data.Either (Either, isRight)
import Data.Identity (Identity(..))
import Data.List.Types (NonEmptyList)
import Data.Newtype (un)
import Effect (Effect)
import Effect.Class.Console (log, logShow)
import Foreign (ForeignError, unsafeToForeign)
import Foreign.Generic (class Decode, decode)
import Test.Assert (assert)
import Test.Fixture.Json (Fixtures, readFixtures)
import Try.API (CompileResult)
import Type.Proxy (Proxy(..))

main :: Effect Unit
main = do
fixtures <- readFixtures
apiTests fixtures

apiTests :: Fixtures -> Effect Unit
apiTests fixtures = do
shouldDecode (Proxy :: _ CompileResult) fixtures.compileOtherError
shouldDecode (Proxy :: _ CompileResult) fixtures.compileFailure
shouldDecode (Proxy :: _ CompileResult) fixtures.compileSuccess

-- | Test that a JSON response decodes successfully.
shouldDecode :: forall a. Decode a => Proxy a -> Json -> Effect Unit
shouldDecode _ fixture = do
let
result :: Either (NonEmptyList ForeignError) a
result = un Identity $ runExceptT $ decode $ unsafeToForeign fixture

_ <- result # ltraverse \errors -> do
log "Failed to decode fixture:\n"
logShow errors

assert (isRight result)