Skip to content

Commit

Permalink
Bump versions to 2.9.0, update CHANGELOG.md and docs
Browse files Browse the repository at this point in the history
  • Loading branch information
mrbbot committed Sep 16, 2022
1 parent a98e0f5 commit 974c7c2
Show file tree
Hide file tree
Showing 34 changed files with 525 additions and 412 deletions.
11 changes: 11 additions & 0 deletions docs/src/content/get-started/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,17 @@ Specifying a script is optional when `--repl` is enabled, but may be required if
you're using Durable Objects. If you're using an ES module format worker,
bindings will be accessible via the `env` global variable.

The REPL can be configured using environment variables similar to
[Node.js](https://nodejs.org/api/repl.html#environment-variable-options):

- `MINIFLARE_REPL_HISTORY`: path to save REPL history to. Setting this to an
empty string disables persistent REPL history. Defaults to
`~/.mf_repl_history`.
- `MINIFLARE_REPL_HISTORY_SIZE`: number of history lines to save if persistent
REPL history is enabled. Defaults to `1000`.
- `MINIFLARE_REPL_MODE`: either `sloppy` or `strict`. Defaults to `sloppy`
allowing non-strict code to run.

```sh
$ miniflare --repl --kv TEST_NAMESPACE
> await new HTMLRewriter().on("p", {
Expand Down
59 changes: 54 additions & 5 deletions docs/src/content/testing/jest.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,10 @@ $ NODE_OPTIONS=--experimental-vm-modules npx jest
## Isolated Storage

The Miniflare environment will use isolated storage for KV namespaces, caches,
and Durable Objects in each test. This essentially means any changes you make in
a test or `describe`-block are automatically undone afterwards. The isolated
storage is copied from the parent `describe`-block, allowing you to seed data in
`beforeAll` hooks.
Durable Objects and D1 databases in each test. This essentially means any
changes you make in a test or `describe`-block are automatically undone
afterwards. The isolated storage is copied from the parent `describe`-block,
allowing you to seed data in `beforeAll` hooks.

As an example, consider the following tests:

Expand Down Expand Up @@ -188,7 +188,7 @@ export class TestObject {
}

async fetch() {
const count = (await this.storage.get("count")) + 1;
const count = ((await this.storage.get("count")) ?? 0) + 1;
this.storage.put("count", count);
return new Response(count.toString());
}
Expand Down Expand Up @@ -264,6 +264,55 @@ test("flushes alarms", async () => {
});
```
### Constructing Durable Objects Directly
Alternatively, you can construct instances of your Durable Object using
`DurableObjectState`s returned by the `getMiniflareDurableObjectState()` global
function. This allows you to call instance methods and access ephemeral state
directly. Wrapping calls to instance methods with
`runWithMiniflareDurableObjectGates()` will close the Durable Object's input
gate, and wait for the output gate to open before resolving. Make sure to use
this when calling your `fetch()` method.
```js
---
filename: test / index.spec.js
---
import { TestObject } from "../src/index.mjs";

test("increments count", async () => {
const env = getMiniflareBindings();
// Use standard Durable Object bindings to generate IDs
const id = env.TEST_OBJECT.newUniqueId();

// Get DurableObjectState, and seed Durable Object storage
// (isolated storage rules from above also apply)
const state = await getMiniflareDurableObjectState(id);
await state.storage.put("count", 3);

// Construct object directly
const object = new TestObject(state, env);

// Concurrently increment the count twice. Wrapping `object.fetch`
// calls with `runWithMiniflareDurableObjectGates(state, ...)`
// closes `object`'s input gate when fetching, preventing race
// conditions.
const [res1, res2] = await Promise.all([
runWithMiniflareDurableObjectGates(state, () => {
return object.fetch(new Request("http://localhost/"));
}),
runWithMiniflareDurableObjectGates(state, () => {
return object.fetch(new Request("http://localhost/"));
}),
]);
expect(await res1.text()).toBe("4");
expect(await res2.text()).toBe("5");

// Check storage updated twice
expect(await state.storage.get("count")).toBe(5);
});
```
## Mocking Outbound `fetch` Requests
Miniflare allows you to substitute custom `Response`s for `fetch()` calls using
Expand Down
60 changes: 56 additions & 4 deletions docs/src/content/testing/vitest.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,10 @@ $ NODE_OPTIONS=--experimental-vm-modules npx vitest run
## Isolated Storage

The Miniflare environment will use isolated storage for KV namespaces, caches,
and Durable Objects in each test. This essentially means any changes you make in
a test or `describe`-block are automatically undone afterwards. The isolated
storage is copied from the parent `describe`-block, allowing you to seed data in
`beforeAll` hooks.
Durable Objects and D1 databases in each test. This essentially means any
changes you make in a test or `describe`-block are automatically undone
afterwards. The isolated storage is copied from the parent `describe`-block,
allowing you to seed data in `beforeAll` hooks.

<Aside type="warning" header="Warning">

Expand Down Expand Up @@ -294,6 +294,58 @@ test("flushes alarms", async () => {
});
```
### Constructing Durable Objects Directly
Alternatively, you can construct instances of your Durable Object using
`DurableObjectState`s returned by the `getMiniflareDurableObjectState()` global
function. This allows you to call instance methods and access ephemeral state
directly. Wrapping calls to instance methods with
`runWithMiniflareDurableObjectGates()` will close the Durable Object's input
gate, and wait for the output gate to open before resolving. Make sure to use
this when calling your `fetch()` method.
```js
---
filename: test / index.spec.js
---
import { expect, test } from "vitest";
const describe = setupMiniflareIsolatedStorage();

import { TestObject } from "../src/index.mjs";

test("increments count", async () => {
const env = getMiniflareBindings();
// Use standard Durable Object bindings to generate IDs
const id = env.TEST_OBJECT.newUniqueId();

// Get DurableObjectState, and seed Durable Object storage
// (isolated storage rules from above also apply)
const state = await getMiniflareDurableObjectState(id);
await state.storage.put("count", 3);

// Construct object directly
const object = new TestObject(state, env);

// Concurrently increment the count twice. Wrapping `object.fetch`
// calls with `runWithMiniflareDurableObjectGates(state, ...)`
// closes `object`'s input gate when fetching, preventing race
// conditions.
const [res1, res2] = await Promise.all([
runWithMiniflareDurableObjectGates(state, () => {
return object.fetch(new Request("http://localhost/"));
}),
runWithMiniflareDurableObjectGates(state, () => {
return object.fetch(new Request("http://localhost/"));
}),
]);
expect(await res1.text()).toBe("4");
expect(await res2.text()).toBe("5");

// Check storage updated twice
expect(await state.storage.get("count")).toBe(5);
});
```
## Mocking Outbound `fetch` Requests
Miniflare allows you to substitute custom `Response`s for `fetch()` calls using
Expand Down
Loading

0 comments on commit 974c7c2

Please sign in to comment.