From 665a9c81a5b1048c0bbc3f88e9086793034c06ee Mon Sep 17 00:00:00 2001 From: SupaJoon Date: Wed, 28 Aug 2024 16:53:50 -0400 Subject: [PATCH] DEVPROD-10020: Open failing line section alongside section containing the share line (#333) --- apps/parsley/src/context/LogContext/index.tsx | 4 +- apps/parsley/src/hooks/useSections/index.ts | 8 +-- .../hooks/useSections/useSections.test.tsx | 10 ++-- .../src/hooks/useSections/utils.test.ts | 60 ++++++++++++++----- apps/parsley/src/hooks/useSections/utils.ts | 12 ++-- 5 files changed, 65 insertions(+), 29 deletions(-) diff --git a/apps/parsley/src/context/LogContext/index.tsx b/apps/parsley/src/context/LogContext/index.tsx index 2597cbf49..33c58aad4 100644 --- a/apps/parsley/src/context/LogContext/index.tsx +++ b/apps/parsley/src/context/LogContext/index.tsx @@ -155,7 +155,9 @@ const LogContextProvider: React.FC = ({ const sectioning = useSections({ logType: state.logMetadata?.logType, logs: state.logs, - onInitOpenSectionContainingLine: shareLine ?? state.failingLine, + onInitOpenSectionsContainingLines: [shareLine, state.failingLine].filter( + (v): v is number => v !== undefined, + ), renderingType: state.logMetadata?.renderingType, }); diff --git a/apps/parsley/src/hooks/useSections/index.ts b/apps/parsley/src/hooks/useSections/index.ts index a5463099d..462054cdb 100644 --- a/apps/parsley/src/hooks/useSections/index.ts +++ b/apps/parsley/src/hooks/useSections/index.ts @@ -46,12 +46,12 @@ interface Props { logs: string[]; logType: string | undefined; renderingType: string | undefined; - onInitOpenSectionContainingLine: number | undefined; + onInitOpenSectionsContainingLines: number[] | undefined; } export const useSections = ({ logType, logs, - onInitOpenSectionContainingLine, + onInitOpenSectionsContainingLines, renderingType, }: Props): UseSectionsResult => { const dispatchToast = useToastContext(); @@ -86,12 +86,12 @@ export const useSections = ({ if (sectionData && sectionState === undefined) { setSectionState( populateSectionState({ - openSectionContainingLine: onInitOpenSectionContainingLine, + openSectionsContainingLines: onInitOpenSectionsContainingLines, sectionData, }), ); } - }, [sectionData, sectionState, onInitOpenSectionContainingLine]); + }, [sectionData, sectionState, onInitOpenSectionsContainingLines]); const toggleFunctionSection: ToggleFunctionSection = useCallback( ({ functionID, isOpen }) => { diff --git a/apps/parsley/src/hooks/useSections/useSections.test.tsx b/apps/parsley/src/hooks/useSections/useSections.test.tsx index 05d9eac15..244fb268d 100644 --- a/apps/parsley/src/hooks/useSections/useSections.test.tsx +++ b/apps/parsley/src/hooks/useSections/useSections.test.tsx @@ -160,7 +160,7 @@ describe("useSections", () => { rerender({ logType: LogTypes.EVERGREEN_TASK_FILE, logs, - onInitOpenSectionContainingLine: undefined, + onInitOpenSectionsContainingLines: undefined, renderingType: LogRenderingTypes.Default, }); rerender({ logs, ...metadata }); @@ -305,13 +305,13 @@ describe("useSections", () => { }); }); - it("should open the section containing 'onInitOpenSectionContainingLine' during initialization only", async () => { + it("should open the section containing 'onInitOpenSectionsContainingLines' during initialization only", async () => { InitializeFakeToastContext(); const { rerender, result } = renderHook((args) => useSections(args), { initialProps: { logType: LogTypes.EVERGREEN_TASK_LOGS, logs, - onInitOpenSectionContainingLine: 10, + onInitOpenSectionsContainingLines: [10], renderingType: LogRenderingTypes.Default, }, wrapper, @@ -335,7 +335,7 @@ describe("useSections", () => { rerender({ logType: LogTypes.EVERGREEN_TASK_LOGS, logs, - onInitOpenSectionContainingLine: 1, + onInitOpenSectionsContainingLines: [1, 2], renderingType: LogRenderingTypes.Default, }); await waitFor(() => { @@ -444,7 +444,7 @@ describe("useSections", () => { }; const metadata = { logType: LogTypes.EVERGREEN_TASK_LOGS, - onInitOpenSectionContainingLine: undefined, + onInitOpenSectionsContainingLines: undefined, renderingType: LogRenderingTypes.Default, }; }); diff --git a/apps/parsley/src/hooks/useSections/utils.test.ts b/apps/parsley/src/hooks/useSections/utils.test.ts index 9dcd40036..bc4b942b5 100644 --- a/apps/parsley/src/hooks/useSections/utils.test.ts +++ b/apps/parsley/src/hooks/useSections/utils.test.ts @@ -510,49 +510,50 @@ describe("getOpenSectionStateBasedOnLineNumbers", () => { }); describe("populateSectionState", () => { - it("should populate the section state based on the section data with all sections closed when 'openSectionContainingLine' is undefined or false", () => { + it("should populate the section state based on the section data with all sections closed when 'openSectionsContainingLines' is undefined or false", () => { expect( populateSectionState({ - openSectionContainingLine: undefined, + openSectionsContainingLines: undefined, sectionData, }), ).toStrictEqual(sectionStateAllClosed); expect( populateSectionState({ isOpen: false, - openSectionContainingLine: undefined, + openSectionsContainingLines: undefined, sectionData, }), ).toStrictEqual(sectionStateAllClosed); }); - it("should populate the section state based on the section data with all sections closed when 'openSectionContainingLine' is undefined or false", () => { + it("should populate the section state based on the section data with all sections closed when 'openSectionsContainingLines' is undefined or false", () => { expect( populateSectionState({ - openSectionContainingLine: undefined, + openSectionsContainingLines: undefined, sectionData, }), ).toStrictEqual(sectionStateAllClosed); expect( populateSectionState({ isOpen: false, - openSectionContainingLine: undefined, + openSectionsContainingLines: undefined, sectionData, }), ).toStrictEqual(sectionStateAllClosed); }); - it("should populate the section state based on the section data with all sections closed when 'openSectionContainingLine' does not match a section", () => { + it("should populate the section state based on the section data with all sections closed when 'openSectionsContainingLines' does not match a section", () => { const result = populateSectionState({ - openSectionContainingLine: 999999, + openSectionsContainingLines: [999999], sectionData, }); expect(result).toStrictEqual(sectionStateAllClosed); }); - it("should populate the section state based on the section data with all sections closed except the sections containing 'openSectionContainingLine'", () => { - const result = populateSectionState({ - openSectionContainingLine: 1, - sectionData, - }); - expect(result).toStrictEqual({ + it("should populate the section state based on the section data with all sections closed except the sections containing 'openSectionsContainingLines'", () => { + expect( + populateSectionState({ + openSectionsContainingLines: [1], + sectionData, + }), + ).toStrictEqual({ ...sectionStateAllClosed, "function-1": { commands: { @@ -566,11 +567,40 @@ describe("populateSectionState", () => { isOpen: true, }, }); + expect( + populateSectionState({ + openSectionsContainingLines: [1, 7, 13], + sectionData, + }), + ).toStrictEqual({ + "function-1": { + commands: { + "command-1": { + isOpen: true, + }, + "command-6": { + isOpen: true, + }, + }, + isOpen: true, + }, + "function-9": { + commands: { + "command-9": { + isOpen: false, + }, + "command-12": { + isOpen: true, + }, + }, + isOpen: true, + }, + }); }); it("should populate the section state based on the section data with all sections open when isOpen is true", () => { const result = populateSectionState({ isOpen: true, - openSectionContainingLine: undefined, + openSectionsContainingLines: undefined, sectionData, }); expect(result).toStrictEqual(sectionStateAllOpen); diff --git a/apps/parsley/src/hooks/useSections/utils.ts b/apps/parsley/src/hooks/useSections/utils.ts index ce749da42..d20d39802 100644 --- a/apps/parsley/src/hooks/useSections/utils.ts +++ b/apps/parsley/src/hooks/useSections/utils.ts @@ -198,7 +198,7 @@ const getOpenSectionStateBasedOnLineNumbers = ({ interface PopulateSectionStateParams { sectionData: SectionData; - openSectionContainingLine?: number; + openSectionsContainingLines?: number[]; isOpen?: boolean; } /** @@ -206,14 +206,14 @@ interface PopulateSectionStateParams { * All sections are set closed except those containing the given line number. * @param params - The parameters for the function * @param params.sectionData - The parsed section data - * @param params.openSectionContainingLine - The line number to be used to determine which section to open + * @param params.openSectionsContainingLines - Line numbers used to determine which sections to open * @param params.isOpen - The default open state for the sections * @returns A sectionState coresponding to sectionData with the specified section open */ const populateSectionState = ({ isOpen = false, - openSectionContainingLine, + openSectionsContainingLines, sectionData, }: PopulateSectionStateParams): SectionState => { const { commands, functions } = sectionData; @@ -223,7 +223,11 @@ const populateSectionState = ({ }); commands.forEach((sectionEntry) => { const { commandID, functionID } = sectionEntry; - if (includesLineNumber(sectionEntry, openSectionContainingLine)) { + if ( + openSectionsContainingLines?.some((lineNumber) => + includesLineNumber(sectionEntry, lineNumber), + ) + ) { sectionState[functionID].isOpen = true; sectionState[functionID].commands[commandID] = { isOpen: true }; } else {