diff --git a/plugins/utils/openapi.js b/plugins/utils/openapi.js index 922c18f1a..96700bd39 100644 --- a/plugins/utils/openapi.js +++ b/plugins/utils/openapi.js @@ -1,3 +1,5 @@ +const { hideChanges, hideDiffChanges } = require('../../src/components/OpenAPIChangelog/utils/filterHiddenChanges'); + const atlasAdminProdChangelogS3Prefix = 'https://mongodb-mms-prod-build-server.s3.amazonaws.com/openapi/changelog'; const atlasAdminDevChangelogS3Prefix = 'https://mongodb-mms-build-server.s3.amazonaws.com/openapi/changelog'; @@ -5,7 +7,8 @@ const fetchChangelogData = async (runId, versions, s3Prefix) => { try { /* Using metadata runId, fetch OpenAPI Changelog full change list */ const changelogResp = await fetch(`${s3Prefix}/${runId}/changelog.json`); - const changelog = await changelogResp.json(); + const unfilteredChangelog = await changelogResp.json(); + const changelog = hideChanges(unfilteredChangelog); /* Aggregate all Resources in changelog for frontend filter */ const resourcesListSet = new Set(); @@ -18,7 +21,8 @@ const fetchChangelogData = async (runId, versions, s3Prefix) => { const mostRecentResourceVersions = versions.slice(-2); const mostRecentDiffLabel = mostRecentResourceVersions.join('_'); const mostRecentDiffResp = await fetch(`${s3Prefix}/${runId}/${mostRecentDiffLabel}.json`); - const mostRecentDiffData = await mostRecentDiffResp.json(); + const mostRecentUnfilteredDiffData = await mostRecentDiffResp.json(); + const mostRecentDiffData = hideDiffChanges(mostRecentUnfilteredDiffData); return { changelog, diff --git a/src/components/OpenAPIChangelog/OpenAPIChangelog.js b/src/components/OpenAPIChangelog/OpenAPIChangelog.js index 0fb111692..55a940229 100644 --- a/src/components/OpenAPIChangelog/OpenAPIChangelog.js +++ b/src/components/OpenAPIChangelog/OpenAPIChangelog.js @@ -72,6 +72,7 @@ const StyledLoadingSkeleton = styled.div` const OpenAPIChangelog = () => { const { snootyEnv } = useSiteMetadata(); const { index = {}, changelog = [], changelogResourcesList = [] } = useChangelogData(); + const resourceVersions = index.versions?.length ? index.versions.slice().reverse() : []; const downloadChangelogUrl = useMemo(() => getDownloadChangelogUrl(index.runId, snootyEnv), [index, snootyEnv]); diff --git a/src/components/OpenAPIChangelog/utils/filterHiddenChanges.js b/src/components/OpenAPIChangelog/utils/filterHiddenChanges.js new file mode 100644 index 000000000..f4e1b4656 --- /dev/null +++ b/src/components/OpenAPIChangelog/utils/filterHiddenChanges.js @@ -0,0 +1,46 @@ +//nested filtering out all changes with hideFromChangelog +//hides changes on all versions changelog +const hideChanges = (changelog) => { + const versionUpdate = (version) => { + const updatedVersion = { ...version }; + if (version?.changes) { + updatedVersion.changes = version.changes.filter((change) => !change.hideFromChangelog); + } + return updatedVersion; + }; + + //pathUpdate takes the array of versions from the specific path passed in and takes each version and runs versionUpdate on it + const pathUpdate = (path) => { + const updatedPath = { ...path, versions: path.versions.map(versionUpdate) }; + updatedPath.versions = updatedPath.versions.filter((version) => version.changes?.length); + return updatedPath; + }; + + //dateUpdate takes the array of paths from the specific date section passed in and takes each path and runs pathUpdate on it + const dateUpdate = (dateSection) => { + const updatedDateSection = { ...dateSection, paths: dateSection.paths.map(pathUpdate) }; + updatedDateSection.paths = updatedDateSection.paths.filter((path) => path.versions?.length); + return updatedDateSection; + }; + + //changelog is the json file with everything in it. Map at this level takes each date section and runs dateUpdate on it + const updatedChangelog = changelog.map(dateUpdate); + return updatedChangelog.filter((dateSection) => dateSection.paths?.length); +}; + +//nested filtering out all changes with hideFromChangelog +//hides changes on diffs +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); +}; + +module.exports = { hideChanges, hideDiffChanges }; diff --git a/src/components/OpenAPIChangelog/utils/useFetchDiff.js b/src/components/OpenAPIChangelog/utils/useFetchDiff.js index 15376c4b2..cf1552acd 100644 --- a/src/components/OpenAPIChangelog/utils/useFetchDiff.js +++ b/src/components/OpenAPIChangelog/utils/useFetchDiff.js @@ -2,6 +2,7 @@ import { useState, useEffect } from 'react'; import { fetchOADiff } from '../../../utils/realm'; import useChangelogData from '../../../utils/use-changelog-data'; import { getDiffRequestFormat } from './getDiffRequestFormat'; +import { hideDiffChanges } from './filterHiddenChanges'; export const useFetchDiff = (resourceVersionOne, resourceVersionTwo, setIsLoading, setToastOpen, snootyEnv) => { const { index = {}, mostRecentDiff = {} } = useChangelogData(); @@ -20,7 +21,8 @@ export const useFetchDiff = (resourceVersionOne, resourceVersionTwo, setIsLoadin setIsLoading(true); fetchOADiff(index.runId, fromAndToDiffLabel, snootyEnv) .then((response) => { - setDiff(response); + const filteredDiff = hideDiffChanges(response); + setDiff(filteredDiff); setIsLoading(false); }) .catch((err) => { diff --git a/tests/unit/__snapshots__/ChangeList.test.js.snap b/tests/unit/__snapshots__/ChangeList.test.js.snap index f0e97e004..3902b0ec0 100644 --- a/tests/unit/__snapshots__/ChangeList.test.js.snap +++ b/tests/unit/__snapshots__/ChangeList.test.js.snap @@ -158,7 +158,7 @@ exports[`OpenAPIChangelog ChangeList ChangeList renders all version changelog co line-height: 28px; } -.emotion-35 { +.emotion-54 { font-family: Euclid Circular A,‘Helvetica Neue’,Helvetica,Arial,sans-serif; display: -webkit-inline-box; display: -webkit-inline-flex; @@ -183,11 +183,11 @@ exports[`OpenAPIChangelog ChangeList ChangeList renders all version changelog co color: #00684A; } -.emotion-40 { +.emotion-59 { position: relative; } -.emotion-41 { +.emotion-60 { display: -webkit-inline-box; display: -webkit-inline-flex; display: -ms-inline-flexbox; @@ -200,7 +200,7 @@ exports[`OpenAPIChangelog ChangeList ChangeList renders all version changelog co margin-right: 5px; } -.emotion-43 { +.emotion-62 { color: #DB3030; } @@ -254,6 +254,53 @@ exports[`OpenAPIChangelog ChangeList ChangeList renders all version changelog co +
+

+ 01 February 2024 Release +

+
+ + +
+
@@ -285,7 +332,7 @@ exports[`OpenAPIChangelog ChangeList ChangeList renders all version changelog co
Released
@@ -297,11 +344,11 @@ exports[`OpenAPIChangelog ChangeList ChangeList renders all version changelog co class="emotion-19 emotion-20" >
Released
@@ -356,11 +403,37 @@ exports[`OpenAPIChangelog ChangeList ChangeList renders all version changelog co class="emotion-19 emotion-20" >
+ + + +
+ This change should be hidden + +
  • +
    Updated
    @@ -512,7 +585,7 @@ exports[`OpenAPIChangelog ChangeList ChangeList renders all version changelog co
    Updated
    @@ -696,6 +769,32 @@ exports[`OpenAPIChangelog ChangeList ChangeList renders diff changelog correctly
      +
    • +
      + + + +
      + A change +
    • @@ -812,6 +911,32 @@ exports[`OpenAPIChangelog ChangeList ChangeList renders diff changelog correctly
    Removed the required property 'name' from the response with the '200' status.
  • +
  • +
    + + + +
    + Removed the required property 'name' from the response with the '200' status. +
  • diff --git a/tests/unit/__snapshots__/OpenAPIChangelog.test.js.snap b/tests/unit/__snapshots__/OpenAPIChangelog.test.js.snap index 4bda94287..ac9eeae50 100644 --- a/tests/unit/__snapshots__/OpenAPIChangelog.test.js.snap +++ b/tests/unit/__snapshots__/OpenAPIChangelog.test.js.snap @@ -794,7 +794,7 @@ exports[`OpenAPIChangelog tests OpenAPIChangelog renders correctly 1`] = ` line-height: 28px; } -.emotion-78 { +.emotion-97 { font-family: Euclid Circular A,‘Helvetica Neue’,Helvetica,Arial,sans-serif; display: -webkit-inline-box; display: -webkit-inline-flex; @@ -819,11 +819,11 @@ exports[`OpenAPIChangelog tests OpenAPIChangelog renders correctly 1`] = ` color: #00684A; } -.emotion-83 { +.emotion-102 { position: relative; } -.emotion-84 { +.emotion-103 { display: -webkit-inline-box; display: -webkit-inline-flex; display: -ms-inline-flexbox; @@ -836,7 +836,7 @@ exports[`OpenAPIChangelog tests OpenAPIChangelog renders correctly 1`] = ` margin-right: 5px; } -.emotion-86 { +.emotion-105 { color: #DB3030; } @@ -1068,6 +1068,53 @@ exports[`OpenAPIChangelog tests OpenAPIChangelog renders correctly 1`] = `
    +
    +

    + 01 February 2024 Release +

    +
    + + +
    +
    @@ -1099,7 +1146,7 @@ exports[`OpenAPIChangelog tests OpenAPIChangelog renders correctly 1`] = `
    Released
    @@ -1111,11 +1158,11 @@ exports[`OpenAPIChangelog tests OpenAPIChangelog renders correctly 1`] = ` class="emotion-62 emotion-63" >
    Released
    @@ -1170,11 +1217,37 @@ exports[`OpenAPIChangelog tests OpenAPIChangelog renders correctly 1`] = ` class="emotion-62 emotion-63" >
    + + + +
    + This change should be hidden + +
  • +
    Updated
    @@ -1326,7 +1399,7 @@ exports[`OpenAPIChangelog tests OpenAPIChangelog renders correctly 1`] = `
    Updated
    diff --git a/tests/unit/data/OpenAPIChangelog.js b/tests/unit/data/OpenAPIChangelog.js index 333e3a420..86b9472e1 100644 --- a/tests/unit/data/OpenAPIChangelog.js +++ b/tests/unit/data/OpenAPIChangelog.js @@ -24,6 +24,32 @@ export const mockChangelog = [ }, ], }, + { + date: '2024-02-01', + paths: [ + { + path: '/api/atlas/v2/groups/{groupId}/alertConfigs/{alertConfigId}', + httpMethod: 'PUT', + operationId: 'updateAlertConfiguration', + tag: 'Alert Configurations', + versions: [ + { + version: '2023-01-01', + stabilityLevel: 'stable', + changeType: 'removed', + changes: [ + { + change: 'This change should really definitely be hidden', + changeCode: 'resource-version-removed', + backwardCompatible: true, + hideFromChangelog: true, + }, + ], + }, + ], + }, + ], + }, { date: '2023-02-01', paths: [ @@ -42,6 +68,7 @@ export const mockChangelog = [ change: 'resource version added.', changeCode: 'resource-version-added', backwardCompatible: false, + hideFromChangelog: false, }, ], }, @@ -58,6 +85,12 @@ export const mockChangelog = [ stabilityLevel: 'stable', changeType: 'release', changes: [ + { + change: 'This change should be hidden', + changeCode: 'resource-version-added', + backwardCompatible: false, + hideFromChangelog: true, + }, { change: 'resource version added.', changeCode: 'resource-version-added', @@ -154,6 +187,12 @@ export const mockDiff = [ tag: 'Federated Authentication', changeType: 'update', changes: [ + { + change: "a change", + changeCode: 'response-non-success-status-removed', + backwardCompatible: false, + hideFromChangelog: true, + }, { change: "removed the non-success response with the status '400'.", changeCode: 'response-non-success-status-removed', @@ -173,6 +212,7 @@ export const mockDiff = [ change: 'this change should be hidden!', changeCode: 'operation-tag-changed', backwardCompatible: false, + hideFromChangelog: false, }, ], }, @@ -183,6 +223,12 @@ export const mockDiff = [ tag: 'Project IP Access List', changeType: 'removed', changes: [ + { + change: "removed the required property 'name' from the response with the '200' status.", + changeCode: 'response-required-property-removed', + backwardCompatible: false, + hideFromChangelog: true, + }, { change: "removed the required property 'name' from the response with the '200' status.", changeCode: 'response-required-property-removed', diff --git a/tests/unit/filterHiddenChanges.test.js b/tests/unit/filterHiddenChanges.test.js new file mode 100644 index 000000000..dfe461761 --- /dev/null +++ b/tests/unit/filterHiddenChanges.test.js @@ -0,0 +1,79 @@ +import React from 'react'; +import * as Gatsby from 'gatsby'; +import { render } from '@testing-library/react'; +import ChangeList from '../../src/components/OpenAPIChangelog/components/ChangeList'; +import { ALL_VERSIONS, COMPARE_VERSIONS } from '../../src/components/OpenAPIChangelog/utils/constants'; +import { hideChanges, hideDiffChanges } from '../../src/components/OpenAPIChangelog/utils/filterHiddenChanges'; + +import { mockChangelog, mockDiff } from './data/OpenAPIChangelog'; + +jest.mock('../../src/utils/use-snooty-metadata', () => () => ({ + openapi_pages: ['reference/api-resources-spec/v2'], + project: '', +})); + +const useStaticQuery = jest.spyOn(Gatsby, 'useStaticQuery'); +useStaticQuery.mockImplementation(() => ({ + site: { + siteMetadata: { + commitHash: '', + parserBranch: '', + patchId: '', + pathPrefix: '', + snootyBranch: '', + user: '', + }, + }, +})); + +describe(' ChangeList data', () => { + it('hideChanges function filters out 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 unhiddenChanges = hideChanges(mockChangelog).reduce((acc, date) => { + date.paths.forEach((path) => + path.versions.forEach((version) => + version.changes.forEach((change) => change.hideFromChangelog && acc.push(change)) + ) + ); + return acc; + }, []); + + expect(hiddenChanges).toHaveLength(2); + expect(unhiddenChanges).toHaveLength(0); + + const { queryByText } = render(); + + 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 unhiddenChanges = hideDiffChanges(mockDiff).reduce((acc, resource) => { + resource.changes.forEach((change) => change.hideFromChangelog && acc.push(change)); + return acc; + }, []); + + expect(hiddenChanges).toHaveLength(2); + expect(unhiddenChanges).toHaveLength(0); + + const { queryByText } = render(); + + hiddenChanges.forEach((change) => { + expect(queryByText(change.change)).toBeNull(); + }); + }); +});