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

DOP-3903: API Changelog Support to omit entries #919

Merged
merged 21 commits into from
Oct 10, 2023
Merged

Conversation

anabellabuckvar
Copy link
Collaborator

@anabellabuckvar anabellabuckvar commented Sep 26, 2023

Stories/Links:

DOP-3903

Current Behavior:

Production API Changelog

Staging Links:

Staging API changelog

Notes:

Atlas App Services Function fetchOADiff was updated in the process of completing this ticket, please review it as well before giving a LGTM!

@anabellabuckvar anabellabuckvar changed the title DOP-3938: API Changelog Support to omit entries DOP-3903: API Changelog Support to omit entries Sep 26, 2023
Copy link
Collaborator

@caesarbell caesarbell left a comment

Choose a reason for hiding this comment

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

Is there a way you can provide a staging link to verify the success of this PR?

@caesarbell
Copy link
Collaborator

I am sorry, I just noticed this PR is a Draff.

@anabellabuckvar anabellabuckvar marked this pull request as ready for review October 2, 2023 21:02
Copy link
Collaborator

@branberry branberry left a comment

Choose a reason for hiding this comment

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

Overall, this is really good! I left some comments about some of the checks, and a small concern I had about the updating of values in the map calls.

Also, I would recommend adding unit tests to ensure that it's working as expected.

gatsby-node.js Outdated

