-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adds DevMock Service #7
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks like it could be very useful! only concerns are: bundle size and confusion over all the "devv" and "dev" terminology which seems like it's just mocking.
} from "./types.js"; | ||
import type { HandlerOverride } from "../types/internal.js"; | ||
|
||
export const createDevvRedis = ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggest calling this createDevvitRedis(). I don't think we use Devv anywhere in any of the codebases (rg -w Devv
comes up empty in shreddit and devvit repos). would love to not have a new term to grep. that said, I think everything here is pretty devvit-y so also consider newMockRedis(). same request for createDevvRedditApi(), DevvRedditApi, and everywhere else.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure about the naming here, because it's not a mockRedis, it's an instance that intercepts some redis requests, but fires real ones for the rest
So calling it mockRedis
might lead to an expectation that it only performs mock requests
Devv was a way to do the reference to devvit and developer at the same time, and I did not come up with a better option yet
@@ -0,0 +1,47 @@ | |||
## Dev Mock Service |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔕 suggest consider renaming to just "mocks". "dev" and "service" aren't buying me much. same thing with the subdirectory names which could be like mock-reddit instead of reddit-api-mock-service.
Redis, RedditAPI, or HTTP request. | ||
|
||
- In Dev mode (`DevMockMode.Dev`), handlers are applied for all requests with the matching method and ID (if available). | ||
- In Prod mode (`DevMockMode.Prod`), handlers are ignored. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this will encourage users to ship development-only code which may be large. I'd love to see this code fall out of apps for at least non-prerelease builds so there wasn't a wrong way to use it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How can I achieve this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like the introduction of a IS_PROD
or NODE_ENV
or IS_PLAYTEST
environmental variable that could be statically added at build time for tree shaking. Would be useful for more than just here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we can implement the IS_PLAYTEST and tree shaking separately, so it does not block this PR
devvRedis: RedisClient; | ||
devvRedditApi: RedditAPIClient; | ||
devvFetch: typeof fetch; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggest omitting the name devv prefix names (I make a comment about this later that it's a new term) because I don't think it's adding much useful context here. the user only needs to know which service is which and the typing covers that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is done to avoid confusion with the actual instances of redis
and reddit
Imagine the following scenario
const {redis, reddit} = context;
const { devvRedis, devvRedditApi, devvFetch } = DevMock.createService({...
Without the prefix there is a potential name collision
@@ -0,0 +1,6 @@ | |||
export type HttpOverride = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think users end up interacting with this type a bit? if so, consider documenting in JSDocs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a purely internal type, used to filter overrides based on the type
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really appreciate you taking the time to mock all of these services out! I think I need an example to understand it more. It looks like a design goal here was to avoid any alterations to public-api or the underlying build system which I understand. I do wish this is something we could do without touching the app code.
Some areas I'd consider exploring:
- Everything is mocked by default and a helpful error is throw if a network request is triggered. I think this is a sound default since an app only has one redis. Running the tests and triggering a bunch of writes to the DB would be bad vibes.
- Is there a way to alter the implementation details of these functions under the hood to make it transparent to the caller. For example, when running the tests, what if we found a way to mutate the context singleton automatically instead of putting a function in front of them.
This triggers some folks (and I totally understand), but I'm a fan of writing my own test harness that wrap describe
and it
. Then you have take care of isolating stuff in true integration tests (aka creating a new userId per test so you can parallelize them). Or, in this case, automatically restore all of the mocks. Something like this:
import { DevvitTestHarness } from 'somewhere'
DevvitTestHarness.it('should do xyz', [
DevMock.fetch.get("https://example.com", () =>
DevMock.httpResponse.ok({ fetched: "mock" }),
)
], () => {
expect('https://example.com').toBe('mock')
})
src/dev-mock-service/README.md
Outdated
@@ -0,0 +1,47 @@ | |||
## Dev Mock Service | |||
|
|||
Dev Mock Service Worker is an API mocking library that allows you to specify |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't actually a server worker is it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Whoops, bad copy paste 😅
Redis, RedditAPI, or HTTP request. | ||
|
||
- In Dev mode (`DevMockMode.Dev`), handlers are applied for all requests with the matching method and ID (if available). | ||
- In Prod mode (`DevMockMode.Prod`), handlers are ignored. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like the introduction of a IS_PROD
or NODE_ENV
or IS_PLAYTEST
environmental variable that could be statically added at build time for tree shaking. Would be useful for more than just here
import type { HandlerOverride } from "../types/index.js"; | ||
import type { ModMailService } from "@devvit/public-api"; | ||
|
||
class DevvRedditApi implements RedditApiInterface { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for all of the leg work here!
src/dev-mock-service/README.md
Outdated
|
||
```typescript | ||
const redisValue = await devvRedis.get("mocked_key"); // "Value from mocks!" | ||
const fetchedValue = await(await devvFetch("https://example.com")).json(); // {fetched: "mock"} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: double await sort of always been a weird pattern to me instead of an intermediate var. Especially to noobies
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just an example to demonstrate the responses
Do you think it's worth breaking into 3 sections? redis, reddit and fetch separately
src/dev-mock-service/README.md
Outdated
|
||
#### Setup | ||
|
||
Create devv versions of the API clients you want to mock. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this in the test file or in the real app code?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Real app code, this molecule is not intended to be used in unit tests (however it certainly can be)
Description:
Dev Mock Service Worker is an API mocking library that allows you to specify custom responses for any API calls inside your app.
🧪 Testing Steps / Validation
✅ Checks