Challenge #8: Design Changes
Because you have State-Based Tests, you can change the design of your code without changing your tests. In this challenge, you’ll demonstrate that capability by changing your usage of Rot13Client
.
Instructions
- Change
HomePageController.postAsync()
to callrot13Client.transform()
instead ofrot13Client.transformAsync()
.
Remember to commit your changes when you’re done.
API Documentation
const { transformPromise, cancelFn } = rot13Client.transform(port, text, correlationId);
Call the ROT-13 service. This is just like transformAsync()
, except that it returns multiple values. Use it like this:
const { transformPromise } = rot13Client.transform(port, text, correlationId);
const transformedText = await transformPromise;
- 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 transformPromise
(Promise<string>)
- the encoded text returned by the ROT-13 service - returns cancelFn
(() => void)
- call this function to cancel the request
JavaScript Primers
No new concepts.
Hints
1
In your production code, call transform()
instead of transformAsync()
.
It’s really that easy.
async function transformAsync(rot13Client, config, log, userInput) {
try {
const { transformPromise } = rot13Client.transform(
config.rot13ServicePort,
userInput,
config.correlationId,
);
return await transformPromise;
}
catch (err) {
log.emergency({
message: "ROT-13 service error",
error: err,
});
return null;
}
}
Complete Solution
Production code (JavaScript):
export class HomePageController {
// ...
async postAsync(request, config) {
const log = config.log.bind({
endpoint: ENDPOINT,
method: "POST",
});
const userInput = await parseRequestBodyAsync(request, log);
if (userInput === null) return homePageView.homePage();
const output = await transformAsync(this._rot13Client, config, log, userInput);
if (output === null) return homePageView.homePage("ROT-13 service failed");
return homePageView.homePage(output);
}
}
async function parseRequestBodyAsync(request, log) {
const form = await request.readBodyAsUrlEncodedFormAsync();
const textFields = form[INPUT_FIELD_NAME];
try {
if (textFields === undefined) throw new Error(`'${INPUT_FIELD_NAME}' form field not found`);
if (textFields.length !== 1) throw new Error(`should only be one '${INPUT_FIELD_NAME}' form field`);
return textFields[0];
}
catch (err) {
log.monitor({
message: "form parse error",
error: err.message,
form,
});
return null;
}
}
async function transformAsync(rot13Client, config, log, userInput) {
try {
const { transformPromise } = rot13Client.transform(
config.rot13ServicePort,
userInput,
config.correlationId,
);
return await transformPromise;
}
catch (err) {
log.emergency({
message: "ROT-13 service error",
error: err,
});
return null;
}
}
Production code (TypeScript):
export class HomePageController {
// ...
async postAsync(request: HttpServerRequest, config: WwwConfig): Promise<HttpServerResponse> {
const log = config.log.bind({
endpoint: ENDPOINT,
method: "POST",
});
const userInput = await parseRequestBodyAsync(request, log);
if (userInput === null) return homePageView.homePage();
const output = await transformAsync(this._rot13Client, config, log, userInput);
if (output === null) return homePageView.homePage("ROT-13 service failed");
return homePageView.homePage(output);
}
}
async function parseRequestBodyAsync(request: HttpServerRequest, log: Log): Promise<string | null> {
const form = await request.readBodyAsUrlEncodedFormAsync();
const textFields = form[INPUT_FIELD_NAME];
try {
if (textFields === undefined) throw new Error(`'${INPUT_FIELD_NAME}' form field not found`);
if (textFields.length !== 1) throw new Error(`should only be one '${INPUT_FIELD_NAME}' form field`);
return textFields[0] as string;
}
catch (err) {
log.monitor({
message: "form parse error",
error: err.message,
form,
});
return null;
}
}
async function transformAsync(
rot13Client: Rot13Client,
config: WwwConfig,
log: Log,
userInput: string,
): Promise<string | null> {
try {
const { transformPromise } = rot13Client.transform(
config.rot13ServicePort,
userInput,
config.correlationId,
);
return await transformPromise;
}
catch (err) {
log.emergency({
message: "ROT-13 service error",
error: err,
});
return null;
}
}
Test code is unchanged.