Make CLI code testable (#510)

This commit is contained in:
Shayne Czyzewski 2022-03-23 08:04:09 -04:00 committed by GitHub
parent 318eb03294
commit 1995ccdb9d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 73 additions and 11 deletions

3
.gitignore vendored
View File

@ -4,3 +4,6 @@
# editor related # editor related
.idea/ .idea/
# macOS related
.DS_Store

3
waspc/.gitignore vendored
View File

@ -13,3 +13,6 @@ module-graph.png
.dir-locals.el .dir-locals.el
.projectile .projectile
.vscode .vscode
# macOS related
.DS_Store

View File

@ -103,7 +103,7 @@ NOTE: Reload page if blank.
1. Create a new feature branch from `main`. 1. Create a new feature branch from `main`.
2. If you don't have a good/reliable working HLS (Haskell Language Server) in your IDE, you will want to instead run `./run ghcid` from the root of the project instead: this will run a process that watches the Haskell project and reports any Haskell compiler errors. Leave it running. 2. If you don't have a good/reliable working HLS (Haskell Language Server) in your IDE, you will want to instead run `./run ghcid` from the root of the project instead: this will run a process that watches the Haskell project and reports any Haskell compiler errors. Leave it running.
NOTE: You will need to install `ghcid` globally first. You can do it with `cabal install ghcid`. NOTE: You will need to install `ghcid` globally first. You can do it with `cabal install ghcid`.
3. Do a change in the codebase (most often in `lib/` or `cli/` or `data/`) (together with tests if that makes sense: see "Tests"). 3. Do a change in the codebase (most often in `src/` or `cli/src/` or `data/`) (together with tests if that makes sense: see "Tests").
Fix any errors shown by HLS/`ghcid`. Fix any errors shown by HLS/`ghcid`.
Rinse and repeat. Rinse and repeat.
4. Once close to done, run `cabal test` to confirm that the project's tests are passing (both new and old). 4. Once close to done, run `cabal test` to confirm that the project's tests are passing (both new and old).
@ -138,7 +138,7 @@ Others will comment on your design doc, and once it has gone through needed iter
## Codebase overview ## Codebase overview
Wasp is implemented in Haskell. Wasp is implemented in Haskell.
Codebase is split into library (`src/`) and CLI (`cli/`). Codebase is split into library (`src/`) and CLI (which itself has a library `cli/src/` and thin executable wrapper `cli/exe/`).
CLI is actually `wasp` executable, and it uses the library, where most of the logic is. CLI is actually `wasp` executable, and it uses the library, where most of the logic is.
Wasp compiler takes .wasp files + everything in the `ext/` dir (JS, HTML, ...) and generates a web app that consists of client, server and database. Wasp compiler takes .wasp files + everything in the `ext/` dir (JS, HTML, ...) and generates a web app that consists of client, server and database.
@ -172,8 +172,9 @@ On any changes you do to the source code of Wasp, Wasp project gets recompiled,
## Important directories (in waspc/) ## Important directories (in waspc/)
- src/ -> main source code, library - src/ -> main source code, library
- cli/ -> rest of the source code, cli, uses library - cli/src/ -> rest of the source code, cli, uses library
- test/ -> tests - cli/exe/ -> thin executable wrapper around cli library code
- test/, e2e-test/, cli/test/ -> tests
- data/Generator/templates/ -> mustache templates for the generated client/server. - data/Generator/templates/ -> mustache templates for the generated client/server.
- examples/ -> example apps - examples/ -> example apps
@ -244,6 +245,8 @@ Tests are run with `cabal test`. They include both unit tests, and end-to-end te
To run unit tests only, you can do `cabal test waspc-test` (or `./run test:unit`). To run unit tests only, you can do `cabal test waspc-test` (or `./run test:unit`).
To run individual unit test, you can do `cabal test waspc-test --test-options "-p \"Some test description to match\""` (or just `./run test:unit "Some test description to match"`). To run individual unit test, you can do `cabal test waspc-test --test-options "-p \"Some test description to match\""` (or just `./run test:unit "Some test description to match"`).
To run cli tests only, you can do `cabal test cli-test` (or `./run test:cli`).
To run end-to-end tests only, you can do `cabal test e2e-test` (or `/run test:e2e`). To run end-to-end tests only, you can do `cabal test e2e-test` (or `/run test:e2e`).
## Code analysis ## Code analysis

View File

@ -7,7 +7,7 @@ import Control.Monad (void)
import Data.Char (isSpace) import Data.Char (isSpace)
import Data.Version (showVersion) import Data.Version (showVersion)
import Paths_waspc (version) import Paths_waspc (version)
import System.Environment import System.Environment (getArgs)
import Wasp.Cli.Command (runCommand) import Wasp.Cli.Command (runCommand)
import Wasp.Cli.Command.BashCompletion (bashCompletion, generateBashCompletionScript, printBashCompletionInstruction) import Wasp.Cli.Command.BashCompletion (bashCompletion, generateBashCompletionScript, printBashCompletionInstruction)
import Wasp.Cli.Command.Build (build) import Wasp.Cli.Command.Build (build)

View File

@ -0,0 +1,5 @@
{-# OPTIONS_GHC -F -pgmF tasty-discover -optF --modules=*Test.hs #-}
-- -optF --modules=*Test.hs tells tasty-discover to pick up only files that match *Test.hs.
-- I did not do this for any strong reason so we can remove it in the future if we figure out
-- it is too restrictive.

View File

@ -0,0 +1,12 @@
module TerminalTest where
import Test.Tasty.Hspec
import Wasp.Cli.Terminal
( asWaspMessage,
)
-- TODO: Showing it can be done. Remove me when writing first real CLI test.
spec_terminalMessages :: Spec
spec_terminalMessages = do
it "can format messages of various kinds" $ do
asWaspMessage "Hello, world!" `shouldBe` "\n --- Hello, world! ---------------------------------------------------------------\n"

View File

@ -22,6 +22,7 @@ BUILD_CMD="cabal build all"
BUILD_ALL_CMD="cabal build all --enable-tests --enable-benchmarks" BUILD_ALL_CMD="cabal build all --enable-tests --enable-benchmarks"
TEST_CMD="cabal test" TEST_CMD="cabal test"
TEST_UNIT_CMD="cabal test waspc-test" TEST_UNIT_CMD="cabal test waspc-test"
TEST_CLI_CMD="cabal test cli-test"
TEST_E2E_CMD="cabal test e2e-test" TEST_E2E_CMD="cabal test e2e-test"
RUN_CMD="cabal run wasp-cli ${ARGS[@]}" RUN_CMD="cabal run wasp-cli ${ARGS[@]}"
GHCID_CMD="ghcid --command=cabal repl" GHCID_CMD="ghcid --command=cabal repl"
@ -61,6 +62,8 @@ print_usage () {
"Executes all tests (unit + e2e). Builds the project first if needed." "Executes all tests (unit + e2e). Builds the project first if needed."
print_usage_cmd "test:unit [pattern]" \ print_usage_cmd "test:unit [pattern]" \
"Executes only unit tests. Builds the project first if needed. If pattern is provided, it will run only tests whose description/name matches the pattern. Check https://github.com/UnkindPartition/tasty#patterns to learn more about valid patterns." "Executes only unit tests. Builds the project first if needed. If pattern is provided, it will run only tests whose description/name matches the pattern. Check https://github.com/UnkindPartition/tasty#patterns to learn more about valid patterns."
print_usage_cmd "test:cli" \
"Executes only cli unit tests. Builds the project first if needed."
print_usage_cmd "test:e2e" \ print_usage_cmd "test:e2e" \
"Executes only e2e tests. Builds the project first if needed." "Executes only e2e tests. Builds the project first if needed."
print_usage_cmd "wasp-cli <args>" \ print_usage_cmd "wasp-cli <args>" \
@ -114,6 +117,9 @@ case $COMMAND in
echo_and_eval "$TEST_UNIT_CMD --test-options \"-p \\\"$TEST_PATTERN\\\"\"" echo_and_eval "$TEST_UNIT_CMD --test-options \"-p \\\"$TEST_PATTERN\\\"\""
fi fi
;;
test:cli)
echo_and_eval "$TEST_CLI_CMD"
;; ;;
test:e2e) test:e2e)
echo_and_eval "$TEST_E2E_CMD" echo_and_eval "$TEST_E2E_CMD"