const hideChanges = (changelog) => {
const versionUpdate = (version) => {
if (version !== null && version.changes !== null) {
Copy link
Collaborator

@branberry branberry Oct 3, 2023

Choose a reason for hiding this comment

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

Updated if statement

I don't believe version will be null, so we can omit the check here. Also, for version.changes, you'll want to check if it's undefined. The simplest way to do this is to check if it is falsy (if (!version.changes))

JavaScript is weird in that there is both null and undefined which aren't exactly the same thing, even though the behavior is similar. More often than not, if we want to check if a property exists, we will want to check if it is undefined as opposed to null. Another option is to simply check if the variable or property is falsy. This means in the if statement you can do something like this:

 if (version && version.changes) { .... }

JavaScript will convert !version and !version.changes to a boolean value. If the value (for example, version), is null, undefined, 0, NaN, or ''(an empty string), the if statement will coerce these values tofalse`.

Here's a helpful link to describe what I am referring to in more detail

gatsby-node.js Outdated

//pathUpdate takes the array of versions from the specific path passed in and takes each version and runs versionUpdate on it
const pathUpdate = (path) => {
path.versions = path.versions.map(versionUpdate);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Mutating the current object that is provided in the map could lead to unintended side effects. Just to err on the side of caution, you can make a copy of path and update that. You can make a copy like so:

const updatedPath = {...path}

gatsby-node.js Outdated
const dateUpdate = (dateSection) => {
dateSection.paths = dateSection.paths.map(pathUpdate);
dateSection.paths = dateSection.paths.filter(
(path) => path !== null && path.versions !== null && path.versions.length !== 0
Copy link
Collaborator

Choose a reason for hiding this comment

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

We can omit path !== null, we'll want to also check if path.versions is also undefined

gatsby-node.js Outdated
//changelog is the json file with everything in it. Map at this level takes each date section and runs dateUpdate on it
changelog = changelog.map(dateUpdate);
return changelog.filter(
(dateSection) => dateSection !== null && dateSection.paths !== null && dateSection.paths.length !== 0
Copy link
Collaborator

Choose a reason for hiding this comment

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

We can omit dateSection !== null, we'll want to also check if dateSection.paths is also undefined

@@ -72,6 +72,15 @@ const StyledLoadingSkeleton = styled.div`
const OpenAPIChangelog = () => {
const { snootyEnv } = useSiteMetadata();
const { index = {}, changelog = [], changelogResourcesList = [] } = useChangelogData();
//updatedChangeLog = changelog.filter()
//console.log(changelog);
Copy link
Collaborator

Choose a reason for hiding this comment

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

This can be removed

@@ -3,10 +3,22 @@ import { fetchOADiff } from '../../../utils/realm';
import useChangelogData from '../../../utils/use-changelog-data';
import { getDiffRequestFormat } from './getDiffRequestFormat';

//filter hideFromChangelog in diff
const hideDiffChanges = (diffData) => {
const pathUpdate = (path) => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Logic looks like it's the same from the filtering of the changelog in gatsby-node.js. Maybe this function could be put into another file and then imported where needed.

@branberry branberry self-requested a review October 3, 2023 14:59
Copy link
Collaborator

@mmeigs mmeigs left a comment

Choose a reason for hiding this comment

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

Mainly a comment below agreeing and expanding on what Brandon mentioned!
Also, just reminding here that this merge with the latest master will be an odd one. This will mostly all go in plugins/utils/openapi I would guess.

gatsby-node.js Outdated
Comment on lines 119 to 120

const changelog = hideChanges(unfilteredChangelog);
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think everything @branberry said is true!! Here's one way to go about it easily and combine all he said.

For each spot where you're mapping (and changing by reference an entire object) you could change this each time to a safe action such as Brandon said for all of them, ie:

path.versions = path.versions.map(versionUpdate);

would become

const updatedPath = {
  ...path,
  versions: path.versions.map(versionUpdate)
}

and then return the updatedPath rather than the path

Then, for each of these (four?) spots where you're filtering, you can condense your three statements (truthy property, truthy nested property, and not an empty array) to something like

path.versions.filter((version) => version.changes?.length !== 0);

For absolute extra security, you could put another optional chain behind version, ie version?.changes?.length but that would be so odd and a very bad error on APIx's part if they had an array that included nulls or empties.

export const useFetchDiff = (resourceVersionOne, resourceVersionTwo, setIsLoading, setToastOpen, snootyEnv) => {
const { index = {}, mostRecentDiff = {} } = useChangelogData();
const [diff, setDiff] = useState([]);

Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: I'm ridiculous but I like this empty line for my brain to separate :)

Comment on lines 23 to 35
setDiff(response);
setDiff(hideDiffChanges(response));
Copy link
Collaborator

Choose a reason for hiding this comment

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

Total nit and stylistic choice, but for readability, I prefer to separate two invocations of functions. Maybe:

const filteredDiff = hideDiffChanges(response);
setDiff(filteredDiff);

@anabellabuckvar anabellabuckvar removed the request for review from caesarbell October 3, 2023 17:31
@anabellabuckvar anabellabuckvar requested a review from mmeigs October 3, 2023 21:42
Copy link
Collaborator

@branberry branberry left a comment

Choose a reason for hiding this comment

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

LGTM!

gatsby-node.js Outdated
const hideDiffChanges = (diffData) => {
const pathUpdate = (path) => {
const updatedPath = { ...path };
if (path?.changes) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

We shouldn't need an optional chain here!

gatsby-node.js Outdated
};

const updatedDiffData = diffData.map(pathUpdate);
return updatedDiffData.filter((path) => path?.changes?.length);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here, no need for the optional chain on path, but yes, keep the one on changes!

Comment on lines 1101 to 1117
<div
class="emotion-57 emotion-58 emotion-59"
>
Removed
</div>
</div>
<ul
class="emotion-60 emotion-61"
>
<li
class="emotion-62 emotion-63"
>
Resource version 2023-01-01 was removed, latest available resource version is 2023-02-01
</li>
</ul>
</div>
</section>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Hmm, this makes me slightly worried? I believe this is the change you added that has the hideFromChangelog flag as true? So, it shouldn't be in the snapshot

Comment on lines 290 to 303
Removed
</div>
</div>
<ul
class="emotion-17 emotion-18"
>
<li
class="emotion-19 emotion-20"
>
Resource version 2023-01-01 was removed, latest available resource version is 2023-02-01
</li>
</ul>
</div>
</section>
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same here

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I redid the tests, the snapshots should be clearer now.

Comment on lines 54 to 65
const hideDiffChanges = (diffData) => {
const pathUpdate = (path) => {
const updatedPath = { ...path };
if (path?.changes) {
updatedPath.changes = path.changes.filter((change) => !change.hideFromChangelog);
}
return updatedPath;
};

const updatedDiffData = diffData.map(pathUpdate);
return updatedDiffData.filter((path) => path.changes?.length);
};
Copy link
Collaborator

Choose a reason for hiding this comment

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

Oh, and reminder to have this function somewhere where it can be exported so we can reuse it rather than declaring it twice!

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Refactored the functions, let me know what you think!

@anabellabuckvar anabellabuckvar requested a review from mmeigs October 6, 2023 17:52
Copy link
Collaborator

@mmeigs mmeigs left a comment

Choose a reason for hiding this comment

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

Two main things about placement of hiding the changes!

  1. You can/should use the hideChanges util function in gatsby-node! That way it only occurs once, server-side.
  2. We still need to use hideDiffChanges in gatsby-node as well. Otherwise, the most recent diff will not have the changes hidden.

Comment on lines 57 to 89
// it('does not render all version changelog changes with "hideFromChangelog=true"', () => {
// const hiddenChanges = mockChangelog.reduce((acc, date) => {
// date.paths.forEach((path) =>
// path.versions.forEach((version) =>
// version.changes.forEach((change) => change.hideFromChangelog && acc.push(change))
// )
// );
// return acc;
// }, []);

// const { queryByText } = render(<ChangeList changes={mockChangelog} versionMode={ALL_VERSIONS} />);

// expect(hiddenChanges).toHaveLength(2);

// hiddenChanges.forEach((change) => {
// expect(queryByText(change.change)).toBeNull();
// });
// });

// it('does not render Diff changelog changes with "hideFromChangelog=true"', () => {
// const hiddenChanges = mockDiff.reduce((acc, resource) => {
// resource.changes.forEach((change) => change.hideFromChangelog && acc.push(change));
// return acc;
// }, []);

// const { queryByText } = render(<ChangeList changes={mockDiff} versionMode={COMPARE_VERSIONS} />);

// expect(hiddenChanges).toHaveLength(2);

// hiddenChanges.forEach((change) => {
// expect(queryByText(change.change)).toBeNull();
// });
// });
Copy link
Collaborator

Choose a reason for hiding this comment

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

These can be removed, I believe

@@ -0,0 +1,41 @@
export const hideChanges = (changelog) => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Would also love a comment above this explaining what this first util function is doing (ie what field it's hiding and that it is meant to be used on the changelog rather than the diff

},
}));

describe(' ChangeList data', () => {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think all of this is fine! I also think if you wanted, this could just be a utility function test, so no need to render any components. Just pass a changelog and a diff through the functions and make sure the output is correct. But I'm totally fine with leaving all this. It accomplishes the same goal!

@anabellabuckvar anabellabuckvar requested a review from mmeigs October 6, 2023 21:10
Copy link
Collaborator

@mmeigs mmeigs left a comment

Choose a reason for hiding this comment

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

It looks good overall. But I am worried about using CommonJS exports in the frontend/react. Does this actually work? Especially if you comment out lines 17-20 in useFetchDiff?

@anabellabuckvar
Copy link
Collaborator Author

anabellabuckvar commented Oct 9, 2023

It looks good overall. But I am worried about using CommonJS exports in the frontend/react. Does this actually work? Especially if you comment out lines 17-20 in useFetchDiff?

Yes, it worked when I commented them out, and I used CommonJs exports only because I was following the format I saw in some of the other files. Would you like me to change it @mmeigs

Copy link
Collaborator

@mmeigs mmeigs left a comment

Choose a reason for hiding this comment

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

Ok, LGTM!

@anabellabuckvar anabellabuckvar merged commit b6308b3 into master Oct 10, 2023
2 checks passed
@anabellabuckvar anabellabuckvar deleted the DOP-3903-b branch October 10, 2023 20:04
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