In Part 2 you deployed a Worker with R2 Bucket
bindings. Now you’ll write integration tests that deploy the stack,
hit the live Worker over HTTP, and verify it works.
Use beforeAll with deploy to deploy your stack once before any
tests run:
test/integ.test.ts
import {
importbeforeAll
beforeAll,
importdeploy
deploy,
importexpect
expect,
importtest
test } from"alchemy/Test/Bun";
import*as
import Effect
Effectfrom"effect/Effect";
import
import Stack
Stackfrom"../alchemy.run.ts";
const
conststack: any
stack=
importbeforeAll
beforeAll(
importdeploy
deploy(
import Stack
Stack));
deploy(Stack) returns an Effect that plans and applies the stack.
beforeAll runs it once, then returns a lazy accessor you can
yield* inside each test to get the stack outputs.
The first run deploys the stack (or reuses the existing one if
already deployed). Subsequent runs are fast because Alchemy diffs
and skips unchanged resources.
Right now the stack stays deployed after tests finish. That’s great
locally — you can re-run tests instantly against the already-deployed
stack. But on CI you want to clean up.
Add afterAll with destroy, using skipIf to only tear down when
CI is set:
import {
importafterAll
afterAll,
importbeforeAll
beforeAll,
importdeploy
deploy,
importdestroy
destroy,
importexpect
expect,
importtest
test,
} from"alchemy/Test/Bun";
import*as
import Effect
Effectfrom"effect/Effect";
import*as
import HttpClient
HttpClientfrom"effect/unstable/http/HttpClient";
import*as
import HttpBody
HttpBodyfrom"effect/unstable/http/HttpBody";
import
import Stack
Stackfrom"../alchemy.run.ts";
const
conststack: any
stack=
importbeforeAll
beforeAll(
importdeploy
deploy(
import Stack
Stack));
importtest
test(
"PUT and GET round-trip an object",
import Effect
Effect.
any
gen(function* () {
const {
consturl: any
url } =yield*
conststack: any
stack;
const
constput: any
put=yield*
import HttpClient
HttpClient.
any
put(`${
consturl: any
url}/hello.txt`, {
body: any
body:
import HttpBody
HttpBody.
any
text("Hello, World!"),
});
importexpect
expect(
constput: any
put.
any
status).
any
toBe(201);
const
constget: any
get=yield*
import HttpClient
HttpClient.
any
get(`${
consturl: any
url}/hello.txt`);
importexpect
expect(yield*
constget: any
get.
any
text).
any
toBe("Hello, World!");
}),
);
importtest
test(
"GET missing key returns 404",
import Effect
Effect.
any
gen(function* () {
const {
consturl: any
url } =yield*
conststack: any
stack;
const
constresponse: any
response=yield*
import HttpClient
HttpClient.
any
get(`${
consturl: any
url}/no-such-key`);
importexpect
expect(
constresponse: any
response.
any
status).
any
toBe(404);
}),
);
importafterAll
afterAll.
any
skipIf(!
var process: NodeJS.Process
process.
NodeJS.Process.env: NodeJS.ProcessEnv
The process.env property returns an object containing the user environment.
See environ(7).
It is possible to modify this object, but such modifications will not be
reflected outside the Node.js process, or (unless explicitly requested)
to other Worker threads.
In other words, the following example would not work:
Assigning a property on process.env will implicitly convert the value
to a string. This behavior is deprecated. Future versions of Node.js may
throw an error when the value is not a string, number, or boolean.
import { env } from'node:process';
env.test =null;
console.log(env.test);
// => 'null'
env.test =undefined;
console.log(env.test);
// => 'undefined'
Use delete to delete a property from process.env.
import { env } from'node:process';
env.TEST=1;
deleteenv.TEST;
console.log(env.TEST);
// => undefined
On Windows operating systems, environment variables are case-insensitive.
import { env } from'node:process';
env.TEST=1;
console.log(env.test);
// => 1
Unless explicitly specified when creating a Worker instance,
each Worker thread has its own copy of process.env, based on its
parent thread's process.env, or whatever was specified as the env option
to the Worker constructor. Changes to process.env will not be visible
across Worker threads, and only the main thread can make changes that
are visible to the operating system or to native add-ons. On Windows, a copy of process.env on a Worker instance operates in a case-sensitive manner
unlike the main thread.
@since ― v0.1.27
env.
string | undefined
CI)(
importdestroy
destroy(
import Stack
Stack));
Locally — CI is not set, so skipIf skips the destroy. You
iterate fast against the live stack.
On CI — set CI=true and the stack is torn down automatically
after tests complete.