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

Initial query performance sidebar e2e #5162

Merged
merged 7 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ const NumericFieldFilter = ({ color, modal, named = true, path }: Props) => {
};

return (
<Container onClick={(e) => e.stopPropagation()}>
<Container
data-cy={`numeric-filter-${path}`}
onClick={(e) => e.stopPropagation()}
>
{named && name && (
<FieldLabelAndInfo
nested
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Selector, useTheme } from "@fiftyone/components";
import * as fos from "@fiftyone/state";
import Bolt from "@mui/icons-material/Bolt";
import React from "react";
import type { RecoilState } from "recoil";
import { useRecoilValue } from "recoil";
import styled from "styled-components";
import FieldLabelAndInfo from "../../FieldLabelAndInfo";
import { LightningBolt } from "../../Sidebar/Entries/FilterablePathEntry/Icon";
import { isInKeypointsField } from "../state";
import useQueryPerformanceTimeout from "../use-query-performance-timeout";
import Checkboxes from "./Checkboxes";
Expand Down Expand Up @@ -103,9 +103,7 @@ const StringFilter = ({
template={({ label, hoverTarget }) => (
<NamedStringFilterHeader>
<span ref={hoverTarget}>{label}</span>
{showQueryPerformanceIcon && (
<Bolt fontSize={"small"} sx={{ color: theme.action.active }} />
)}
{showQueryPerformanceIcon && <LightningBolt />}
</NamedStringFilterHeader>
)}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@ import { useRecoilValue } from "recoil";
import styled from "styled-components";
import Arrow from "./Arrow";

export const LightningIcon = styled(Bolt)`
const LightningIcon = styled(Bolt)`
color: ${({ theme }) => theme.text.secondary};
`;

export const LightningBolt: React.FC = (_) => {
return (
<Tooltip placement="top-center" text={"Indexed"}>
<LightningIcon style={{ height: 16, marginRight: 2, width: 16 }} />
<LightningIcon
data-cy={"query-performance"}
style={{ height: 16, marginRight: 2, width: 16 }}
/>
</Tooltip>
);
};
Expand Down
4 changes: 2 additions & 2 deletions e2e-pw/src/oss/poms/action-row/display-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Page } from "src/oss/fixtures";
type SidebarStatisticsMode = "slice" | "group";
type SidebarMode = "fast" | "best" | "all";
type SidebarSortMode = "count" | "value";
type LightningMode = "enable" | "disable";
type QueryPerformanceMode = "enabled" | "disabled";

export class DisplayOptionsPom {
readonly page: Page;
Expand All @@ -12,7 +12,7 @@ export class DisplayOptionsPom {
this.page = page;
}

async setLightningMode(mode: LightningMode) {
async setQueryPerformance(mode: QueryPerformanceMode) {
const selector = this.page.getByTestId(`qp-mode-${mode}`);
return selector.click();
}
Expand Down
29 changes: 29 additions & 0 deletions e2e-pw/src/oss/poms/sidebar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,13 @@ export class SidebarPom {
return this.sidebar.getByTestId(`${filterType}-filter-${fieldName}`);
}

queryPerformance(fieldName: string, filterType?: "categorical" | "numeric") {
const locator = filterType
? this.filter(fieldName, filterType)
: this.fieldContainer(fieldName);
return locator.getByTestId("query-performance");
}

sidebarEntryDraggableArea(fieldName: string) {
return this.sidebar
.getByTestId(`sidebar-entry-draggable-${fieldName}`)
Expand Down Expand Up @@ -179,6 +186,28 @@ class SidebarAsserter {
}
}

async assertFieldHasQueryPerformance(fieldName: string) {
await expect(this.sb.queryPerformance(fieldName)).toBeVisible();
}

async assertFieldMissingQueryPerformance(fieldName: string) {
await expect(this.sb.queryPerformance(fieldName)).toBeHidden();
}

async assertSubfieldHasQueryPerformance(
fieldName: string,
filterType?: "categorical" | "numeric"
) {
await expect(this.sb.queryPerformance(fieldName, filterType)).toBeVisible();
}

async assertSubfieldMissingQueryPerformance(
fieldName: string,
filterType?: "categorical" | "numeric"
) {
await expect(this.sb.queryPerformance(fieldName, filterType)).toBeHidden();
}

async assertFieldInSidebar(fieldName: string) {
await expect(this.sb.field(fieldName)).toBeVisible();
}
Expand Down
246 changes: 246 additions & 0 deletions e2e-pw/src/oss/specs/sidebar/query-performance.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
import { test as base } from "src/oss/fixtures";
import { GridPom } from "src/oss/poms/grid";
import { SidebarPom } from "src/oss/poms/sidebar";
import { getUniqueDatasetNameWithPrefix } from "src/oss/utils";

const datasetName = getUniqueDatasetNameWithPrefix("query-performance");

const test = base.extend<{ sidebar: SidebarPom; grid: GridPom }>({
grid: async ({ page, eventUtils }, use) => {
await use(new GridPom(page, eventUtils));
},
sidebar: async ({ page }, use) => {
await use(new SidebarPom(page));
},
});

test.describe("query performance sidebar", () => {
test.beforeAll(async ({ fiftyoneLoader }) => {
await fiftyoneLoader.executePythonCode(`
import fiftyone as fo

dataset = fo.Dataset("${datasetName}")
dataset.add_samples([fo.Sample(filepath=f"{i}.png") for i in range(0, 4)])
dataset.persistent = True

# NOT REAL VALUES

first = dataset.first()

first["bool"] = False
first["bool_list"] = [False]

first["inf"] = float("inf")
first["inf_list"] = [float("inf")]
first["inf_label_list"] = fo.Classifications(
classifications=[fo.Classification(label="label", confidence=float("inf"))]
)

first["nan"] = float("nan")
first["nan_list"] = [float("nan")]
first["nan_label_list"] = fo.Classifications(
classifications=[fo.Classification(label="label", confidence=float("nan"))]
)

first["ninf"] = float("-inf")
first["ninf_list"] = [float("-inf")]
first["ninf_label_list"] = fo.Classifications(
classifications=[
fo.Classification(label="label", confidence=float("-inf"))
]
)


first["str"] = "0"
first["str_list"] = ["0"]

first.save()

# REAL VALUES MAX

second = dataset.skip(1).first()

second["bool"] = False
second["bool_list"] = [False]

second["inf"] = 1.0
second["inf_list"] = [1.0]
second["inf_label_list"] = fo.Classifications(
classifications=[fo.Classification(label="label", confidence=1.0)]
)

second["nan"] = 1.0
second["nan_list"] = [1.0]
second["nan_label_list"] = fo.Classifications(
classifications=[fo.Classification(label="label", confidence=1.0)]
)

second["ninf"] = 1.0
second["ninf_list"] = [1.0]
second["ninf_label_list"] = fo.Classifications(
classifications=[fo.Classification(label="label", confidence=float(1.0))]
)

second["str"] = "1"
second["str_list"] = ["1"]

second.save()

# REAL VALUES MIN

third = dataset.skip(2).first()

third["bool"] = True
third["bool_list"] = [True]

third["inf"] = -1.0
third["inf_list"] = [-1.0]
third["inf_label_list"] = fo.Classifications(
classifications=[fo.Classification(label="label", confidence=-1.0)]
)

third["nan"] = -1.0
third["nan_list"] = [-1.0]
third["nan_label_list"] = fo.Classifications(
classifications=[fo.Classification(label="label", confidence=-1.0)]
)

third["ninf"] = -1.0
third["ninf_list"] = [-1.0]
third["ninf_label_list"] = fo.Classifications(
classifications=[fo.Classification(label="label", confidence=-1.0)]
)

third["str"] = "2"
third["str_list"] = ["2"]

third.save()

# NONE VALUES

fourth = dataset.skip(3).first()

fourth["bool"] = None
fourth["bool_list"] = None

fourth["inf"] = None
fourth["inf_list"] = None
fourth["inf_label_list"] = fo.Classifications(
classifications=[fo.Classification(label="label", confidence=None)]
)

fourth["nan"] = None
fourth["nan_list"] = None
fourth["nan_label_list"] = fo.Classifications(
classifications=[fo.Classification(label="label", confidence=None)]
)

fourth["ninf"] = None
fourth["ninf_list"] = None
fourth["ninf_label_list"] = fo.Classifications(
classifications=[fo.Classification(label="label", confidence=None)]
)

fourth["str"] = None
fourth["str_list"] = None

dataset.create_index("$**")

fourth.save()`);
});

test.beforeEach(async ({ page, fiftyoneLoader }) => {
await fiftyoneLoader.waitUntilGridVisible(page, datasetName);
});

test("assert query performance icons", async ({
eventUtils,
grid,
sidebar,
}) => {
await grid.actionsRow.toggleDisplayOptions();
await grid.actionsRow.displayActions.setQueryPerformance("enabled");
for (const field of [
"tags",
"metadata.mime_type",
"inf_label_list",
"nan_label_list",
"ninf_label_list",
"id",
"filepath",
"created_at",
"last_modified_at",
"bool",
"bool_list",
"str",
"str_list",
]) {
await sidebar.asserter.assertFieldHasQueryPerformance(field);
}

for (const field of [
"_label_tags",
"metadata.size_bytes",
"metadata.width",
"metadata.height",
"metadata.num_channels",
"inf",
"inf_list",
"nan",
"nan_list",
"ninf",
"ninf_list",
]) {
await sidebar.asserter.assertFieldMissingQueryPerformance(field);
}

let animation = eventUtils.getEventReceivedPromiseForPredicate(
"animation-onRest",
() => true
);
await sidebar.clickFieldDropdown("inf_label_list");
await animation;

animation = eventUtils.getEventReceivedPromiseForPredicate(
"animation-onRest",
() => true
);
await sidebar.clickFieldDropdown("nan_label_list");
await animation;

animation = eventUtils.getEventReceivedPromiseForPredicate(
"animation-onRest",
() => true
);
await sidebar.clickFieldDropdown("ninf_label_list");
await animation;

const subfieldsIndexed = ["id", "label", "tags"];
for (const field of [
"inf_label_list",
"nan_label_list",
"ninf_label_list",
]) {
for (const subfield of subfieldsIndexed) {
await sidebar.asserter.assertSubfieldHasQueryPerformance(
`${field}.classifications.${subfield}`,
"categorical"
);
}
}

const subfieldsUnindexed = ["confidence"];
for (const field of [
"inf_label_list",
"nan_label_list",
"ninf_label_list",
]) {
for (const subfield of subfieldsUnindexed) {
await sidebar.asserter.assertSubfieldMissingQueryPerformance(
`${field}.classifications.${subfield}`,
"categorical"
);
}
}
});
});
Loading