From fbe57bbc082985d3734ee9498288e24044c0ce3b Mon Sep 17 00:00:00 2001 From: SupaJoon Date: Fri, 5 Apr 2024 14:20:49 -0400 Subject: [PATCH] DEVPROD-5130: Case on renderingType during log ingestion, introduce LOCAL_UPLOAD logType and fix bug related to exposing renderingType from hook (#25) --- .evergreen/shared.yml | 10 +- .../resmokeLogs/resmoke_evg_test_logView.ts | 318 ++++++++++++++++ apps/parsley/scripts/bootstrap-logkeeper.sh | 14 +- .../src/analytics/useAnalyticAttributes.ts | 7 +- .../PrettyPrintToggle.test.tsx | 10 +- .../Toggles/PrettyPrintToggle/index.tsx | 6 +- .../LogRow/AnsiRow/AnsiRow.stories.tsx | 11 +- .../BaseRow/SharingMenu/SharingMenu.test.tsx | 3 +- .../LogRow/BaseRow/SharingMenu/index.tsx | 3 +- .../CollapsedRow/CollapsedRow.stories.tsx | 16 +- .../LogRow/ResmokeRow/ResmokeRow.stories.tsx | 11 +- .../components/LogRow/RowRenderer/index.tsx | 7 +- .../src/components/LogWindow/index.tsx | 7 +- .../SubHeader/EvergreenTaskSubHeader.tsx | 43 ++- .../SubHeader/SubHeader.stories.tsx | 2 +- .../__snapshots__/SubHeader.stories.storyshot | 344 ++---------------- .../src/components/SubHeader/index.tsx | 13 +- apps/parsley/src/constants/enums.ts | 1 + .../context/LogContext/LogContext.test.tsx | 12 +- apps/parsley/src/context/LogContext/index.tsx | 15 +- apps/parsley/src/context/LogContext/state.ts | 11 +- apps/parsley/src/context/LogContext/types.ts | 10 +- apps/parsley/src/gql/generated/types.ts | 2 + ...et-test-log-url-and-rendering-type.graphql | 2 + apps/parsley/src/hooks/useTaskQuery/index.ts | 3 +- apps/parsley/src/pages/LogDrop.tsx | 9 +- .../parsley/src/pages/LogDrop/FileDropper.tsx | 8 +- apps/parsley/src/pages/LogView.tsx | 6 +- .../src/pages/LogView/LoadingPage/index.tsx | 3 +- .../useResolveLogURLAndRenderingType.test.tsx | 286 ++++++++++++++- .../useResolveLogURLAndRenderingType.ts | 8 +- 31 files changed, 773 insertions(+), 428 deletions(-) create mode 100644 apps/parsley/cypress/integration/resmokeLogs/resmoke_evg_test_logView.ts diff --git a/.evergreen/shared.yml b/.evergreen/shared.yml index 98d515913..a46336f85 100644 --- a/.evergreen/shared.yml +++ b/.evergreen/shared.yml @@ -67,21 +67,21 @@ functions: params: working_dir: ui/logkeeper background: true - script: go run main/logkeeper.go --localPath _bucketdata + script: go run main/logkeeper.go --localPath ../evergreen/_bucketdata shell: bash env: GOROOT: ${goroot} PATH: ${goroot}/bin:$PATH LK_CORS_ORIGINS: http:\/\/localhost:\d+ - seed-logkeeper: + seed-bucket-data: command: s3.get type: setup params: aws_key: ${AWS_ACCESS_KEY_ID} aws_secret: ${AWS_SECRET_ACCESS_KEY} aws_session_token: ${AWS_SESSION_TOKEN} - extract_to: ui/logkeeper + extract_to: ui/evergreen remote_file: _bucketdata.tar.gz bucket: parsley-test @@ -361,7 +361,7 @@ tasks: - func: run-make-background vars: target: local-evergreen - - func: seed-logkeeper + - func: seed-bucket-data - func: run-logkeeper - func: yarn-build - func: yarn-preview @@ -376,7 +376,7 @@ tasks: vars: target: local-evergreen - func: symlink - - func: seed-logkeeper + - func: seed-bucket-data - func: run-logkeeper - func: yarn-build - func: yarn-serve diff --git a/apps/parsley/cypress/integration/resmokeLogs/resmoke_evg_test_logView.ts b/apps/parsley/cypress/integration/resmokeLogs/resmoke_evg_test_logView.ts new file mode 100644 index 000000000..715275418 --- /dev/null +++ b/apps/parsley/cypress/integration/resmokeLogs/resmoke_evg_test_logView.ts @@ -0,0 +1,318 @@ +describe("Basic resmoke log view", () => { + const logLink = + "/test/mongodb_mongo_master_rhel80_debug_v4ubsan_all_feature_flags_experimental_concurrency_sharded_with_stepdowns_and_balancer_4_linux_enterprise_361789ed8a613a2dc0335a821ead0ab6205fbdaa_22_09_21_02_53_24/0/1716e11b4f8a4541c5e2faf70affbfab"; + beforeEach(() => { + cy.visit(logLink); + }); + + it("should render resmoke lines", () => { + cy.dataCy("resmoke-row").should("be.visible"); + }); + it("by default should have wrapping turned off and should be able to scroll horizontally", () => { + cy.dataCy("log-row-16").should("be.visible"); + cy.dataCy("log-row-16").isNotContainedInViewport(); + + cy.dataCy("paginated-virtual-list").scrollTo(500, 0, { + ensureScrollable: true, + }); + }); + it("long lines with wrapping turned on should fit on screen", () => { + cy.clickToggle("wrap-toggle", true, "log-viewing"); + cy.dataCy("log-row-16").should("be.visible"); + cy.dataCy("log-row-16").isContainedInViewport(); + }); + it("should still allow horizontal scrolling when there are few logs on screen", () => { + cy.addFilter("Putting spruce/"); + cy.contains("Above & Below").click(); + cy.dataCy("paginated-virtual-list").scrollTo("right"); + }); + + it("log header should show breadcrumbs, including one for the test name", () => { + cy.dataCy("project-breadcrumb").should( + "contain.text", + "mongodb-mongo-master", + ); + + cy.dataCy("version-breadcrumb").should("contain.text", "Patch 973"); + cy.dataCy("version-breadcrumb").trigger("mouseover"); + cy.dataCy("breadcrumb-tooltip").should( + "contain.text", + "SERVER-45720 Create tests for Atlas Workflows", + ); + cy.dataCy("version-breadcrumb").trigger("mouseout"); + + cy.dataCy("task-breadcrumb") + .should("contain.text", "merge-patch") + .should( + "have.attr", + "href", + "http://localhost:9090/task/mongodb_mongo_master_rhel80_debug_v4ubsan_all_feature_flags_experimental_concurrency_sharded_with_stepdowns_and_balancer_4_linux_enterprise_361789ed8a613a2dc0335a821ead0ab6205fbdaa_22_09_21_02_53_24/0?redirect_spruce_users=true", + ); + cy.dataCy("task-status-badge").should("contain.text", "Succeeded"); + + cy.dataCy("test-breadcrumb").should( + "contain.text", + "internal_transactions_kill_sessions.js", + ); + cy.dataCy("test-status-badge").should("contain.text", "Pass"); + }); +}); + +describe("Resmoke syntax highlighting", () => { + // Although it isn't ideal to test for a specific color, this helps us ensure that the color is consistent and deterministic. + const colors = { + black: "rgb(0, 0, 0)", + blue: "rgb(8, 60, 144)", + green: "rgb(0, 163, 92)", + }; + const logLink = + "/test/mongodb_mongo_master_rhel80_debug_v4ubsan_all_feature_flags_experimental_concurrency_sharded_with_stepdowns_and_balancer_4_linux_enterprise_361789ed8a613a2dc0335a821ead0ab6205fbdaa_22_09_21_02_53_24/0/1716e11b4f8a4541c5e2faf70affbfab"; + + beforeEach(() => { + cy.visit(logLink); + }); + it("should not color non-resmoke log lines", () => { + cy.dataCy("log-row-0").within(() => { + cy.dataCy("resmoke-row").should("have.css", "color", colors.black); + }); + }); + it("should color similar resmoke lines with the same color", () => { + cy.dataCy("log-row-20").should("be.visible"); + cy.dataCy("log-row-21").should("be.visible"); + cy.dataCy("log-row-20").should("contain", "[j0:s0:n1]"); + cy.dataCy("log-row-21").should("contain", "[j0:s0:n1]"); + cy.dataCy("log-row-20").within(() => { + cy.dataCy("resmoke-row").should("have.css", "color", colors.blue); + }); + cy.dataCy("log-row-21").within(() => { + cy.dataCy("resmoke-row").should("have.css", "color", colors.blue); + }); + }); + it("should color different resmoke lines with different colors if their resmoke state is different", () => { + cy.dataCy("log-row-19").should("be.visible"); + cy.dataCy("log-row-20").should("be.visible"); + cy.dataCy("log-row-19").should("contain", "[j0:s0:n0]"); + cy.dataCy("log-row-20").should("contain", "[j0:s0:n1]"); + cy.dataCy("log-row-19").within(() => { + cy.dataCy("resmoke-row").should("have.css", "color", colors.green); + }); + cy.dataCy("log-row-20").within(() => { + cy.dataCy("resmoke-row").should("have.css", "color", colors.blue); + }); + }); +}); + +describe("Bookmarking and selecting lines", () => { + const logLink = + "/test/mongodb_mongo_master_rhel80_debug_v4ubsan_all_feature_flags_experimental_concurrency_sharded_with_stepdowns_and_balancer_4_linux_enterprise_361789ed8a613a2dc0335a821ead0ab6205fbdaa_22_09_21_02_53_24/0/1716e11b4f8a4541c5e2faf70affbfab"; + beforeEach(() => { + cy.visit(logLink); + }); + + it("should default to bookmarking 0 and the last log line on load", () => { + cy.location("search").should("equal", "?bookmarks=0,12568"); + cy.dataCy("bookmark-0").should("be.visible"); + cy.dataCy("bookmark-12568").should("be.visible"); + }); + + it("should be able to bookmark and unbookmark log lines", () => { + cy.dataCy("log-row-4").dblclick(); + cy.location("search").should("equal", "?bookmarks=0,4,12568"); + cy.dataCy("bookmark-0").should("be.visible"); + cy.dataCy("bookmark-4").should("be.visible"); + cy.dataCy("bookmark-12568").should("be.visible"); + cy.dataCy("log-row-4").dblclick(); + cy.location("search").should("equal", "?bookmarks=0,12568"); + cy.dataCy("bookmark-4").should("not.exist"); + }); + + it("should be able to set and unset the share line", () => { + cy.dataCy("log-link-5").click(); + cy.location("search").should("equal", "?bookmarks=0,12568&shareLine=5"); + cy.dataCy("bookmark-0").should("be.visible"); + cy.dataCy("bookmark-5").should("be.visible"); + cy.dataCy("bookmark-12568").should("be.visible"); + cy.dataCy("log-link-5").click(); + cy.location("search").should("equal", "?bookmarks=0,12568"); + cy.dataCy("bookmark-5").should("not.exist"); + }); + + it("should be able to copy bookmarks as JIRA format", () => { + cy.dataCy("log-row-10").dblclick({ scrollBehavior: false }); + cy.dataCy("log-row-11").dblclick({ scrollBehavior: false }); + + const logLine0 = + "[fsm_workload_test:internal_transactions_kill_sessions] Fixture status:"; + const logLine10 = + "|ShardedClusterFixture:job0:mongos0 |j0:s0 |20009|73157|"; + const logLine11 = + "|ShardedClusterFixture:job0:mongos1 |j0:s1 |20010|73217|"; + const logLine1638 = `[ContinuousStepdown:job0] Pausing the stepdown thread.`; + + cy.dataCy("details-button").click(); + // Need to fire a real click here because the copy to clipboard + cy.dataCy("jira-button").realClick(); + cy.assertValueCopiedToClipboard( + `{noformat}\n${logLine0}\n...\n${logLine10}\n${logLine11}\n...\n${logLine1638}\n{noformat}`, + ); + }); + + it("should be able to clear bookmarks", () => { + cy.location("search").should("equal", "?bookmarks=0,12568"); + cy.dataCy("clear-bookmarks").click(); + cy.location("search").should("equal", ""); + }); +}); + +describe("Jump to line", () => { + const logLink = + "/test/mongodb_mongo_master_rhel80_debug_v4ubsan_all_feature_flags_experimental_concurrency_sharded_with_stepdowns_and_balancer_4_linux_enterprise_361789ed8a613a2dc0335a821ead0ab6205fbdaa_22_09_21_02_53_24/0/1716e11b4f8a4541c5e2faf70affbfab"; + + it("should be able to use the bookmarks bar to jump to a line when there are no collapsed rows", () => { + cy.visit(logLink); + cy.dataCy("log-row-4").should("be.visible").dblclick({ force: true }); + cy.dataCy("bookmark-4").should("be.visible"); + + cy.dataCy("bookmark-12568").click(); + cy.dataCy("log-row-12568").should("be.visible"); + cy.dataCy("log-row-4").should("not.exist"); + + cy.dataCy("bookmark-4").click(); + cy.dataCy("log-row-4").should("be.visible"); + }); + + it("should be able to use the bookmarks bar to jump to a line when there are collapsed rows", () => { + cy.visit(`${logLink}?filters=100repl_hb`); + cy.dataCy("log-row-30").should("be.visible").dblclick({ force: true }); + cy.url().should("include", "bookmarks=0,30,12568"); + cy.dataCy("bookmark-30").should("be.visible"); + cy.dataCy("bookmark-12568").click(); + cy.dataCy("log-row-12568").should("be.visible"); + cy.dataCy("log-row-30").should("not.exist"); + + cy.dataCy("bookmark-30").click(); + cy.dataCy("log-row-30").should("be.visible"); + }); + + it("visiting a log with a share line should jump to that line on page load", () => { + cy.visit(`${logLink}?shareLine=200`); + cy.dataCy("log-row-200").should("be.visible"); + }); +}); + +describe("expanding collapsed rows", () => { + const logLink = + "/test/mongodb_mongo_master_rhel80_debug_v4ubsan_all_feature_flags_experimental_concurrency_sharded_with_stepdowns_and_balancer_4_linux_enterprise_361789ed8a613a2dc0335a821ead0ab6205fbdaa_22_09_21_02_53_24/0/1716e11b4f8a4541c5e2faf70affbfab?bookmarks=0,12568&filters=100ShardedClusterFixture%253Ajob0"; + beforeEach(() => { + cy.visit(logLink); + }); + + it("should be able to expand collapsed rows", () => { + cy.dataCy("log-row-1").should("not.exist"); + cy.dataCy("log-row-2").should("not.exist"); + cy.dataCy("log-row-3").should("not.exist"); + + cy.dataCy("collapsed-row-1-3").within(() => { + cy.contains("All").click(); + }); + + cy.dataCy("collapsed-row-1-3").should("not.exist"); + cy.dataCy("log-row-1").should("be.visible"); + cy.dataCy("log-row-2").should("be.visible"); + cy.dataCy("log-row-3").should("be.visible"); + }); + + it("should be able to see what rows have been expanded in the drawer", () => { + cy.dataCy("collapsed-row-1-3").within(() => { + cy.contains("All").click(); + }); + cy.toggleDrawer(); + cy.dataCy("expanded-row-1-to-3").should("be.visible"); + }); + + it("should be possible to re-collapse rows through the drawer", () => { + cy.dataCy("collapsed-row-1-3").within(() => { + cy.contains("All").click(); + }); + cy.dataCy("collapsed-row-1-3").should("not.exist"); + + cy.toggleDrawer(); + cy.dataCy("expanded-row-1-to-3").within(() => { + cy.get(`[aria-label="Delete range"]`).click(); + }); + cy.dataCy("collapsed-row-1-3").should("exist"); + }); +}); + +describe("pretty print", () => { + const logLink = + "/test/mongodb_mongo_master_rhel80_debug_v4ubsan_all_feature_flags_experimental_concurrency_sharded_with_stepdowns_and_balancer_4_linux_enterprise_361789ed8a613a2dc0335a821ead0ab6205fbdaa_22_09_21_02_53_24/0/1716e11b4f8a4541c5e2faf70affbfab"; + beforeEach(() => { + cy.setCookie("pretty-print-bookmarks", "true"); + cy.visit(logLink); + }); + + it("should pretty print bookmarks if pretty print is enabled", () => { + const defaultRowHeight = 18; + + cy.dataCy("log-row-19").dblclick({ force: true }); + cy.dataCy("log-row-19") + .invoke("height") + .should("be.greaterThan", defaultRowHeight); + }); +}); + +describe("Sharing lines", () => { + const logLink = + "/test/mongodb_mongo_master_rhel80_debug_v4ubsan_all_feature_flags_experimental_concurrency_sharded_with_stepdowns_and_balancer_4_linux_enterprise_361789ed8a613a2dc0335a821ead0ab6205fbdaa_22_09_21_02_53_24/0/1716e11b4f8a4541c5e2faf70affbfab"; + + beforeEach(() => { + cy.visit(logLink); + }); + + it("should present a share button with a menu when a line is selected", () => { + cy.dataCy("line-index-1").click(); + cy.dataCy("sharing-menu-button").should("be.visible"); + cy.dataCy("sharing-menu-button").click(); + cy.dataCy("sharing-menu").should("be.visible"); + }); + it("shift+click selecting a range of lines should automatically open the sharing menu", () => { + cy.dataCy("line-index-1").click(); + cy.dataCy("line-index-10").click({ shiftKey: true }); + cy.dataCy("sharing-menu").should("be.visible"); + }); + it("should be able to copy the selected lines as JIRA format", () => { + cy.dataCy("line-index-1").click(); + cy.dataCy("line-index-2").click({ shiftKey: true }); + cy.dataCy("sharing-menu").should("be.visible"); + cy.contains("Copy selected contents").should("be.visible"); + // Need to fire a real click here because the copy to clipboard + cy.contains("Copy selected contents").realClick(); + cy.validateToast("success", "Copied 2 lines to clipboard", true); + cy.assertValueCopiedToClipboard( + `{noformat}\n+------------------------------------------+--------+-----+-----+\n|full_name |name |port |pid |\n{noformat}`, + ); + }); + it("should be able to copy a link to the selected lines", () => { + cy.dataCy("line-index-1").click(); + cy.dataCy("line-index-2").click({ shiftKey: true }); + cy.dataCy("sharing-menu").should("be.visible"); + cy.contains("Copy share link to selected lines").should("be.visible"); + // Need to fire a real click here because the copy to clipboard + cy.contains("Copy share link to selected lines").realClick(); + cy.validateToast("success", "Copied link to clipboard", true); + cy.assertValueCopiedToClipboard( + "http://localhost:4173/test/mongodb_mongo_master_rhel80_debug_v4ubsan_all_feature_flags_experimental_concurrency_sharded_with_stepdowns_and_balancer_4_linux_enterprise_361789ed8a613a2dc0335a821ead0ab6205fbdaa_22_09_21_02_53_24/0/1716e11b4f8a4541c5e2faf70affbfab?bookmarks=0%2C12568&selectedLineRange=L1-L2&shareLine=1", + ); + }); + it("should be able to limit the search range to the selected lines", () => { + cy.dataCy("line-index-1").click(); + cy.dataCy("line-index-2").click({ shiftKey: true }); + cy.dataCy("sharing-menu").should("be.visible"); + cy.contains("Only search on range").should("be.visible"); + cy.contains("Only search on range").click(); + cy.toggleDetailsPanel(true); + cy.dataCy("range-lower-bound").should("have.value", "1"); + cy.dataCy("range-upper-bound").should("have.value", "2"); + }); +}); diff --git a/apps/parsley/scripts/bootstrap-logkeeper.sh b/apps/parsley/scripts/bootstrap-logkeeper.sh index c2d4337f8..bec3bcc45 100755 --- a/apps/parsley/scripts/bootstrap-logkeeper.sh +++ b/apps/parsley/scripts/bootstrap-logkeeper.sh @@ -1,4 +1,4 @@ -# This file downloads a resmoke log for use with the local logkeeper db +# This file downloads bucket data for task output. RED='\033[0;31m' @@ -14,7 +14,7 @@ if [ ! -d "bin/_bucketdata" ]; then # Use aws cli to download the bucket data echo "Downloading bucket data..." # Try to download the bucket data - aws s3 sync --content-encoding gzip s3://parsley-test/ ./bin + aws s3 cp s3://parsley-test/_bucketdata.tar.gz bin/_bucketdata.tar.gz # Check to see if the download was successful if [ $? -ne 0 ]; then echo "${RED}Failed to download bucket data!${NC}" @@ -26,12 +26,12 @@ if [ ! -d "bin/_bucketdata" ]; then fi # Uncompress the files in the _bucketdata directory echo "Uncompressing bucket data..." - tar -xzf ./bin/_bucketdata.tar.gz -C ./bin/ + tar -xzf bin/_bucketdata.tar.gz -C bin/ # Check to see if the uncompress was successful if [ $? -ne 0 ]; then echo "${RED}Failed to uncompress bucket data!${NC}" echo "Cleaning up _bucketdata directory..." - rm -rf _bucketdata + rm -rf bin/_bucketdata exit 1 fi echo "Finished uncompressing files." @@ -45,6 +45,8 @@ else echo "If you want to download the bucket data again, delete the _bucketdata directory and rerun this script." fi - -echo "Use the following command within the logkeeper directory to start logkeeper:" +echo "Use the following command to start logkeeper:" echo "${YELLOW}LK_CORS_ORIGINS=http:\/\/localhost:\\\d+ LK_EVERGREEN_ORIGIN=http://localhost:8080 LK_PARSLEY_ORIGIN=http://localhost:5173 go run main/logkeeper.go --localPath $PWD/bin/_bucketdata${NC}" + +echo "Create symlink in your local evergreen directory:" +echo "ln -s $PWD/bin/_bucketdata _bucketdata" diff --git a/apps/parsley/src/analytics/useAnalyticAttributes.ts b/apps/parsley/src/analytics/useAnalyticAttributes.ts index dbbc40716..c365c223a 100644 --- a/apps/parsley/src/analytics/useAnalyticAttributes.ts +++ b/apps/parsley/src/analytics/useAnalyticAttributes.ts @@ -5,7 +5,7 @@ export const useAnalyticAttributes = () => { const { newrelic } = window; const { logMetadata } = useLogContext(); - const { logType } = logMetadata || {}; + const { logType, renderingType } = logMetadata || {}; const userId = localStorage.getItem("userId"); @@ -21,5 +21,8 @@ export const useAnalyticAttributes = () => { if (userId !== null) { newrelic.setCustomAttribute("userId", userId); } - }, [userId, logType, newrelic]); + if (renderingType !== undefined) { + newrelic.setCustomAttribute("renderingType", renderingType); + } + }, [userId, logType, newrelic, renderingType]); }; diff --git a/apps/parsley/src/components/DetailsMenu/DetailsMenuCard/Toggles/PrettyPrintToggle/PrettyPrintToggle.test.tsx b/apps/parsley/src/components/DetailsMenu/DetailsMenuCard/Toggles/PrettyPrintToggle/PrettyPrintToggle.test.tsx index 5586190f3..d318b47c9 100644 --- a/apps/parsley/src/components/DetailsMenu/DetailsMenuCard/Toggles/PrettyPrintToggle/PrettyPrintToggle.test.tsx +++ b/apps/parsley/src/components/DetailsMenu/DetailsMenuCard/Toggles/PrettyPrintToggle/PrettyPrintToggle.test.tsx @@ -1,5 +1,5 @@ import Cookie from "js-cookie"; -import { LogTypes } from "constants/enums"; +import { LogRenderingTypes } from "constants/enums"; import { LogContextProvider, useLogContext } from "context/LogContext"; import { act, @@ -42,21 +42,21 @@ describe("pretty print toggle", () => { ); render(, { wrapper }); act(() => { - hook.current.setLogMetadata({ logType: LogTypes.EVERGREEN_TASK_LOGS }); + hook.current.setLogMetadata({ renderingType: LogRenderingTypes.Default }); }); const prettyPrintToggle = screen.getByDataCy("pretty-print-toggle"); expect(prettyPrintToggle).toHaveAttribute("aria-disabled", "true"); }); - it("should not disable the toggle if the logType is resmoke", () => { + it("should not disable the toggle if the renderingType is resmoke", () => { const { Component, hook } = renderComponentWithHook( useLogContext, , ); render(, { wrapper }); act(() => { - hook.current.setLogMetadata({ logType: LogTypes.RESMOKE_LOGS }); + hook.current.setLogMetadata({ renderingType: LogRenderingTypes.Resmoke }); }); const prettyPrintToggle = screen.getByDataCy("pretty-print-toggle"); @@ -71,7 +71,7 @@ describe("pretty print toggle", () => { ); const { router } = render(, { wrapper }); act(() => { - hook.current.setLogMetadata({ logType: LogTypes.RESMOKE_LOGS }); + hook.current.setLogMetadata({ renderingType: LogRenderingTypes.Resmoke }); }); const prettyPrintToggle = screen.getByDataCy("pretty-print-toggle"); diff --git a/apps/parsley/src/components/DetailsMenu/DetailsMenuCard/Toggles/PrettyPrintToggle/index.tsx b/apps/parsley/src/components/DetailsMenu/DetailsMenuCard/Toggles/PrettyPrintToggle/index.tsx index 4f505acb9..d2af89bf8 100644 --- a/apps/parsley/src/components/DetailsMenu/DetailsMenuCard/Toggles/PrettyPrintToggle/index.tsx +++ b/apps/parsley/src/components/DetailsMenu/DetailsMenuCard/Toggles/PrettyPrintToggle/index.tsx @@ -1,5 +1,5 @@ import { usePreferencesAnalytics } from "analytics"; -import { LogTypes } from "constants/enums"; +import { LogRenderingTypes } from "constants/enums"; import { useLogContext } from "context/LogContext"; import BaseToggle from "../BaseToggle"; @@ -8,8 +8,8 @@ const PrettyPrintToggle: React.FC = () => { const { logMetadata, preferences } = useLogContext(); const { prettyPrint, setPrettyPrint } = preferences; - const { logType } = logMetadata || {}; - const disablePrettyPrint = logType !== LogTypes.RESMOKE_LOGS; + const disablePrettyPrint = + logMetadata?.renderingType !== LogRenderingTypes.Resmoke; return ( { const { ingestLines, scrollToLine } = useLogContext(); useEffect(() => { - ingestLines(logLines, LogTypes.EVERGREEN_TASK_LOGS); + ingestLines(logLines, LogRenderingTypes.Default); }, []); // eslint-disable-line react-hooks/exhaustive-deps return ( @@ -57,11 +57,13 @@ export const SingleLine: CustomStoryObj = { // Multiple AnsiRows. const MultiLineStory = (args: any) => { - const { ingestLines, preferences, processedLogLines } = useLogContext(); + const { ingestLines, preferences, processedLogLines, setLogMetadata } = + useLogContext(); const { setWrap } = preferences; useEffect(() => { - ingestLines(logLines, LogTypes.EVERGREEN_TASK_LOGS); + setLogMetadata({ logType: LogTypes.EVERGREEN_TASK_LOGS }); + ingestLines(logLines, LogRenderingTypes.Default); }, []); // eslint-disable-line react-hooks/exhaustive-deps useEffect(() => { @@ -73,7 +75,6 @@ const MultiLineStory = (args: any) => { diff --git a/apps/parsley/src/components/LogRow/BaseRow/SharingMenu/SharingMenu.test.tsx b/apps/parsley/src/components/LogRow/BaseRow/SharingMenu/SharingMenu.test.tsx index 6654edf0b..5eee59432 100644 --- a/apps/parsley/src/components/LogRow/BaseRow/SharingMenu/SharingMenu.test.tsx +++ b/apps/parsley/src/components/LogRow/BaseRow/SharingMenu/SharingMenu.test.tsx @@ -1,3 +1,4 @@ +import { LogTypes } from "constants/enums"; import { LogContextProvider, useLogContext } from "context/LogContext"; import { MultiLineSelectContextProvider, @@ -150,7 +151,7 @@ describe("sharingMenu", () => { }); act(() => { hook.current.useLogContextHook.setLogMetadata({ - isUploadedLog: true, + logType: LogTypes.LOCAL_UPLOAD, }); }); expect(screen.queryByText("Share link to selected lines")).toBeNull(); diff --git a/apps/parsley/src/components/LogRow/BaseRow/SharingMenu/index.tsx b/apps/parsley/src/components/LogRow/BaseRow/SharingMenu/index.tsx index df7276ac5..eb71bb5e6 100644 --- a/apps/parsley/src/components/LogRow/BaseRow/SharingMenu/index.tsx +++ b/apps/parsley/src/components/LogRow/BaseRow/SharingMenu/index.tsx @@ -20,12 +20,11 @@ interface SharingMenuProps { const SharingMenu: React.FC = ({ defaultOpen }) => { const { clearSelection, selectedLines } = useMultiLineSelectContext(); - const { getLine, logMetadata, processedLogLines } = useLogContext(); + const { getLine, isUploadedLog, processedLogLines } = useLogContext(); const [params, setParams] = useQueryParams(); const dispatchToast = useToastContext(); const [open, setOpen] = useState(defaultOpen); const { sendEvent } = useLogWindowAnalytics(); - const { isUploadedLog } = logMetadata || {}; const setMenuOpen = () => { if (open) { sendEvent({ name: "Closed Share Menu" }); diff --git a/apps/parsley/src/components/LogRow/CollapsedRow/CollapsedRow.stories.tsx b/apps/parsley/src/components/LogRow/CollapsedRow/CollapsedRow.stories.tsx index 3c74954f5..d53665774 100644 --- a/apps/parsley/src/components/LogRow/CollapsedRow/CollapsedRow.stories.tsx +++ b/apps/parsley/src/components/LogRow/CollapsedRow/CollapsedRow.stories.tsx @@ -2,7 +2,7 @@ import { useEffect, useState } from "react"; import styled from "@emotion/styled"; import LogPane from "components/LogPane"; import { ParsleyRow } from "components/LogRow/RowRenderer"; -import { LogTypes } from "constants/enums"; +import { LogRenderingTypes, LogTypes } from "constants/enums"; import { useLogContext } from "context/LogContext"; import { CustomMeta, CustomStoryObj } from "test_utils/types"; import { ExpandedLine, ExpandedLines } from "types/logs"; @@ -54,11 +54,13 @@ const CollapsedAnsiRowStory = ( wrap: boolean; }, ) => { - const { ingestLines, preferences, processedLogLines } = useLogContext(); + const { ingestLines, preferences, processedLogLines, setLogMetadata } = + useLogContext(); const { setWrap } = preferences; useEffect(() => { - ingestLines(ansiLogLines, LogTypes.EVERGREEN_TASK_LOGS); + setLogMetadata({ logType: LogTypes.EVERGREEN_TASK_LOGS }); + ingestLines(ansiLogLines, LogRenderingTypes.Default); }, []); // eslint-disable-line react-hooks/exhaustive-deps useEffect(() => { @@ -70,7 +72,6 @@ const CollapsedAnsiRowStory = ( @@ -95,11 +96,13 @@ const CollapsedResmokeRowStory = ( wrap: boolean; }, ) => { - const { ingestLines, preferences, processedLogLines } = useLogContext(); + const { ingestLines, preferences, processedLogLines, setLogMetadata } = + useLogContext(); const { setWrap } = preferences; useEffect(() => { - ingestLines(resmokeLogLines, LogTypes.RESMOKE_LOGS); + setLogMetadata({ logType: LogTypes.RESMOKE_LOGS }); + ingestLines(resmokeLogLines, LogRenderingTypes.Resmoke); }, []); // eslint-disable-line react-hooks/exhaustive-deps useEffect(() => { @@ -111,7 +114,6 @@ const CollapsedResmokeRowStory = ( diff --git a/apps/parsley/src/components/LogRow/ResmokeRow/ResmokeRow.stories.tsx b/apps/parsley/src/components/LogRow/ResmokeRow/ResmokeRow.stories.tsx index 7988200a5..4118df387 100644 --- a/apps/parsley/src/components/LogRow/ResmokeRow/ResmokeRow.stories.tsx +++ b/apps/parsley/src/components/LogRow/ResmokeRow/ResmokeRow.stories.tsx @@ -2,7 +2,7 @@ import { useEffect } from "react"; import styled from "@emotion/styled"; import LogPane from "components/LogPane"; import { ParsleyRow } from "components/LogRow/RowRenderer"; -import { LogTypes, WordWrapFormat } from "constants/enums"; +import { LogRenderingTypes, LogTypes, WordWrapFormat } from "constants/enums"; import { useLogContext } from "context/LogContext"; import { MultiLineSelectContextProvider } from "context/MultiLineSelectContext"; import WithToastContext from "test_utils/toast-decorator"; @@ -28,7 +28,7 @@ const SingleLineStory = (args: any) => { const { getResmokeLineColor, ingestLines, scrollToLine } = useLogContext(); useEffect(() => { - ingestLines(logLines, LogTypes.RESMOKE_LOGS); + ingestLines(logLines, LogRenderingTypes.Resmoke); }, []); // eslint-disable-line react-hooks/exhaustive-deps return ( @@ -60,11 +60,13 @@ export const SingleLine: CustomStoryObj = { // Multiple ResmokeRows. const MultipleLinesStory = (args: any) => { - const { ingestLines, preferences, processedLogLines } = useLogContext(); + const { ingestLines, preferences, processedLogLines, setLogMetadata } = + useLogContext(); const { setPrettyPrint, setWrap } = preferences; useEffect(() => { - ingestLines(logLines, LogTypes.RESMOKE_LOGS); + setLogMetadata({ logType: LogTypes.EVERGREEN_TASK_LOGS }); + ingestLines(logLines, LogRenderingTypes.Resmoke); }, []); // eslint-disable-line react-hooks/exhaustive-deps useEffect(() => { @@ -80,7 +82,6 @@ const MultipleLinesStory = (args: any) => { diff --git a/apps/parsley/src/components/LogRow/RowRenderer/index.tsx b/apps/parsley/src/components/LogRow/RowRenderer/index.tsx index e05444fc4..fb7c7c49a 100644 --- a/apps/parsley/src/components/LogRow/RowRenderer/index.tsx +++ b/apps/parsley/src/components/LogRow/RowRenderer/index.tsx @@ -1,4 +1,4 @@ -import { LogRenderingTypes, LogTypes } from "constants/enums"; +import { LogRenderingTypes } from "constants/enums"; import { useLogContext } from "context/LogContext"; import { useHighlightParam } from "hooks/useHighlightParam"; import { ProcessedLogLines } from "types/logs"; @@ -9,10 +9,9 @@ import ResmokeRow from "../ResmokeRow"; type RowRendererFunction = (props: { processedLogLines: ProcessedLogLines; - logType: LogTypes; }) => (index: number) => JSX.Element; -const ParsleyRow: RowRendererFunction = ({ logType, processedLogLines }) => { +const ParsleyRow: RowRendererFunction = ({ processedLogLines }) => { const { expandLines, getLine, @@ -83,7 +82,7 @@ const ParsleyRow: RowRendererFunction = ({ logType, processedLogLines }) => { ); }; - result.displayName = `${logType}RowRenderer`; + result.displayName = `${logMetadata?.logType}RowRenderer`; return result; }; diff --git a/apps/parsley/src/components/LogWindow/index.tsx b/apps/parsley/src/components/LogWindow/index.tsx index 66a7df259..bb5cffb25 100644 --- a/apps/parsley/src/components/LogWindow/index.tsx +++ b/apps/parsley/src/components/LogWindow/index.tsx @@ -5,13 +5,9 @@ import LogPane from "components/LogPane"; import { ParsleyRow } from "components/LogRow/RowRenderer"; import SidePanel from "components/SidePanel"; import SubHeader from "components/SubHeader"; -import { LogTypes } from "constants/enums"; import { useLogContext } from "context/LogContext"; -interface LogWindowProps { - logType: LogTypes; -} -const LogWindow: React.FC = ({ logType }) => { +const LogWindow: React.FC = () => { const { clearExpandedLines, collapseLines, @@ -41,7 +37,6 @@ const LogWindow: React.FC = ({ logType }) => { diff --git a/apps/parsley/src/components/SubHeader/EvergreenTaskSubHeader.tsx b/apps/parsley/src/components/SubHeader/EvergreenTaskSubHeader.tsx index d41a63666..947abcf49 100644 --- a/apps/parsley/src/components/SubHeader/EvergreenTaskSubHeader.tsx +++ b/apps/parsley/src/components/SubHeader/EvergreenTaskSubHeader.tsx @@ -1,3 +1,4 @@ +import { useQuery } from "@apollo/client"; import { InlineCode } from "@leafygreen-ui/typography"; import { usePreferencesAnalytics } from "analytics"; import { TaskStatusBadge, TestStatusBadge } from "components/Badge"; @@ -6,6 +7,11 @@ import Icon from "components/Icon"; import { StyledLink } from "components/styles"; import { LogTypes } from "constants/enums"; import { getEvergreenTaskURL } from "constants/externalURLTemplates"; +import { + TestLogUrlAndRenderingTypeQuery, + TestLogUrlAndRenderingTypeQueryVariables, +} from "gql/generated/types"; +import { GET_TEST_LOG_URL_AND_RENDERING_TYPE } from "gql/queries"; import { useTaskQuery } from "hooks/useTaskQuery"; import { shortenGithash, trimStringFromMiddle } from "utils/string"; @@ -27,14 +33,25 @@ export const EvergreenTaskSubHeader: React.FC = ({ testID, }) => { const { sendEvent } = usePreferencesAnalytics(); - const { loading, task } = useTaskQuery({ + const { loading: isLoadingTask, task: taskData } = useTaskQuery({ buildID, execution, logType, taskID, }); - if (loading || !task) { + const { data: testData, loading: isLoadingTest } = useQuery< + TestLogUrlAndRenderingTypeQuery, + TestLogUrlAndRenderingTypeQueryVariables + >(GET_TEST_LOG_URL_AND_RENDERING_TYPE, { + skip: !(logType === LogTypes.EVERGREEN_TEST_LOGS && testID), + variables: { + execution, + taskID, + testName: `^${testID}$`, + }, + }); + if (isLoadingTask || isLoadingTest || !taskData) { return ( <> @@ -47,20 +64,30 @@ export const EvergreenTaskSubHeader: React.FC = ({ ); } - const { displayName, execution: taskExecution, patchNumber, status, versionMetadata, - } = task; + } = taskData; + const { isPatch, message, projectIdentifier, revision } = versionMetadata; - const currentTest = - task?.tests?.testResults?.find((test) => - test?.logs?.urlRaw?.match(new RegExp(`${testID}`)), - ) ?? null; + let currentTest: { testFile: string; status: string } | null = null; + switch (logType) { + case LogTypes.RESMOKE_LOGS: + currentTest = + taskData?.tests?.testResults?.find((test) => + test?.logs?.urlRaw?.match(new RegExp(`${testID}`)), + ) ?? null; + break; + case LogTypes.EVERGREEN_TEST_LOGS: + currentTest = testData?.task?.tests?.testResults?.[0] ?? null; + break; + default: + currentTest = null; + } const breadcrumbs = [ { diff --git a/apps/parsley/src/components/SubHeader/SubHeader.stories.tsx b/apps/parsley/src/components/SubHeader/SubHeader.stories.tsx index da0e7fe52..99df6e534 100644 --- a/apps/parsley/src/components/SubHeader/SubHeader.stories.tsx +++ b/apps/parsley/src/components/SubHeader/SubHeader.stories.tsx @@ -77,7 +77,7 @@ const SubheaderWrapper: React.FC = ({ const { setLogMetadata } = useLogContext(); useEffect(() => { - setLogMetadata({ ...metaData, isUploadedLog }); + setLogMetadata({ ...metaData, logType: LogTypes.LOCAL_UPLOAD }); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return ; diff --git a/apps/parsley/src/components/SubHeader/__snapshots__/SubHeader.stories.storyshot b/apps/parsley/src/components/SubHeader/__snapshots__/SubHeader.stories.storyshot index 3e53bb350..72eef0f4e 100644 --- a/apps/parsley/src/components/SubHeader/__snapshots__/SubHeader.stories.storyshot +++ b/apps/parsley/src/components/SubHeader/__snapshots__/SubHeader.stories.storyshot @@ -10,28 +10,21 @@ exports[`Snapshot Tests SubHeader.stories TaskFileLog 1`] = ` class="css-1xawlld" > - -