get-convex / get-convex/r2

test.ts's register() registers actionRetrier at the wrong (top-level) name — deleteObject/store unusable in consumer tests

Open Beginner friendly
#72 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
49
Forks
26
Avg merge
6h 22m
Merged PRs (30d)
1

Description

**Environment**
- `@convex-dev/r2`: 0.10.2
- `@convex-dev/action-retrier`: 0.3.1 (transitive dep)
- `convex`: 1.42.1, `convex-test`: 0.0.53

**Repro**

```ts
import { convexTest } from "convex-test";
import r2Test from "@convex-dev/r2/test";
import schema from "./schema"; // app schema with `app.use(r2)` in convex.config.ts

const t = convexTest(schema);
r2Test.register(t); // the documented way to test code that uses the r2 client

await t.run(async (ctx) => {
await r2.deleteObject(ctx, "some-key"); // or r2.store(...)
});
```

**Expected:** the object's metadata row is deleted and a retry is scheduled.

**Actual:**
```
Error: Component "r2/actionRetrier" is not registered. Call "t.registerComponent".
```

**Root cause**

`r2`'s own `convex.config.ts` does:
```ts
const component = defineComponent("r2");
component.use(actionRetrier);
```
which nests action-retrier as a subcomponent — any app that does `app.use(r2)` gets it installed at the path `r2/actionRetrier`, which is what `r2.deleteObject()`'s internal `retrier.run(...)` resolves against at runtime.

But `src/test.ts`'s `register()` does:
```ts
export function register(t, name = "r2") {
t.registerComponent(name, schema, modules);
actionRetrier.register(t); // registers at actionRetrier's OWN default name: "actionRetrier"
}
```
`actionRetrier.register(t)` is called with no name override, so it registers the component at the top-level path `"actionRetrier"` — not the nested `"r2/actionRetrier"` path that's actually looked up. The two names never match, so `deleteObject`/`store` (or anything else routed through the retrier) throws in any consumer test that follows the documented `r2Test.register(t)` pattern.

**Suggested fix**

```ts
export function register(t, name = "r2") {
t.registerComponent(name, schema, modules);
actionRetrier.register(t, `${name}/actionRetrier`);
}
```

**Workaround** (for anyone hitting this in the meantime):
```ts
import actionRetrierTest from "@convex-dev/action-retrier/test";
r2Test.register(t);
actionRetrierTest.register(t, "r2/actionRetrier");
```

**Note:** the package's own `example/convex/setup.test.ts` never actually exercises `deleteObject`/`store` in a real test (just a placeholder `test("setup", () => {})`), which is presumably why this hasn't surfaced upstream.

Contributor guide

Open the contributing guide

Research direction

Start in src/test.ts at register(), then compare its component registration with the nested path configured in convex.config.ts. Extend the relevant test coverage beyond the placeholder in example/convex/setup.test.ts, exercising deleteObject or store through r2Test.register(t). Done means the consumer-style test no longer reports that r2/actionRetrier is unregistered.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
testing-qa
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
84/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.