Swap part7 and part8

This commit is contained in:
Richard Feldman
2016-06-25 08:27:41 -07:00
parent a771127739
commit 635c55460d
16 changed files with 130 additions and 238 deletions

View File

@@ -1,26 +1,23 @@
module ElmHub exposing (..) module ElmHub exposing (..)
import Auth
import Html exposing (..) import Html exposing (..)
import Html.Attributes exposing (class, target, href, property, defaultValue) import Html.Attributes exposing (class, target, href, property, defaultValue)
import Html.Events exposing (..) import Html.Events exposing (..)
import Http import Auth
import Task exposing (Task) import Task exposing (Task)
import Json.Decode exposing (Decoder) import Json.Decode exposing (Decoder)
import Json.Decode.Pipeline exposing (..) import Json.Decode.Pipeline exposing (..)
import Json.Encode
searchFeed : String -> Cmd Msg getQueryUrl : String -> String
searchFeed query = getQueryUrl query =
let -- See https://developer.github.com/v3/search/#example for how to customize!
url =
"https://api.github.com/search/repositories?access_token=" "https://api.github.com/search/repositories?access_token="
++ Auth.token ++ Auth.token
++ "&q=" ++ "&q="
++ query ++ query
++ "+language:elm&sort=stars&order=desc" ++ "+language:elm&sort=stars&order=desc"
in
Task.perform HandleSearchError HandleSearchResponse (Http.get responseDecoder url)
responseDecoder : Decoder (List SearchResult) responseDecoder : Decoder (List SearchResult)
@@ -101,34 +98,26 @@ type Msg
= Search = Search
| SetQuery String | SetQuery String
| DeleteById ResultId | DeleteById ResultId
| HandleSearchResponse (List SearchResult) | SetResults (List SearchResult)
| HandleSearchError Http.Error | SetErrorMessage (Maybe String)
| DoNothing
update : Msg -> Model -> ( Model, Cmd Msg ) update : (String -> Cmd Msg) -> Msg -> Model -> ( Model, Cmd Msg )
update msg model = update searchFeed msg model =
case msg of case msg of
Search -> Search ->
( model, searchFeed model.query ) ( model, searchFeed (getQueryUrl model.query) )
HandleSearchResponse results ->
( { model | results = results }, Cmd.none )
HandleSearchError error ->
let
errorMessage =
case error of
Http.UnexpectedPayload message ->
Just message
_ ->
Nothing
in
( { model | errorMessage = errorMessage }, Cmd.none )
SetQuery query -> SetQuery query ->
( { model | query = query }, Cmd.none ) ( { model | query = query }, Cmd.none )
SetResults results ->
( { model | results = results }, Cmd.none )
SetErrorMessage errorMessage ->
( { model | errorMessage = errorMessage }, Cmd.none )
DeleteById idToHide -> DeleteById idToHide ->
let let
newResults = newResults =
@@ -139,3 +128,15 @@ update msg model =
{ model | results = newResults } { model | results = newResults }
in in
( newModel, Cmd.none ) ( newModel, Cmd.none )
DoNothing ->
( model, Cmd.none )
decodeGithubResponse : Json.Encode.Value -> Msg
decodeGithubResponse value =
-- TODO use Json.Decode.DecodeValue to decode the response into an Action.
--
-- Hint: look at ElmHub.elm, specifically the definition of Action and
-- the deefinition of responseDecoder
SetErrorMessage (Just "TODO decode the response!")

View File

@@ -1,13 +1,31 @@
module Main exposing (..) port module Main exposing (..)
import ElmHub exposing (..) import ElmHub exposing (..)
import Html.App
import Json.Decode
main : Program Never main : Program Never
main = main =
Html.App.program Html.App.program
{ view = view { view = view
, update = update , update = update githubSearch
, init = ( initialModel, searchFeed initialModel.query ) , init = ( initialModel, githubSearch (getQueryUrl initialModel.query) )
, inputs = [] , subscriptions = \_ -> githubResponse decodeResponse
} }
decodeResponse : Json.Decode.Value -> Msg
decodeResponse json =
case Json.Decode.decodeValue responseDecoder json of
Err err ->
SetErrorMessage (Just err)
Ok results ->
SetResults results
port githubSearch : String -> Cmd msg
port githubResponse : (Json.Decode.Value -> msg) -> Sub msg

