Skip to content

Commit

Permalink
Merge pull request #30 from mbland/jsdoc
Browse files Browse the repository at this point in the history
Start adding JSDoc to strcalc/src/main/frontend
  • Loading branch information
mbland committed Dec 3, 2023
2 parents 2f05c23 + 98412d9 commit ee5973f
Show file tree
Hide file tree
Showing 15 changed files with 422 additions and 60 deletions.
61 changes: 13 additions & 48 deletions README.md
Expand Up @@ -95,6 +95,19 @@ On macOS and Linux, I installed the latest JDK 21.0.1 from [Eclipse
Temurin™ Latest Releases][] via [SDKMAN!][]. On Windows, I downloaded it
from the [Download the Microsoft Build of OpenJDK][] page.

### Setup the frontend JavaScript environment

See [strcalc/src/main/frontend/README.md](strcalc/src/main/frontend/README.md)
for guidance on setting up the frontend development and build environment.

The frontend environment isn't required for `./gradlew test`, which runs the
small Java unit tests from the exercise. Conversely, the Java environment isn't
strictly required to develop, build, and test the frontend in isolation.

However, you will need to have both environments installed to build most of the
Gradle targets. This includes the medium integration and large system tests in
`strcalc/src/test/java`, which also depend on the frontend build.

### Optional: Install the [Tomcat servlet container][]

_This step is optional, as the [bin/tomcat-docker.sh][] script will run Tomcat
Expand Down Expand Up @@ -739,40 +752,6 @@ plugin:
- Configure the selected plugin to process the downloaded
`jacocoXmlTestReport.xml` file.

## Setup frontend JavaScript environment

[Node.js][] is a JavaScript runtime environment. [pnpm][] is a Node.js package
manager.

- TODO(mbland): Document usage of [nodenv][], [Homebrew][]

[ESLint][] is a tool for formatting and linting JavaScript code.

[Vite][] is a JavaScript development and deployment platform. [Vitest][] is a
JavaScript test framework and runner designed to work well with Vite.

Though I've had a great experience testing with Mocha, Chai, and Sinon in the
past, setting them up involves a bit more work.

- [Mocha test framework][]
- [Chai test assertion library][]
- [Sinon test double framework][]

In contrast, Vitest is largely modeled after the popular Jest framework and is a
breeze to set up, especially for existing Vite projects. Like Jest, it contains
its own assertion library and test double framework. For the purpose of a
teaching example for people who may never have tested JavaScript before, but
aren't using React, Vitest seems much more accessible.

Suffice it to say, ESLint and Vite have IntelliJ IDEA and Visual Studio
Code support:

- ESLint in IntelliJ IDEA: _Settings > Languages & Frameworks >
JavaScript > Code Quality Tools > ESLint_
- [ESLint extension for Visual Studio Code][]
- [Vite IntelliJ plugin][]
- [Vite extension for Visual Studio Code][]

## Adding large tests

Coming soon...
Expand All @@ -786,7 +765,6 @@ TODO(mbland): Document how the following are configured:
(for medium tests)
- [node-gradle/gradle-node-plugin][]


## Implementing core logic using Test Driven Development and unit tests