View File

@ -238,11 +238,9 @@ library
Wasp.Generator.NpmInstall Wasp.Generator.NpmInstall
Wasp.Message Wasp.Message
library cli-lib
executable wasp-cli import: common-all
import: common-all, common-exe hs-source-dirs: cli/src
hs-source-dirs: cli
main-is: Main.hs
build-depends: build-depends:
directory directory
, base , base
@ -261,7 +259,8 @@ executable wasp-cli
, utf8-string , utf8-string
, uuid , uuid
, waspc , waspc
other-modules: other-modules: Paths_waspc
exposed-modules:
Wasp.Cli.Command Wasp.Cli.Command
Wasp.Cli.Command.BashCompletion Wasp.Cli.Command.BashCompletion
Wasp.Cli.Command.Build Wasp.Cli.Command.Build
@ -284,6 +283,17 @@ executable wasp-cli
Wasp.Cli.Terminal Wasp.Cli.Terminal
Wasp.Cli.Command.Message Wasp.Cli.Command.Message
Wasp.Cli.Message Wasp.Cli.Message
executable wasp-cli
import: common-all, common-exe
hs-source-dirs: cli/exe
main-is: Main.hs
build-depends:
base
, async
, waspc
, cli-lib
other-modules:
Paths_waspc Paths_waspc
test-suite waspc-test test-suite waspc-test
@ -374,6 +384,26 @@ test-suite e2e-test
Tests.WaspMigrateTest Tests.WaspMigrateTest
Tests.WaspNewTest Tests.WaspNewTest
test-suite cli-test
import: common-all, common-exe
type: exitcode-stdio-1.0
hs-source-dirs: cli/test
main-is: TastyDiscoverDriver.hs
build-tool-depends:
tasty-discover:tasty-discover
build-depends:
, base
, waspc
, cli-lib
, QuickCheck ^>= 2.14
, tasty ^>= 1.4.2
-- tasty-hspec 1.1.7 introduces breaking changes, which is why we have < 1.1.7 .
, tasty-hspec >= 1.1 && < 1.1.7
, tasty-quickcheck ^>= 0.10
other-modules:
TerminalTest
Paths_waspc
benchmark waspc-benchmarks benchmark waspc-benchmarks
import: common-all, common-exe import: common-all, common-exe
type: exitcode-stdio-1.0 type: exitcode-stdio-1.0