View File

@@ -18,17 +18,3 @@ to fail; in that case, just run `elm-package install` again.)
```bash ```bash
elm-live Main.elm --open --output=elm.js elm-live Main.elm --open --output=elm.js
``` ```
## Running Tests
```bash
cd test
elm-package install
elm test TestRunner.elm
```
## References
* [Using Elm packages](https://github.com/elm-lang/elm-package/blob/master/README.md#basic-usage)
* [elm-test documentation](http://package.elm-lang.org/packages/deadfoxygrandpa/elm-test/3.1.1/)
* [`(<|)` documentation](http://package.elm-lang.org/packages/elm-lang/core/3.0.0/Basics#<|)

View File

@@ -4,17 +4,36 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>ElmHub</title> <title>ElmHub</title>
<script type="text/javascript" src="github.js"></script>
<script type="text/javascript" src="elm.js"></script> <script type="text/javascript" src="elm.js"></script>
<link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="style.css">
<link rel="icon" type="image/png" href="elm-hub.png"> <link rel="icon" type="image/png" href="elm-hub.png">
</head> </head>
<body> <body>
<div id="elm-landing-pad"></div>
</body> </body>
<script type="text/javascript"> <script type="text/javascript">
var app = Elm.Main.fullscreen(); // documentation: https://github.com/michael/github
var github = new Github();
var app = Elm.Main.embed(
document.getElementById("elm-landing-pad"),
{githubResponse: []});
function searchGithub(query) {
console.log("Searching for", query);
var search = github.getSearch(query);
search.repositories({}, function (err, repositories) {
console.log("Got response", repositories);
// TODO: app.ports.portNameGoesHere.send(repositories);
});
}
// TODO app.ports.portNameGoesHere.subscribe(searchGithub);
</script> </script>
</html> </html>

View File

@@ -1,7 +0,0 @@
module Auth exposing (token)
token : String
token =
-- Tests don't need a real token.
""

View File

@@ -1,15 +0,0 @@
module Main where
import Signal exposing (Signal)
import ElmTest exposing (consoleRunner)
import Console exposing (IO, run)
import Task
import Tests
console : IO ()
console = consoleRunner Tests.all
port runner : Signal (Task.Task x ())
port runner = run console

View File

@@ -1,55 +0,0 @@
port module Main exposing (..)
import Test exposing (..)
import Expect exposing (Expectation)
import ElmHub exposing (responseDecoder)
import Json.Decode exposing (decodeString, Value)
import Test.Runner.Node as Runner
main : Program Never
main =
describe "Decoding responses from GitHub"
[ test "they can decode empty responses"
<| \() ->
let
emptyResponse =
"""{ "items": [] }"""
in
Expect.equal (Ok [])
(decodeString responseDecoder emptyResponse)
, test "they can decode responses with results in them"
<| \() ->
let
response =
"""{ "items": [
/* TODO: dummy JSON goes here */
] }"""
in
Expect.equal
(Ok
[ { id = 5, name = "foo", stars = 42 }
, { id = 3, name = "bar", stars = 77 }
]
)
(decodeString responseDecoder response)
, test "they result in an error for invalid JSON"
<| \() ->
let
response =
"""{ "pizza": [] }"""
isErrorResult result =
-- TODO return True if the given Result is an Err of some sort,
-- and False if it is an Ok of some sort.
--
-- Result docs: http://package.elm-lang.org/packages/elm-lang/core/3.0.0/Result
False
in
Expect.true "Expected decoding an invalid response to return an Err."
(isErrorResult (decodeString responseDecoder response))
]
|> Runner.run emit
port emit : ( String, Value ) -> Cmd msg

View File

@@ -1,20 +0,0 @@
{
"version": "1.0.0",
"summary": "Like GitHub, but for Elm stuff.",
"repository": "https://github.com/rtfeldman/elm-workshop.git",
"license": "BSD-3-Clause",
"source-directories": [
".",
".."
],
"exposed-modules": [],
"dependencies": {
"project-fuzzball/test": "2.0.1 <= v < 3.0.0",
"project-fuzzball/node": "1.0.2 <= v < 2.0.0",
"NoRedInk/elm-decode-pipeline": "1.1.2 <= v < 2.0.0",
"elm-lang/core": "4.0.1 <= v < 5.0.0",
"elm-lang/html": "1.0.0 <= v < 2.0.0",
"evancz/elm-http": "3.0.1 <= v < 4.0.0"
},
"elm-version": "0.17.0 <= v < 0.18.0"
}

View File

@@ -1,23 +1,26 @@
module ElmHub exposing (..) module ElmHub exposing (..)
import Auth
import Html exposing (..) import Html exposing (..)
import Html.Attributes exposing (class, target, href, property, defaultValue) import Html.Attributes exposing (class, target, href, property, defaultValue)
import Html.Events exposing (..) import Html.Events exposing (..)
import Auth import Http
import Task exposing (Task) import Task exposing (Task)
import Json.Decode exposing (Decoder) import Json.Decode exposing (Decoder)
import Json.Decode.Pipeline exposing (..) import Json.Decode.Pipeline exposing (..)
import Json.Encode
getQueryUrl : String -> String searchFeed : String -> Cmd Msg
getQueryUrl query = searchFeed query =
-- See https://developer.github.com/v3/search/#example for how to customize! let
url =
"https://api.github.com/search/repositories?access_token=" "https://api.github.com/search/repositories?access_token="
++ Auth.token ++ Auth.token
++ "&q=" ++ "&q="
++ query ++ query
++ "+language:elm&sort=stars&order=desc" ++ "+language:elm&sort=stars&order=desc"
in
Task.perform HandleSearchError HandleSearchResponse (Http.get responseDecoder url)
responseDecoder : Decoder (List SearchResult) responseDecoder : Decoder (List SearchResult)
@@ -98,26 +101,34 @@ type Msg
= Search = Search
| SetQuery String | SetQuery String
| DeleteById ResultId | DeleteById ResultId
| SetResults (List SearchResult) | HandleSearchResponse (List SearchResult)
| SetErrorMessage (Maybe String) | HandleSearchError Http.Error
| DoNothing
update : (String -> Cmd Msg) -> Msg -> Model -> ( Model, Cmd Msg ) update : Msg -> Model -> ( Model, Cmd Msg )
update searchFeed msg model = update msg model =
case msg of case msg of
Search -> Search ->
( model, searchFeed (getQueryUrl model.query) ) ( model, searchFeed model.query )
HandleSearchResponse results ->
( { model | results = results }, Cmd.none )
HandleSearchError error ->
let
errorMessage =
case error of
Http.UnexpectedPayload message ->
Just message
_ ->
Nothing
in
( { model | errorMessage = errorMessage }, Cmd.none )
SetQuery query -> SetQuery query ->
( { model | query = query }, Cmd.none ) ( { model | query = query }, Cmd.none )
SetResults results ->
( { model | results = results }, Cmd.none )
SetErrorMessage errorMessage ->
( { model | errorMessage = errorMessage }, Cmd.none )
DeleteById idToHide -> DeleteById idToHide ->
let let
newResults = newResults =
@@ -128,15 +139,3 @@ update searchFeed msg model =
{ model | results = newResults } { model | results = newResults }
in in
( newModel, Cmd.none ) ( newModel, Cmd.none )
DoNothing ->
( model, Cmd.none )
decodeGithubResponse : Json.Encode.Value -> Msg
decodeGithubResponse value =
-- TODO use Json.Decode.DecodeValue to decode the response into an Action.
--
-- Hint: look at ElmHub.elm, specifically the definition of Action and
-- the deefinition of responseDecoder
SetErrorMessage (Just "TODO decode the response!")

View File

@@ -1,31 +1,13 @@
port module Main exposing (..) module Main exposing (..)
import ElmHub exposing (..) import ElmHub exposing (..)
import Html.App
import Json.Decode exposing (Value)
main : Program Never main : Program Never
main = main =
Html.App.program Html.App.program
{ view = view { view = view
, update = update githubSearch , update = update
, init = ( initialModel, githubSearch (getQueryUrl initialModel.query) ) , init = ( initialModel, searchFeed initialModel.query )
, subscriptions = \_ -> githubResponse decodeResponse , inputs = []
} }
decodeResponse : Json.Decode.Value -> Msg
decodeResponse json =
case Json.Decode.decodeValue responseDecoder json of
Err err ->
SetErrorMessage (Just err)
Ok results ->
SetResults results
port githubSearch : String -> Cmd msg
port githubResponse : (Json.Decode.Value -> msg) -> Sub msg

View File

@@ -26,3 +26,9 @@ cd test
elm-package install elm-package install
elm test TestRunner.elm elm test TestRunner.elm
``` ```
## References
* [Using Elm packages](https://github.com/elm-lang/elm-package/blob/master/README.md#basic-usage)
* [elm-test documentation](http://package.elm-lang.org/packages/deadfoxygrandpa/elm-test/3.1.1/)
* [`(<|)` documentation](http://package.elm-lang.org/packages/elm-lang/core/3.0.0/Basics#<|)

View File

@@ -4,36 +4,17 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<title>ElmHub</title> <title>ElmHub</title>
<script type="text/javascript" src="github.js"></script>
<script type="text/javascript" src="elm.js"></script> <script type="text/javascript" src="elm.js"></script>
<link rel="stylesheet" href="style.css"> <link rel="stylesheet" href="style.css">
<link rel="icon" type="image/png" href="elm-hub.png"> <link rel="icon" type="image/png" href="elm-hub.png">
</head> </head>
<body> <body>
<div id="elm-landing-pad"></div>
</body> </body>
<script type="text/javascript"> <script type="text/javascript">
// documentation: https://github.com/michael/github var app = Elm.Main.fullscreen();
var github = new Github();
var app = Elm.Main.embed(
document.getElementById("elm-landing-pad"),
{githubResponse: []});
function searchGithub(query) {
console.log("Searching for", query);
var search = github.getSearch(query);
search.repositories({}, function (err, repositories) {
console.log("Got response", repositories);
// TODO: app.ports.portNameGoesHere.send(repositories);
});
}
// TODO app.ports.portNameGoesHere.subscribe(searchGithub);
</script> </script>
</html> </html>

View File

@@ -1 +0,0 @@
!Auth.elm

View File

@@ -23,8 +23,7 @@ main =
let let
response = response =
"""{ "items": [ """{ "items": [
{ "id": 5, "full_name": "foo", "stargazers_count": 42 }, /* TODO: dummy JSON goes here */
{ "id": 3, "full_name": "bar", "stargazers_count": 77 }
] }""" ] }"""
in in
Expect.equal Expect.equal
@@ -41,14 +40,13 @@ main =
"""{ "pizza": [] }""" """{ "pizza": [] }"""
isErrorResult result = isErrorResult result =
case result of -- TODO return True if the given Result is an Err of some sort,
Ok _ -> -- and False if it is an Ok of some sort.
--
-- Result docs: http://package.elm-lang.org/packages/elm-lang/core/3.0.0/Result
False False
Err _ ->
True
in in
Expect.equal True Expect.true "Expected decoding an invalid response to return an Err."
(isErrorResult (decodeString responseDecoder response)) (isErrorResult (decodeString responseDecoder response))
] ]
|> Runner.run emit |> Runner.run emit