Split off beta build process and add snapshot test.

This commit is contained in:
Dillon Kearns 2020-10-09 17:08:02 -07:00
parent e327d7a25d
commit daa128796d
9 changed files with 242 additions and 80 deletions

View File

@ -21,6 +21,7 @@
], ],
"elm-version": "0.19.0 <= v < 0.20.0", "elm-version": "0.19.0 <= v < 0.20.0",
"dependencies": { "dependencies": {
"ThinkAlexandria/elm-html-in-elm": "1.0.1 <= v < 2.0.0",
"avh4/elm-color": "1.0.0 <= v < 2.0.0", "avh4/elm-color": "1.0.0 <= v < 2.0.0",
"elm/browser": "1.0.1 <= v < 2.0.0", "elm/browser": "1.0.1 <= v < 2.0.0",
"elm/core": "1.0.2 <= v < 2.0.0", "elm/core": "1.0.2 <= v < 2.0.0",

View File

@ -9,6 +9,7 @@
"elm-version": "0.19.1", "elm-version": "0.19.1",
"dependencies": { "dependencies": {
"direct": { "direct": {
"ThinkAlexandria/elm-html-in-elm": "1.0.1",
"avh4/elm-color": "1.0.0", "avh4/elm-color": "1.0.0",
"billstclair/elm-xml-eeue56": "1.0.1", "billstclair/elm-xml-eeue56": "1.0.1",
"dillonkearns/elm-markdown": "4.0.2", "dillonkearns/elm-markdown": "4.0.2",
@ -58,4 +59,4 @@
}, },
"indirect": {} "indirect": {}
} }
} }

View File

