Challenge #7: Partial Configuration

Tests will often only need to configure certain responses. The rest can be left as a default. In this challenge, you’ll update your embedded stub to support partially-configured responses.

Instructions

1. In the "provides defaults for partially-configured responses" test:

  1. Assert that an endpoint with no specific configuration has the following response:
    {
    	status: 501,
    	headers: {},
    	body: "",
    }

2. In the production code:

  1. Modify the embedded stub to make the test pass.

Remember to commit your changes when you’re done.

API Documentation

No new methods.

JavaScript Primers

No new concepts.

Hints

1
The test needs to configure an endpoint, then assert on it.
The configured response for the endpoint should be {}. That’s technically a configuration that has no status, headers, or body.
it("provides defaults for partially-configured responses", async () => {
	const client = HttpClient.createNull({
		"/endpoint": {},
	});

	const { response } = await requestAsync({ client, path: "/endpoint" });

	assert.deepEqual(response, {
		status: 501,
		headers: {},
		body: "",
	});
});
2
In JavaScript, the test is ready to run. (If you’re using TypeScript, skip this hint.)
It should fail, saying that it cannot convert undefined or null to object.
It’s failing in Object.entries(headers).

That’s because the endpoint technically has a configuration—it’s an empty object—but the headers property is undefined.

3
In TypeScript, the test is ready to run. (If you’re using JavaScript, skip this hint.)
It should fail, saying that the status and body are different than expected.
The actual values are the same as the placeholders in StubbedResponse.

That’s because the endpoint technically has a configuration—it’s an empty object—but the status, headers, and body are undefined. As a result, the ?? operators in StubbedResponse are assigning defaults.

4
Modify the production code to make the test pass.
You need to provide defaults in the case where the object exists, but specific fields don’t.
Object destructuring is probably the cleanest way to do that.
In TypeScript, this will replace the ?? operators.
class StubbedResponse extends EventEmitter {

	constructor({
		status = 501,
		headers = {},
		body = "",
	} = DEFAULT_NULLED_RESPONSE) {
		super();

		this.statusCode = status;
		this.headers = normalizeHeaders(headers);

		setImmediate(() => {
			this.emit("data", body);
			this.emit("end");
		});
	}

}

The TypeScript code is cleaner now:

class StubbedResponse extends EventEmitter implements NodeHttpResponse {

	statusCode: number;
	headers: HttpHeaders;

	constructor({
			status = 501,
			headers = {},
			body = "",
	}: NulledHttpClientResponse = DEFAULT_NULLED_RESPONSE) {
		super();

		this.statusCode = status;  // no more ??
		this.headers = normalizeHeaders(headers);  // no more ??

		setImmediate(() => {
			this.emit("data", body);
			this.emit("end");
		});
	}

}

Complete Solution

Test code:
it("provides defaults for partially-configured responses", async () => {
	const client = HttpClient.createNull({
		"/endpoint": {},
	});

	const { response } = await requestAsync({ client, path: "/endpoint" });

	assert.deepEqual(response, {
		status: 501,
		headers: {},
		body: "",
	});
});
Production code (JavaScript):
class StubbedResponse extends EventEmitter {

	constructor({
		status = 501,
		headers = {},
		body = "",
	} = DEFAULT_NULLED_RESPONSE) {
		super();

		this.statusCode = status;
		this.headers = normalizeHeaders(headers);

		setImmediate(() => {
			this.emit("data", body);
			this.emit("end");
		});
	}

}
Production code (TypeScript):
class StubbedResponse extends EventEmitter implements NodeHttpResponse {

	statusCode: number;
	headers: HttpHeaders;

	constructor({
			status = 501,
			headers = {},
			body = "",
	}: NulledHttpClientResponse = DEFAULT_NULLED_RESPONSE) {
		super();

		this.statusCode = status;
		this.headers = normalizeHeaders(headers);

		setImmediate(() => {
			this.emit("data", body);
			this.emit("end");
		});
	}

}

Next challenge

Return to module overview