test.ts's register() registers actionRetrier at the wrong (top-level) name — deleteObject/store unusable in consumer tests
- 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
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