@ -12,6 +12,8 @@ module Pages.Internal.Platform.Cli exposing
import BuildError exposing (BuildError) import BuildError exposing (BuildError)
import Codec exposing (Codec) import Codec exposing (Codec)
import Dict exposing (Dict) import Dict exposing (Dict)
import ElmHtml.InternalTypes exposing (decodeElmHtml)
import ElmHtml.ToString exposing (FormatOptions, defaultFormatOptions, nodeToStringWithOptions)
import Head import Head
import Html exposing (Html) import Html exposing (Html)
import Http import Http
@ -103,8 +105,7 @@ type alias Config pathKey userMsg userModel metadata view =
-> ->
StaticHttp.Request StaticHttp.Request
(List (List
(Result (Result String
String
{ path : List String { path : List String
, content : String , content : String
} }
@ -160,6 +161,40 @@ cliApplication cliMsgConstructor narrowMsg toModel fromModel config =
} }
viewRenderer : Html msg -> String
viewRenderer html =
let
options =
{ defaultFormatOptions | newLines = False, indent = 0 }
in
viewDecoder options html
viewDecoder : FormatOptions -> Html msg -> String
viewDecoder options viewHtml =
case
Decode.decodeValue
(decodeElmHtml
(\_ _ ->
Decode.succeed ()
)
)
(asJsonView
viewHtml
)
of
Ok str ->
nodeToStringWithOptions options str
Err err ->
"Error: " ++ Decode.errorToString err
asJsonView : Html msg -> Decode.Value
asJsonView x =
Json.Encode.string "REPLACE_ME_WITH_JSON_STRINGIFY"
perform : (Msg -> msg) -> (Json.Encode.Value -> Cmd Never) -> Effect pathKey -> Cmd msg perform : (Msg -> msg) -> (Json.Encode.Value -> Cmd Never) -> Effect pathKey -> Cmd msg
perform cliMsgConstructor toJsPort effect = perform cliMsgConstructor toJsPort effect =
case effect of case effect of
@ -208,6 +243,13 @@ perform cliMsgConstructor toJsPort effect =
, tracker = Nothing , tracker = Nothing
} }
Effect.SendSinglePage info ->
Json.Encode.object
[ ( "html", Json.Encode.string info.html )
]
|> toJsPort
|> Cmd.map never
flagsDecoder : flagsDecoder :
Decode.Decoder Decode.Decoder
@ -244,76 +286,12 @@ init :
init toModel contentCache siteMetadata config flags = init toModel contentCache siteMetadata config flags =
case Decode.decodeValue flagsDecoder flags of case Decode.decodeValue flagsDecoder flags of
Ok { secrets, mode, staticHttpCache } -> Ok { secrets, mode, staticHttpCache } ->
case contentCache of case mode of
Ok _ -> Mode.ElmToHtmlBeta ->
case ContentCache.pagesWithErrors contentCache of elmToHtmlBetaInit { secrets = secrets, mode = mode, staticHttpCache = staticHttpCache } toModel contentCache siteMetadata config flags
[] ->
let
requests =
Result.andThen
(\metadata ->
staticResponseForPage metadata config.view
)
siteMetadata
staticResponses : StaticResponses _ ->
staticResponses = initLegacy { secrets = secrets, mode = mode, staticHttpCache = staticHttpCache } toModel contentCache siteMetadata config flags
case requests of
Ok okRequests ->
StaticResponses.init staticHttpCache siteMetadata config okRequests
Err errors ->
-- TODO need to handle errors better?
StaticResponses.init staticHttpCache siteMetadata config []
in
StaticResponses.nextStep config siteMetadata mode secrets staticHttpCache [] staticResponses
|> nextStepToEffect (Model staticResponses secrets [] staticHttpCache mode [])
|> Tuple.mapFirst toModel
pageErrors ->
let
requests =
Result.andThen
(\metadata ->
staticResponseForPage metadata config.view
)
siteMetadata
staticResponses : StaticResponses
staticResponses =
case requests of
Ok okRequests ->
StaticResponses.init staticHttpCache siteMetadata config okRequests
Err errors ->
-- TODO need to handle errors better?
StaticResponses.init staticHttpCache siteMetadata config []
in
updateAndSendPortIfDone
config
siteMetadata
(Model
staticResponses
secrets
pageErrors
staticHttpCache
mode
[]
)
toModel
Err metadataParserErrors ->
updateAndSendPortIfDone
config
siteMetadata
(Model StaticResponses.error
secrets
(metadataParserErrors |> List.map Tuple.second)
staticHttpCache
mode
[]
)
toModel
Err error -> Err error ->
updateAndSendPortIfDone updateAndSendPortIfDone
@ -333,6 +311,109 @@ init toModel contentCache siteMetadata config flags =
toModel toModel
elmToHtmlBetaInit { secrets, mode, staticHttpCache } toModel contentCache siteMetadata config flags =
--case flags of
--init toModel contentCache siteMetadata config flags
--|> Tuple.mapSecond (perform cliMsgConstructor config.toJsPort)
--|> Tuple.mapSecond
-- (\cmd ->
--Cmd.map AppMsg
--Cmd.none
( toModel
(Model StaticResponses.error
secrets
[]
--(metadataParserErrors |> List.map Tuple.second)
staticHttpCache
mode
[]
)
, { html =
Html.div []
[ Html.text "Hello!!!!!" ]
|> viewRenderer
}
|> Effect.SendSinglePage
)
--)
initLegacy { secrets, mode, staticHttpCache } toModel contentCache siteMetadata config flags =
case contentCache of
Ok _ ->
case ContentCache.pagesWithErrors contentCache of
[] ->
let
requests =
Result.andThen
(\metadata ->
staticResponseForPage metadata config.view
)
siteMetadata
staticResponses : StaticResponses
staticResponses =
case requests of
Ok okRequests ->
StaticResponses.init staticHttpCache siteMetadata config okRequests
Err errors ->
-- TODO need to handle errors better?
StaticResponses.init staticHttpCache siteMetadata config []
in
StaticResponses.nextStep config siteMetadata mode secrets staticHttpCache [] staticResponses
|> nextStepToEffect (Model staticResponses secrets [] staticHttpCache mode [])
|> Tuple.mapFirst toModel
pageErrors ->
let
requests =
Result.andThen
(\metadata ->
staticResponseForPage metadata config.view
)
siteMetadata
staticResponses : StaticResponses
staticResponses =
case requests of
Ok okRequests ->
StaticResponses.init staticHttpCache siteMetadata config okRequests
Err errors ->
-- TODO need to handle errors better?
StaticResponses.init staticHttpCache siteMetadata config []
in
updateAndSendPortIfDone
config
siteMetadata
(Model
staticResponses
secrets
pageErrors
staticHttpCache
mode
[]
)
toModel
Err metadataParserErrors ->
updateAndSendPortIfDone
config
siteMetadata
(Model StaticResponses.error
secrets
(metadataParserErrors |> List.map Tuple.second)
staticHttpCache
mode
[]
)
toModel
updateAndSendPortIfDone : updateAndSendPortIfDone :
Config pathKey userMsg userModel metadata view Config pathKey userMsg userModel metadata view
-> Result (List BuildError) (List ( PagePath pathKey, metadata )) -> Result (List BuildError) (List ( PagePath pathKey, metadata ))
@ -465,8 +546,7 @@ staticResponseForPage :
} }
) )
-> ->
Result Result (List BuildError)
(List BuildError)
(List (List
( PagePath pathKey ( PagePath pathKey
, StaticHttp.Request , StaticHttp.Request

View File

@ -9,3 +9,4 @@ type Effect pathKey
| SendJsData (ToJsPayload pathKey) | SendJsData (ToJsPayload pathKey)
| FetchHttp { masked : RequestDetails, unmasked : RequestDetails } | FetchHttp { masked : RequestDetails, unmasked : RequestDetails }
| Batch (List (Effect pathKey)) | Batch (List (Effect pathKey))
| SendSinglePage { html : String }

View File

@ -6,6 +6,7 @@ import Json.Decode as Decode
type Mode type Mode
= Prod = Prod
| Dev | Dev
| ElmToHtmlBeta
modeDecoder = modeDecoder =
@ -15,6 +16,9 @@ modeDecoder =
if mode == "prod" then if mode == "prod" then
Decode.succeed Prod Decode.succeed Prod
else if mode == "elm-to-html-beta" then
Decode.succeed ElmToHtmlBeta
else else
Decode.succeed Dev Decode.succeed Dev
) )

View File

@ -51,8 +51,7 @@ init :
-> ->
StaticHttp.Request StaticHttp.Request
(List (List
(Result (Result String
String
{ path : List String { path : List String
, content : String , content : String
} }
@ -175,6 +174,9 @@ encode requestsAndPending mode (StaticResponses staticResponses) =
Mode.Prod -> Mode.Prod ->
StaticHttpRequest.strippedResponses ApplicationType.Cli request requestsAndPending StaticHttpRequest.strippedResponses ApplicationType.Cli request requestsAndPending
Mode.ElmToHtmlBeta ->
StaticHttpRequest.strippedResponses ApplicationType.Cli request requestsAndPending
) )
@ -201,8 +203,7 @@ nextStep :
-> ->
StaticHttp.Request StaticHttp.Request
(List (List
(Result (Result String
String
{ path : List String { path : List String
, content : String , content : String
} }

View File

@ -786,8 +786,7 @@ startWithHttpCache =
startLowLevel : startLowLevel :
StaticHttp.Request StaticHttp.Request
(List (List
(Result (Result String
String
{ path : List String { path : List String
, content : String , content : String
} }
@ -953,6 +952,13 @@ simulateEffects effect =
, tracker = Nothing , tracker = Nothing
} }
Effect.SendSinglePage info ->
SimulatedEffect.Ports.send "toJsPort"
(Encode.object
[ ( "html", Encode.string info.html )
]
)
expectErrorsPort : String -> List (ToJsPayload pathKey) -> Expect.Expectation expectErrorsPort : String -> List (ToJsPayload pathKey) -> Expect.Expectation
expectErrorsPort expectedPlainString actualPorts = expectErrorsPort expectedPlainString actualPorts =

View File

@ -0,0 +1,3 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`one-page app 1`] = `"<div>Hello!!!!!</div>"`;

View File

@ -0,0 +1,65 @@
const {
elmPagesCliFile,
elmPagesUiFile,
} = require("../generator/src/elm-file-constants.js");
const generateRecords = require("../generator/src/generate-records.js");
test("one-page app", async () => {
process.chdir(__dirname);
const result = await doThing();
console.log("result is", result);
expect(result).toMatchSnapshot();
});
async function doThing() {
const fs = require("fs");
const path = require("path");
XMLHttpRequest = require("xhr2");
const DIR_PATH = path.join(process.cwd(), "../examples/simple/");
const OUTPUT_FILE_NAME = "elm.js";
const ELM_FILE_PATH = path.join(
DIR_PATH,
"./elm-stuff/elm-pages",
OUTPUT_FILE_NAME
);
const util = require("util");
const exec = util.promisify(require("child_process").exec);
const output = await exec(
"cd ../examples/simple/elm-stuff/elm-pages && elm-optimize-level-2 ../../src/Main.elm --output elm.js"
);
console.log("shell", `${output.stdout}`);
const elmFileContent = fs.readFileSync(ELM_FILE_PATH, "utf-8");
fs.writeFileSync(
ELM_FILE_PATH,
elmFileContent.replace(
/return \$elm\$json\$Json\$Encode\$string\(.REPLACE_ME_WITH_JSON_STRINGIFY.\)/g,
"return x"
)
);
function runElmApp() {
return new Promise((resolve, _) => {
const mode /** @type { "dev" | "prod" } */ = "elm-to-html-beta";
const staticHttpCache = {};
const app = require(ELM_FILE_PATH).Elm.Main.init({
flags: { secrets: process.env, mode, staticHttpCache },
});
app.ports.toJsPort.subscribe((
/** @type { { head: SeoTag[], allRoutes: string[], html: string } } */ fromElm
) => {
if (fromElm.html) {
console.log("@@@ fromElm", fromElm);
resolve(fromElm.html);
} else {
console.log("??? fromElm", fromElm);
}
});
});
}
return await runElmApp();
}