Coming soon...
Expand Down Expand Up @@ -879,17 +857,4 @@ Coming soon...
[coverallsapp/github-action GitHub Actions plugin]: https://github.com/coverallsapp/github-action
[GitHub Actions marketplace]: https://github.com/marketplace?type=actions
[JaCoCo related GitHub Actions plugins]: https://github.com/marketplace?category=&type=actions&verification=&query=jacoco
[Node.js]: https://nodejs.org/
[pnpm]: https://pnpm.io/
[nodenv]: https://github.com/nodenv/nodenv
[homebrew]: https://brew.sh/
[ESLint]: https://eslint.style/
[Vite]: https://vitejs.dev/
[Vitest]: https://vitest.dev/
[Mocha test framework]: https://mochajs.org/
[Chai test assertion library]: https://www.chaijs.com/
[Sinon test double framework]: https://sinonjs.org/
[ESLint extension for Visual Studio Code]: https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint
[Vite IntelliJ plugin]: https://plugins.jetbrains.com/plugin/20011-vite
[Vite extension for Visual Studio Code]: https://marketplace.visualstudio.com/items?itemName=antfu.vite
[Selenium: Design patterns and development strategies]: https://www.selenium.dev/documentation/test_practices/design_strategies/
16 changes: 13 additions & 3 deletions strcalc/src/main/frontend/.eslintrc
@@ -1,4 +1,4 @@
{ "extends": "eslint:recommended",
{
"env" : {
"browser" : true,
"node": true,
Expand All @@ -8,12 +8,22 @@
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": [ "@stylistic/js", "vitest" ],
"plugins": [
"@stylistic/js",
"vitest",
"jsdoc"
],
"extends": [
"eslint:recommended",
"plugin:jsdoc/recommended"
],
"overrides": [
{
"files": ["**/*.test.js"],
"plugins": ["vitest"],
"extends": ["plugin:vitest/recommended"]
"extends": [
"plugin:vitest/recommended"
]
}
],
"rules" : {
Expand Down
141 changes: 141 additions & 0 deletions strcalc/src/main/frontend/README.md
@@ -0,0 +1,141 @@
# Tomcat Servlet Testing Example Frontend

This is the frontend component of the [mbland/tomcat-servlet-testing-example][]
project. For details on the larger project and the backend component, see the
[top level README.md][].

The Java environment isn't strictly required to develop, build, and test the
frontend in isolation. Conversely, the frontend environment isn't required for
`./gradlew test`, which runs the small Java unit tests from the exercise.

However, you will need to have both environments installed to build most of the
Gradle targets. This includes the medium integration and large system tests in
`strcalc/src/test/java`, which also depend on the frontend build.

## Setup frontend JavaScript environment

[Node.js][] is a JavaScript runtime environment. [pnpm][] is a Node.js package
manager.

- TODO(mbland): Document usage of [nodenv][], [Homebrew][]

[ESLint][] is a tool for formatting and linting JavaScript code.

[Vite][] is a JavaScript development and deployment platform. [Vitest][] is a
JavaScript test framework and runner designed to work well with Vite.

Though I've had a great experience testing with Mocha, Chai, and Sinon in the
past, setting them up involves a bit more work.

- [Mocha test framework][]
- [Chai test assertion library][]
- [Sinon test double framework][]

In contrast, Vitest is largely modeled after the popular Jest framework and is a
breeze to set up, especially for existing Vite projects. Like Jest, it contains
its own assertion library and test double framework. For the purpose of a
teaching example for people who may never have tested JavaScript before, but
aren't using React, Vitest seems much more accessible.

Suffice it to say, ESLint and Vite have IntelliJ IDEA and Visual Studio
Code support:

- ESLint in IntelliJ IDEA: _Settings > Languages & Frameworks >
JavaScript > Code Quality Tools > ESLint_
- [ESLint extension for Visual Studio Code][]
- [Vite IntelliJ plugin][]
- [Vite extension for Visual Studio Code][]

## JSDoc documentation

The inline documentation is written using the [JSDoc][] format. [IntelliJ IDEA][]
and [Visual Studio Code][] both support JSDoc natively, so there's no need to
install any extra tools.

However, if you want to generate the HTML version of the documentation, you can run:

```sh
# If you've never installed a global package with pnpm before
# - https://pnpm.io/cli/setup
$ pnpm setup
[...snip...]

# Install JSDoc globally
$ pnpm add -g jsdoc
[...snip...]

# Run the "jsdoc" script from package.json, where "0.0.0" is whatever the
# current version is now
$ pnpm jsdoc

> tomcat-servlet-testing-example-frontend@0.0.0 jsdoc .../tomcat-servlet-testing-example/strcalc/src/main/frontend
> bin/jsdoc -c ./jsdoc.json .

../../../build/jsdoc/tomcat-servlet-testing-example-frontend/0.0.0/index.html
```

To open the resulting file on macOS, Linux, or a [Bash][]-based environment on
Windows (e.g., [Git for Windows][], [MSYS2][]):

```sh
open ../../../build/jsdoc/tomcat-servlet-testing-example-frontend/0.0.0/index.html
```

On [Windows Subsystem for Linux][]:

```sh
# If you haven't installed the Windows Subsystem for Linux Utilities
sudo apt install wslu

# Once WSLU is installed
wslview ../../../build/jsdoc/tomcat-servlet-testing-example-frontend/0.0.0/index.html
```

To open it in the [Windows Command Prompt][] or [PowerShell][], just enter the
path directly at the prompt, or prefix it with [`start`][]:

```bat
..\..\..\build\jsdoc\tomcat-servlet-testing-example-frontend\0.0.0\index.html
```

### JSDoc eslint plugin

Note that this project uses [eslint-plugin-jsdoc][] to enforce JSDoc style rules.

### JSDoc quirk

JSDoc can't yet handle objects defined in an `export default` declaration
without the `@function` tag:

- <https://github.com/jsdoc/jsdoc/issues/1539>
- <https://github.com/jsdoc/jsdoc/issues/2038>

When that bug gets fixed, I'll remove this comment and the explicit `@function`
decorators.

[mbland/tomcat-servlet-testing-example]: https://github.com/mbland/tomcat-servlet-testing-example
[top level README.md]: ../../../../README.md
[Node.js]: https://nodejs.org/
[pnpm]: https://pnpm.io/
[nodenv]: https://github.com/nodenv/nodenv
[homebrew]: https://brew.sh/
[ESLint]: https://eslint.style/
[Vite]: https://vitejs.dev/
[Vitest]: https://vitest.dev/
[Mocha test framework]: https://mochajs.org/
[Chai test assertion library]: https://www.chaijs.com/
[Sinon test double framework]: https://sinonjs.org/
[ESLint extension for Visual Studio Code]: https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint
[Vite IntelliJ plugin]: https://plugins.jetbrains.com/plugin/20011-vite
[Vite extension for Visual Studio Code]: https://marketplace.visualstudio.com/items?itemName=antfu.vite
[JSDoc]: https://jsdoc.app/
[IntelliJ IDEA]: https://www.jetbrains.com/idea/
[Visual Studio Code]: https://code.visualstudio.com/
[Bash]: https://www.gnu.org/software/bash/
[Git for Windows]: https://git-scm.com/download/win
[MSYS2]: https://www.msys2.org/
[Windows Subsystem for Linux]: https://learn.microsoft.com/windows/wsl/
[Windows Command Prompt]: https://learn.microsoft.com/windows-server/administration/windows-commands/windows-commands
[PowerShell]: https://learn.microsoft.com/powershell/
[`start`]: https://learn.microsoft.com/windows-server/administration/windows-commands/start
[eslint-plugin-jsdoc]: https://www.npmjs.com/package/eslint-plugin-jsdoc
56 changes: 56 additions & 0 deletions strcalc/src/main/frontend/bin/jsdoc
@@ -0,0 +1,56 @@
#!/usr/bin/env bash
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
#
# jsdoc wrapper used by the "jsdoc" package.json script
#
# Removes the existing destination directory if it exists, runs JSDoc, and emits
# the relative path to the generated index.html file.
#
# Prompts the user to install JSDoc if not present. It's not a package.json
# devDependency because it seems that many folks browse JSDoc in their IDE
# without needing to generate the HTML version.

if ! command -v jsdoc > /dev/null; then
echo \"Run 'pnpm add -g jsdoc' to install JSDoc: https://jsdoc.app\"
exit 1
fi

ARGS=()
DESTINATION=""

# Discover the output directory, since JSDoc doesn't have a setting to emit it.
while [[ "$#" -ne 0 ]]; do
curArg="$1"
shift
ARGS+=("$curArg")

case "$curArg" in
-c|--configure)
if [[ -z "$DESTINATION" ]]; then
# All bets are off if the destination property contains an escaped '"' or
# there's more than one "destination" property defined.
DESTINATION="$(sed -ne 's/.*"destination": *"\([^"]*\)".*/\1/p' < "$1")"
fi
ARGS+=("$1")
shift
;;
-d|--destination)
DESTINATION="$1"
ARGS+=("$1")
shift
;;
*)
;;
esac
done

# "out" is the JSDoc default directory.
DESTINATION="${DESTINATION:-out}"
rm -rf "$DESTINATION"

if jsdoc "${ARGS[@]}"; then
exec find "$DESTINATION" -name index.html -print -quit
fi
13 changes: 13 additions & 0 deletions strcalc/src/main/frontend/components/helpers.js
Expand Up @@ -7,6 +7,19 @@
* - https://handlebarsjs.com/guide/expressions.html#helpers
*/

/**
* Exports a function to register Handlebars helpers.
*
* Passed to rollup-plugin-handlebars-precompiler via options.helpers.
* @see https://handlebarsjs.com/api-reference/runtime.html#handlebars-registerhelper-name-helper
* @module components/helpers
*/

/**
* Registers helper functions via Handlebars.registerHelper().
* @function default
* @param {module} Handlebars The Handlebars runtime module
*/
export default function(Handlebars) {
Handlebars.registerHelper('link', function(text, options) {
const attrs = Object.keys(options.hash).map(key => {
Expand Down
8 changes: 8 additions & 0 deletions strcalc/src/main/frontend/components/placeholder.js
Expand Up @@ -2,9 +2,17 @@
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

/**
* The placeholder component for the String Calculator application
*
* This is an example of a JavaScript class representing a web page component,
* implemented using a precompiled Handlebars template.
*
* Implemented using Handlebars template compiled via
* rollup-plugin-handlebars-precompiler.
* @module placeholder
*/

import Template from './placeholder.hbs'
Expand Down
12 changes: 12 additions & 0 deletions strcalc/src/main/frontend/init.js
Expand Up @@ -5,8 +5,20 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/

/**
* Initializer for the String Calculator web application.
* @module init
*/

import Placeholder from './components/placeholder'

/**
* Instantiates the top level objects and calls the `init()` method on each.
*
* This is a teaching example that contains minimal business logic in order to
* demonstrate how to design much larger applications for testability.
* @param {Document} document The DOM window.document object
*/
export default function initApp(document) {
new Placeholder(document).init()
}
14 changes: 14 additions & 0 deletions strcalc/src/main/frontend/jsdoc.json
@@ -0,0 +1,14 @@
{
"plugins": [ "plugins/markdown" ],
"recurseDepth": 10,
"source": {
"includePattern": ".+\\.js$",
"exclude": ["node_modules"]
},
"opts": {
"destination": "../../../build/jsdoc",
"recurse": true,
"readme": "README.md",
"package": "package.json"
}
}

0 comments on commit ee5973f

Please sign in to comment.