Challenge #2a: Tracking Requests
Next, you’ll make HomePageController
respond to POST
requests. This is a lot more challenging! To make it easier, the challenge is broken up into three parts.
For part (a), make the HomePageController
call the ROT-13 service when it receives a POST
request. Use hard-coded parameters. You don’t need to worry about the response for this challenge. Don’t worry about errors or edge cases either.
This challenge introduces the Output Tracking pattern. You’ll use it to confirm that the HomePageController
calls the ROT-13 service.
Instructions
1. Implement the "POST asks ROT-13 service to transform text"
test:
- Call
HomePageController.postAsync()
. - Assert that it called the ROT-13 service using port
123
, the text"some text"
, and the correlation ID"0000-0000"
.
2. Implement HomePageController.postAsync()
:
- Call the ROT-13 service. Hardcode the port, text, and correlation ID.
Remember to commit your changes when you’re done.
API Documentation
const transformedText = await rot13Client.transformAsync(port, text, correlationId);
Call the ROT-13 service.
- port
(number)
- the port of the ROT-13 service - text
(string)
- the text to send to the ROT-13 service - correlationId
(string)
- a unique ID representing the user’s request - returns transformedText
(string)
- the encoded text returned by the ROT-13 service
const rot13Requests = rot13Client.trackRequests();
Track requests made by rot13Client
. This returns an OutputTracker
instance. Every time rot13Client
makes a request to the ROT-13 service, the OutputTracker
is updated with an object describing the request. The object is in this format:
{
port: 123,
text: "some text",
correlationId: "0000-0000",
}
- returns rot13Requests
(OutputTracker)
- the request tracker
const output = rot13Requests.data;
Returns an array with every request stored in the output tracker. Use it like this:
const rot13Requests = rot13Client.trackRequests();
// run code that makes requests
const output = rot13Requests.data;
- returns output
(array)
: the data
const response = await controller.postAsync(request, config);
Handle a browser’s POST
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
TypeScript Types
rot13Requests.data: Rot13ClientOutput[]
The requests stored in the output tracker.
interface Rot13ClientOutput {
port: number,
text: string,
correlationId: string,
cancelled?: boolean, // not relevant to this challenge
}
JavaScript Primers
No new concepts.
Hints
1
Your test will need a HomePageController
.
You can construct it just like in the last challenge.
it("POST asks ROT-13 service to transform text", async () => {
// Arrange
const rot13Client = Rot13Client.createNull();
const clock = Clock.createNull();
const controller = new HomePageController(rot13Client, clock);
// Act
// Assert
});
2
Your test will need to check whether the ROT-13 service was called.
You can track how the service is used by calling rot13Client.trackRequests()
.
You have to call rot13Client.trackRequests()
before the request is made.
it("POST asks ROT-13 service to transform text", async () => {
// Arrange
const rot13Client = Rot13Client.createNull();
const rot13Requests = rot13Client.trackRequests();
const clock = Clock.createNull();
const controller = new HomePageController(rot13Client, clock);
// Act
// Assert
});
3
Your test needs to simulate a POST
request.
You can do that by calling controller.postAsync()
. (Don’t forget to await
it.) You can ignore the return value.
it("POST asks ROT-13 service to transform text", async () => {
// Arrange
const rot13Client = Rot13Client.createNull();
const rot13Requests = rot13Client.trackRequests();
const clock = Clock.createNull();
const controller = new HomePageController(rot13Client, clock);
// Act
await controller.postAsync(request, config);
// Assert
});
4
Just like before, you’ll need HttpServerRequest
and WwwConfig
instances.
Use their createNull()
and createTestInstance()
factory methods.
it("POST asks ROT-13 service to transform text", async () => {
// Arrange
const rot13Client = Rot13Client.createNull();
const rot13Requests = rot13Client.trackRequests();
const clock = Clock.createNull();
const controller = new HomePageController(rot13Client, clock);
const request = HttpServerRequest.createNull();
const config = WwwConfig.createTestInstance();
// Act
await controller.postAsync(request, config);
// Assert
});
5
It’s time to assert that the ROT-13 service was called.
You’re tracking requests to the ROT-13 service in rot13Requests
.
You can access the tracking data with rot13Requests.data
.
You can use assert.deepEqual()
to compare rot13Requests.data
to an array with the expected requests.
it("POST asks ROT-13 service to transform text", async () => {
// Arrange
const rot13Client = Rot13Client.createNull();
const rot13Requests = rot13Client.trackRequests();
const clock = Clock.createNull();
const controller = new HomePageController(rot13Client, clock);
const request = HttpServerRequest.createNull();
const config = WwwConfig.createTestInstance();
// Act
await controller.postAsync(request, config);
// Assert
assert.deepEqual(rot13Requests.data, [{
port: 123,
text: "some text",
correlationId: "0000-0000",
}]);
});
6
You’re ready to run the test.
It should fail, saying the actual value is []
(an empty array).
This means your production code isn’t making any requests of the ROT-13 service.
7
Call the ROT-13 service in your production code. Remember, you only need to provide hardcoded values.
You can use this._rot13Client.transformAsync()
. Don’t forget to await
it.
async postAsync(request, config) {
await this._rot13Client.transformAsync(123, "some text", "0000-0000");
}
TypeScript needs a placeholder return:
// TypeScript
async postAsync(request: HttpServerRequest, config: WwwConfig): Promise<HttpServerResponse> {
await this._rot13Client.transformAsync(123, "some text", "0000-0000");
// DELETE ME: placeholder to satisfy compiler
return await HttpServerResponse.createPlainTextResponse({ status: 501, body: "not implemented" });
}
Complete Solution
Test code:
it("POST asks ROT-13 service to transform text", async () => {
// Arrange
const rot13Client = Rot13Client.createNull();
const rot13Requests = rot13Client.trackRequests();
const clock = Clock.createNull();
const controller = new HomePageController(rot13Client, clock);
const request = HttpServerRequest.createNull();
const config = WwwConfig.createTestInstance();
// Act
await controller.postAsync(request, config);
// Assert
assert.deepEqual(rot13Requests.data, [{
port: 123,
text: "some text",
correlationId: "0000-0000",
}]);
});
Production code (JavaScript):
async postAsync(request, config) {
await this._rot13Client.transformAsync(123, "some text", "0000-0000");
}
Production code (TypeScript):
async postAsync(request: HttpServerRequest, config: WwwConfig): Promise<HttpServerResponse> {
await this._rot13Client.transformAsync(123, "some text", "0000-0000");
// DELETE ME: placeholder to satisfy compiler
return await HttpServerResponse.createPlainTextResponse({ status: 501, body: "not implemented" });
}