Challenge #1: Using Nullables

We’re going to start off nice and easy. For this first challenge, you’ll make the HomePageController return the home page when it receives a GET request. This challenge introduces the Nullables pattern. (The Parameterless Instantiation pattern makes a guest appearance, too.)

Instructions

1. Implement the "GET renders home page" test:

  1. Call HomePageController.getAsync().
  2. Assert that it returns homePageView.homePage().

2. Implement HomePageController.getAsync():

  1. Return homePageView.homePage().

3. Verify that it worked:

  1. Run the server from a command prompt:
    • Windows: .\serve_dev.cmd 5010 5011
    • Mac/Linux: ./serve_dev.sh 5010 5011
  2. Visit http://localhost:5010 in a browser.
  3. If it worked, you’ll see a page that says “Enter text to translate.”

Remember to commit your changes when you’re done.

API Documentation

const controller = new HomePageController(rot13Client, clock);

Create a HomePageController. Most code will use one of the factory methods, but your test should call the constructor directly. It gives you more control over the controller’s dependencies.

  • rot13Client (Rot13Client) - the ROT-13 client
  • clock (Clock) - the system clock
  • returns controller (HomePageController) - the controller
const response = await controller.getAsync(request, config);

Handle a browser’s GET request. In production, this method is called by WwwRouter.

  • request (HttpServerRequest) - browser’s request
  • config (WwwConfig) - configuration for this request
  • returns response (HttpResponse) - the response to serve
const rot13Client = Rot13Client.createNull();

Create a Nulled Rot13Client.

  • returns rot13Client (Rot13Client) - the ROT-13 client
const clock = Clock.createNull();

Create a Nulled Clock.

  • returns clock (Clock) - the clock
const request = HttpServerRequest.createNull();

Create a Nulled HttpServerRequest.

  • returns request (HttpServerRequest) - the request
const config = WwwConfig.createTestInstance();

Create a WwwConfig with default values.

  • returns config (WwwConfig): the config
const response = homePageView.homePage();

Render the home page.

  • returns response (HttpResponse) - the home page
assert.deepEqual(actual, expected);

Assert that two objects (or arrays) and all their recursive contents are equal.

  • actual (any) - the actual value
  • expected (any) - the expected value

JavaScript Primers

Hints

1
Your test will need a HomePageController.
You can construct it with new HomePageController().
it("GET renders home page", async () => {
	// Arrange
	const controller = new HomePageController(rot13Client, clock);

	// Act

	// Assert
});
2
The HomePageController constructor needs a Rot13Client and a Clock.
You can construct them with their createNull() factory methods.
it("GET renders home page", async () => {
	// Arrange
	const rot13Client = Rot13Client.createNull();
	const clock = Clock.createNull();
	const controller = new HomePageController(rot13Client, clock);

	// Act

	// Assert
});
3
Your test will need to simulate a GET request.
You can do that by calling controller.getAsync(). (Be sure to await it.)
it("GET renders home page", async () => {
  // Arrange
	const rot13Client = Rot13Client.createNull();
	const clock = Clock.createNull();
	const controller = new HomePageController(rot13Client, clock);

	// Act
	const response = await controller.getAsync(request, config);

	// Assert
});
4
getAsync() expects an HttpServerRequest object and a WwwConfig object.
They can be instantiated with their createNull() and createTestInstance() factory methods.
it("GET renders home page", async () => {
	// Arrange
	const rot13Client = Rot13Client.createNull();
	const clock = Clock.createNull();
	const controller = new HomePageController(rot13Client, clock);

	const request = HttpServerRequest.createNull();
	const config = WwwConfig.createTestInstance();

	// Act
	const response = await controller.getAsync(request, config);

	// Assert
});
5
You’ll need an “expected” value to compare against the results of getAsync().
You can use homePageView.homePage() as your expected value.
it("GET renders home page", async () => {
	// Arrange
	const rot13Client = Rot13Client.createNull();
	const clock = Clock.createNull();
	const controller = new HomePageController(rot13Client, clock);

	const request = HttpServerRequest.createNull();
	const config = WwwConfig.createTestInstance();

	// Act
	const response = await controller.getAsync(request, config);

	// Assert
	const expected = homePageView.homePage();
});
6
You’re ready to assert that the expected and actual values are the same. You need to check that the contents of the two objects are identical.
You can use assert.deepEqual() to make the comparison.
it("GET renders home page", async () => {
	// Arrange
	const rot13Client = Rot13Client.createNull();
	const clock = Clock.createNull();
	const controller = new HomePageController(rot13Client, clock);

	const request = HttpServerRequest.createNull();
	const config = WwwConfig.createTestInstance();

	// Act
	const response = await controller.getAsync(request, config);

	// Assert
	const expected = homePageView.homePage();
	assert.deepEqual(response, expected);
});
7
You’re ready to run the test.
It should fail, saying the response was undefined.

This means your production code isn’t returning a value.

8
HomePageController.getAsync() needs to return the home page.
You can do that by calling homePageView.homePage().
async getAsync(request, config) {
	return homePageView.homePage();
}

Complete Solution

Test code:
it("GET renders home page", async () => {
	// Arrange
	const rot13Client = Rot13Client.createNull();
	const clock = Clock.createNull();
	const controller = new HomePageController(rot13Client, clock);

	const request = HttpServerRequest.createNull();
	const config = WwwConfig.createTestInstance();

	// Act
	const response = await controller.getAsync(request, config);

	// Assert
	const expected = homePageView.homePage();
	assert.deepEqual(response, expected);
});
Production code (JavaScript):
async getAsync(request, config) {
  return homePageView.homePage();
}
Production code (TypeScript):
async getAsync(request: HttpServerRequest, config: WwwConfig): Promise<HttpServerResponse> {
  return homePageView.homePage();
}

Next challenge

Return to module overview