Skip to content
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

feat: RequestSamples in docs #864

Merged
merged 6 commits into from
Feb 15, 2021
Merged

feat: RequestSamples in docs #864

merged 6 commits into from
Feb 15, 2021

Conversation

marcelltoth
Copy link
Contributor

Summary

Resolves #683

Not based on @mpodlasin's branch, I decided to take another approach.

Changes of plans

I made a change compared to what we discussed earlier: The solution is not using the IHttpRequest type for inter-component communication, but TryIt is now exposing a HAR directly. The reason is three factors combined:

  1. IHttpRequest is a bit of pain to work with. It imposes some format choices that neither fetch nor HAR are using, leading to a need for a back-and-forth conversion.
  2. It isn't a clearly defined format either, one of the most important pieces, body is left undefined. (It's generic and <T = any>.)
  3. Probably because of the above, we are not using it anywhere else either.

So I decided that HAR is probably a better format even for passing data around, and it's a lot simpler this way because RequestSamples needs a HAR anyway.

TODO

There's some cleanup to do in TryIt, it grew large and ugly, and also I probably put a lot of repetitive code in there. I'm working on that still but any suggestions are welcome.

@marcelltoth marcelltoth self-assigned this Feb 12, 2021
@marcelltoth marcelltoth requested a review from a team February 12, 2021 15:28
},
];
}

async function buildHarRequest({
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function requires a lot of cleanup, I know. And potentially a move to another file along with buildFetchRequest. (Which @mpodlasin did in his version as far as I remember.)

@@ -18,7 +18,7 @@ type MockUrlResult = { servicePath: string; operationPath?: string; id: number }
const bundledNodesUri = 'api/v1/projects/{workspaceSlug}/{projectSlug}/bundled-nodes/{uri}';
const mockActionsUrl = 'api/actions/branchNodeMockUrl';

export const TryIt = ({ node }: ITryItProps) => {
export const TryItContainer = ({ node }: ITryItProps) => {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved it next to the rest of TryIt as

  1. It's not a public component, the only place we use it is within StoplightProject, not even in platform. It's really a piece of StoplightProject, I was also considering creating a folder for it under components just like how we have API. Can do that if you prefer.
  2. We discussed previously that this container / component distinction is non-ideal for many reasons. It's hard to find the file, to know which one you're talking / reading about, and in general, they are all just components.

@netlify
Copy link

netlify bot commented Feb 12, 2021

Deploy preview for stoplight-elements ready!

Built with commit bf769a9

https://deploy-preview-864--stoplight-elements.netlify.app

@philsturgeon
Copy link
Contributor

Parameters are showing up escaped.

3EFD33EF-EBE5-46AC-8CEF-F93ED160359E

@marcelltoth
Copy link
Contributor Author

Parameters are showing up escaped.

Of course, that's because the default value for a path parameter is {pathParamName} which gets escaped to %pathParamName%7D. That's the same fallback behavior we have if you hit Send on such thing.

We can change the fallback if you'd like, but I think if we implement the Required property on params this will become a non-issue anyway.

Copy link
Contributor

@mpodlasin mpodlasin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks really good!

* Callback to retrieve the current request in a HAR format.
* Called whenever the request was changed in any way. Changing `httpOperation`, user entering parameter values, etc.
*/
onRequestChange?: (currentRequest: HarRequest) => void;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should test it?

To make sure it is being called with request object of proper shape?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely, maybe not exactly the shape - that's guaranteed by TypeScript - but also the contents, and whether it's called after an update.

And also the integration could be tested, whether StoplightProject / etc display RequestSamples at all.

I'll work on adding them.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, when I wrote "shape" I meant more contents etc. ;)

packages/elements/src/components/TryIt/TryIt.tsx Outdated Show resolved Hide resolved
@@ -0,0 +1,25 @@
import { Box } from '@stoplight/mosaic';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I worry about this inheritence approach over some other form of linking things up, and maybe I'm worrying wrong here, but it seems like when we add Response Sample we might end up with TryItWithRequestSamplesAndResponseExamples.tsx?

If there's a plan for response examples which im not aware of that will help us avoid that, then no biggy.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not inheritance, it's composition. And yes, that's what we'll end up with, and we'll likely call it TryItStack or something.
Just like how we call TocDocsAndTryItSideBySide a SidebarLayout. And a SidebarLayoutWithDataFetching is an API. That's how React works IMO.

My naming is non-ideal, that's a given. Feel free to suggest another.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name is not the concern, the concern is that the only way our different sub components can talk to each other is by making more and more super components. Whether the right term in TS is inheritance or composition, the problem here is Foo,FooAndBar, FooAndBarAndBaz,BazAndFoo,FooAndBaz, FooAllTheThings.

There have to be some alternative approaches to getting request samples into the api component that don’t include bunging it into Try It just so it has access to some of the data try it is creating, like the request it’s building. Do components not have any other way to share information?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still not sure I get your point. There are other ways, but the most elementary and go-to way you make react components communicate with eachother is via super components, by lifting state up. You learn this lesson while completing the official React tutorial The other the approaches (state management libraries, custom hooks, HOCs) are more advanced and to be used when the basic one is impractical.

You don't have to build one for each combination though. If you need a FooAndBarAndBaz you don't have to first build a FooAndBar.

bunging it into Try It just so it has access to some of the data try it is creating

It is not bunging into it, it is creating a component that holds them together. I could have pulled the state up all the way to SidebarLayout & StackedLayout & TryItContainer, then reduced the code-duplication with a custom hook, but that's an inferior solution IMO. (It still leaves some duplication in the components, the usage of the hook and the JSX stacking TryIt and RequestSamples on top of eachother, and it's also in general harder to comprehend than the most basic React pattern available: composition.) You don't use a cannon to kill a fly.

I double checked with the Team to make sure I'm not missing something here, but they, too don't see a problem with the structure here. If you are still concerned please schedule a call before the retro or after the planning meeting tomorrow and I'll be happy to discuss it.

@marcelltoth marcelltoth marked this pull request as draft February 15, 2021 14:31
@marcelltoth marcelltoth marked this pull request as ready for review February 15, 2021 16:31
Copy link
Contributor

@mmiask mmiask left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests and stories good look to me! RequestSamples already has its own test, so this should be enough.

As for the code itself, I see that @mpodlasin already reviewed this so I didn't touch that part

@@ -54,10 +56,11 @@ export const RequestSamples = React.memo<RequestSamplesProps>(({ request }) => {
</Panel.Titlebar>
<Panel.Content p={0}>
<CodeViewer
aria-label={requestSample ?? fallbackText}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the label take the full string as a value?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well it's not ideal, but that's how I thought we could provide a text-only alternative. (That's what label is.) Helpful for both testing and screen readers who may have a hard time reading the codeviewer. Ideally CodeViewer should handle this on its own, but this is an acceptable compromise IMO.

@marcelltoth marcelltoth merged commit 17232d7 into v7 Feb 15, 2021
@marcelltoth marcelltoth deleted the feat/request-samples-in-docs branch February 15, 2021 18:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants