Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -37430,15 +37430,13 @@
"xpack.searchInferenceEndpoints.filter.emptyMessage": "Keine Optionen",
"xpack.searchInferenceEndpoints.filter.options": "{totalCount, plural, one {# option} other {# Optionen}}",
"xpack.searchInferenceEndpoints.groupBy.label": "Gruppe: {selectedGroup}",
"xpack.searchInferenceEndpoints.groupBy.options.models.label": "Modellautor",
"xpack.searchInferenceEndpoints.groupBy.options.none.label": "Keine",
"xpack.searchInferenceEndpoints.groupBy.options.service.label": "Service",
"xpack.searchInferenceEndpoints.groupedEndpoints.collapseAll": "Alle einklappen",
"xpack.searchInferenceEndpoints.groupedEndpoints.expandAll": "Alle erweitern",
"xpack.searchInferenceEndpoints.groupedEndpoints.headers.endpointsCountBadge": "{endpointCount} {endpointCount, plural, one {endpoint} other {endpoints}}",
"xpack.searchInferenceEndpoints.groupedEndpoints.headers.icon.title": "{serviceName} Service-Logo",
"xpack.searchInferenceEndpoints.groupedEndpoints.tableCaption": "Liste der Inferenz-Endpoints, gruppiert nach {groupBy}: {groupId}",
"xpack.searchInferenceEndpoints.groupedEndpoints.unknownModelLabel": "Unbekanntes Modell",
"xpack.searchInferenceEndpoints.knownModelGroups.anthropic.label": "Anthropic",
"xpack.searchInferenceEndpoints.knownModelGroups.e5.label": "Mehrsprachig E5",
"xpack.searchInferenceEndpoints.knownModelGroups.elastic.label": "Elastic",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37359,15 +37359,13 @@
"xpack.searchInferenceEndpoints.filter.emptyMessage": "Aucune option",
"xpack.searchInferenceEndpoints.filter.options": "{totalCount, plural, one {# option} other {# options}}",
"xpack.searchInferenceEndpoints.groupBy.label": "Groupe : {selectedGroup}",
"xpack.searchInferenceEndpoints.groupBy.options.models.label": "Auteur du modèle",
"xpack.searchInferenceEndpoints.groupBy.options.none.label": "Aucun",
"xpack.searchInferenceEndpoints.groupBy.options.service.label": "Service",
"xpack.searchInferenceEndpoints.groupedEndpoints.collapseAll": "Tout réduire",
"xpack.searchInferenceEndpoints.groupedEndpoints.expandAll": "Tout développer",
"xpack.searchInferenceEndpoints.groupedEndpoints.headers.endpointsCountBadge": "{endpointCount} {endpointCount, plural, one {endpoint} other {points de terminaison}}",
"xpack.searchInferenceEndpoints.groupedEndpoints.headers.icon.title": "Logo du service {serviceName}",
"xpack.searchInferenceEndpoints.groupedEndpoints.tableCaption": "Liste des points de terminaison d’inférence regroupés par {groupBy} : {groupId}",
"xpack.searchInferenceEndpoints.groupedEndpoints.unknownModelLabel": "Modèle inconnu",
"xpack.searchInferenceEndpoints.knownModelGroups.anthropic.label": "Anthropic",
"xpack.searchInferenceEndpoints.knownModelGroups.e5.label": "E5 multilingue",
"xpack.searchInferenceEndpoints.knownModelGroups.elastic.label": "Elastic",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37551,15 +37551,13 @@
"xpack.searchInferenceEndpoints.filter.emptyMessage": "オプションなし",
"xpack.searchInferenceEndpoints.filter.options": "{totalCount, plural, one {# option} other {#件のオプション}}",
"xpack.searchInferenceEndpoints.groupBy.label": "グループ:{selectedGroup}",
"xpack.searchInferenceEndpoints.groupBy.options.models.label": "モデル作成者",
"xpack.searchInferenceEndpoints.groupBy.options.none.label": "なし",
"xpack.searchInferenceEndpoints.groupBy.options.service.label": "サービス",
"xpack.searchInferenceEndpoints.groupedEndpoints.collapseAll": "すべて折りたたむ",
"xpack.searchInferenceEndpoints.groupedEndpoints.expandAll": "すべて展開",
"xpack.searchInferenceEndpoints.groupedEndpoints.headers.endpointsCountBadge": "{endpointCount} {endpointCount, plural, one {endpoint} other {エンドポイント}}",
"xpack.searchInferenceEndpoints.groupedEndpoints.headers.icon.title": "{serviceName} サービスロゴ",
"xpack.searchInferenceEndpoints.groupedEndpoints.tableCaption": "推論エンドポイントのリスト({groupBy}:{groupId}でグループ化)",
"xpack.searchInferenceEndpoints.groupedEndpoints.unknownModelLabel": "不明なモデル",
"xpack.searchInferenceEndpoints.knownModelGroups.anthropic.label": "Anthropic",
"xpack.searchInferenceEndpoints.knownModelGroups.e5.label": "Multilingual E5",
"xpack.searchInferenceEndpoints.knownModelGroups.elastic.label": "Elastic",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37555,14 +37555,12 @@
"xpack.searchInferenceEndpoints.filter.emptyMessage": "无选项",
"xpack.searchInferenceEndpoints.filter.options": "{totalCount, plural, one {# option} other {# 个选项}}",
"xpack.searchInferenceEndpoints.groupBy.label": "组:{selectedGroup}",
"xpack.searchInferenceEndpoints.groupBy.options.models.label": "模型作者",
"xpack.searchInferenceEndpoints.groupBy.options.none.label": "无",
"xpack.searchInferenceEndpoints.groupBy.options.service.label": "服务",
"xpack.searchInferenceEndpoints.groupedEndpoints.collapseAll": "折叠全部",
"xpack.searchInferenceEndpoints.groupedEndpoints.expandAll": "展开全部",
"xpack.searchInferenceEndpoints.groupedEndpoints.headers.icon.title": "{serviceName} 服务徽标",
"xpack.searchInferenceEndpoints.groupedEndpoints.tableCaption": "推理终端列表按 {groupBy} 分组:{groupId}",
"xpack.searchInferenceEndpoints.groupedEndpoints.unknownModelLabel": "未知模型",
"xpack.searchInferenceEndpoints.knownModelGroups.anthropic.label": "Anthropic",
"xpack.searchInferenceEndpoints.knownModelGroups.e5.label": "多语言 E5",
"xpack.searchInferenceEndpoints.knownModelGroups.elastic.label": "Elastic",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,17 +38,6 @@ describe('GroupBySelect', () => {
expect(getByText(/None/i)).toBeInTheDocument();
});

it('should render the filter button with "Model Author" when model_id is selected', () => {
const { getByText } = render(
<Wrapper>
<GroupBySelect value={GroupByOptions.Model} onChange={mockOnChange} />
</Wrapper>
);

expect(getByText(/Group:/i)).toBeInTheDocument();
expect(getByText(/Model Author/i)).toBeInTheDocument();
});

it('should render the filter button with "Service" when service is selected', () => {
const { getByText } = render(
<Wrapper>
Expand Down Expand Up @@ -99,42 +88,10 @@ describe('GroupBySelect', () => {
});
});

it('should call onChange with GroupByOptions.Model when "Models" option is selected', async () => {
const { getByRole } = render(
<Wrapper>
<GroupBySelect value={GroupByOptions.None} onChange={mockOnChange} />
</Wrapper>
);

// Open popover
const filterButton = getByRole('button');
fireEvent.click(filterButton);

await waitFor(() => {
const options = document.querySelectorAll('[role="option"]');
expect(options.length).toBeGreaterThan(0);
});

// Find and click the "Models" option
const options = document.querySelectorAll('[role="option"]');
const modelsOption = Array.from(options).find((option) =>
option.textContent?.includes('Model Author')
);

expect(modelsOption).toBeDefined();
if (modelsOption) {
fireEvent.click(modelsOption);
}

await waitFor(() => {
expect(mockOnChange).toHaveBeenCalledWith(GroupByOptions.Model);
});
});

it('should call onChange with GroupByOptions.None when "None" option is selected', async () => {
const { getByRole } = render(
<Wrapper>
<GroupBySelect value={GroupByOptions.Model} onChange={mockOnChange} />
<GroupBySelect value={GroupByOptions.Service} onChange={mockOnChange} />
</Wrapper>
);

Expand Down Expand Up @@ -210,12 +167,12 @@ describe('GroupBySelect', () => {

// Select an option
const options = document.querySelectorAll('[role="option"]');
const modelsOption = Array.from(options).find((option) =>
option.textContent?.includes('Model Author')
const serviceOption = Array.from(options).find((option) =>
option.textContent?.includes('Service')
);

if (modelsOption) {
fireEvent.click(modelsOption);
if (serviceOption) {
fireEvent.click(serviceOption);
}

// Popover should close after selection
Expand All @@ -227,7 +184,7 @@ describe('GroupBySelect', () => {
it('should mark the current selection as checked', async () => {
const { getByRole } = render(
<Wrapper>
<GroupBySelect value={GroupByOptions.Model} onChange={mockOnChange} />
<GroupBySelect value={GroupByOptions.Service} onChange={mockOnChange} />
</Wrapper>
);

Expand All @@ -237,18 +194,18 @@ describe('GroupBySelect', () => {

await waitFor(() => {
const options = document.querySelectorAll('[role="option"]');
expect(options.length).toBe(3);
expect(options.length).toBe(2);
});

// Check that the "Models" option is marked as checked
// Check that the "Service" option is marked as checked
const options = document.querySelectorAll('[role="option"]');
const modelsOption = Array.from(options).find((option) =>
option.textContent?.includes('Model Author')
const serviceOption = Array.from(options).find((option) =>
option.textContent?.includes('Service')
) as HTMLElement;

expect(modelsOption).toBeDefined();
if (modelsOption) {
expect(modelsOption.getAttribute('aria-selected')).toBe('true');
expect(serviceOption).toBeDefined();
if (serviceOption) {
expect(serviceOption.getAttribute('aria-selected')).toBe('true');
}
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,6 @@ const GROUP_BY_OPTIONS = [
defaultMessage: 'None',
}),
},
{
key: GroupByOptions.Model,
label: i18n.translate('xpack.searchInferenceEndpoints.groupBy.options.models.label', {
defaultMessage: 'Model Author',
}),
},
{
key: GroupByOptions.Service,
label: i18n.translate('xpack.searchInferenceEndpoints.groupBy.options.service.label', {
Expand All @@ -49,8 +43,6 @@ const GROUP_BY_OPTIONS = [

function parseGroupByValue(value: string | undefined): GroupByOptions {
switch (value) {
case GroupByOptions.Model:
return GroupByOptions.Model;
case GroupByOptions.Service:
return GroupByOptions.Service;
case GroupByOptions.None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,114 +323,6 @@ describe('When the tabular page is loaded', () => {
expect(rows[11]).not.toHaveTextContent(techPreview);
});
});
describe('group by models', () => {
beforeEach(() => {
renderTabularPageWithProviders();
});

it('should display accordions with tables for model groups', () => {
const groupAccordions = screen.getAllByTestId(/-accordion$/);
expect(groupAccordions).toHaveLength(6);
const groupTables = screen.getAllByTestId(/-table$/);
expect(groupTables).toHaveLength(6);
});

it('should have expected endpoint table columns', () => {
const endpointTables = screen.getAllByTestId(/-table$/);

endpointTables.forEach((table) => {
const columnHeaders = within(table).getAllByRole('columnheader');
const headerLabels = columnHeaders.map((header) => header.textContent?.trim() ?? '');

expect(headerLabels).toEqual(['Endpoint', 'Model', 'Service', '']);
});
});

it('should show expected group labels and endpoint counts', () => {
const expectedGroups = [
{
groupId: 'Elastic',
label: 'Elastic',
countLabel: '5 endpoints',
},
{
groupId: 'Anthropic',
label: 'Anthropic',
countLabel: '1 endpoint',
},
{
groupId: '.own_model',
label: '.own_model',
countLabel: '2 endpoints',
},
{
groupId: 'multilingual-e5',
label: 'Multilingual E5',
countLabel: '1 endpoint',
},
{
groupId: 'multilingual-embed-v1',
label: 'multilingual-embed-v1',
countLabel: '1 endpoint',
},
{
groupId: 'rerank-v1',
label: 'rerank-v1',
countLabel: '1 endpoint',
},
];

expectedGroups.forEach(({ groupId, label, countLabel }) => {
const accordionHeader = screen.getByTestId(`${groupId}-accordion-header`);
expect(within(accordionHeader).getByText(label)).toBeInTheDocument();
expect(within(accordionHeader).getByText(countLabel)).toBeInTheDocument();
});
});

it('should show empty prompt when search removes all groups', async () => {
fireEvent.change(screen.getByTestId('search-field-endpoints'), {
target: { value: 'no-matching-endpoint' },
});

expect(await screen.findByText('No items found')).toBeInTheDocument();
});

it('should disable delete action for preconfigured endpoints in grouped tables', () => {
const elserTable = screen.getByTestId('Elastic-table');

const preconfiguredRow = within(elserTable).getByText('.elser-2-elastic').closest('tr');

expect(preconfiguredRow).not.toBeNull();

act(() => {
within(preconfiguredRow as HTMLElement)
.getByTestId('euiCollapsedItemActionsButton')
.click();
});

const deleteAction = screen.getByTestId(/inferenceUIDeleteAction/);

expect(deleteAction).toBeDisabled();
});

it('should enable delete action for user-defined endpoints in grouped tables', () => {
const elserTable = screen.getByTestId('Elastic-table');

const userDefinedRow = within(elserTable).getByText('custom-inference-id').closest('tr');

expect(userDefinedRow).not.toBeNull();

act(() => {
within(userDefinedRow as HTMLElement)
.getByTestId('euiCollapsedItemActionsButton')
.click();
});

const deleteAction = screen.getByTestId(/inferenceUIDeleteAction/);

expect(deleteAction).toBeEnabled();
});
});
describe('group by service', () => {
beforeAll(() => {
window.history.pushState({}, '', '?groupBy=service');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const searchContainerStyles = ({ euiTheme }: UseEuiTheme) => css`
width: ${euiTheme.base * 25}px;
`;

const DEFAULT_GROUP_BY = GroupByOptions.Model;
const DEFAULT_GROUP_BY = GroupByOptions.None;

const initializeGroupBy = (): GroupByOptions => {
const params = new URLSearchParams(window.location.search);
Expand All @@ -52,8 +52,6 @@ const initializeGroupBy = (): GroupByOptions => {
return GroupByOptions.None;
case GroupByOptions.Service:
return GroupByOptions.Service;
case GroupByOptions.Model:
return GroupByOptions.Model;
default:
// Fallback to default group by setting
return DEFAULT_GROUP_BY;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,37 +9,23 @@ import { renderHook } from '@testing-library/react';

import { InferenceEndpoints } from '../__mocks__/inference_endpoints';

import { UNKNOWN_MODEL_ID_FALLBACK } from '../utils/group_by';
import { useGroupedData } from './use_grouped_data';
import { GroupByOptions } from '../types';

describe('useGroupedData', () => {
it('should return empty groupedEndpoints and filteredEndpoints when no endpoints provided', () => {
const { result } = renderHook(() =>
useGroupedData([], GroupByOptions.Model, { provider: [], type: [] }, '')
useGroupedData([], GroupByOptions.Service, { provider: [], type: [] }, '')
);

expect(result.current).toEqual({ groupedEndpoints: [], filteredEndpoints: [] });
});

it('should sort elastic endpoints first when grouping by model', () => {
it('should sort elastic services first when grouping by service', () => {
const { result } = renderHook(() =>
useGroupedData(InferenceEndpoints, GroupByOptions.Model, { provider: [], type: [] }, '')
useGroupedData(InferenceEndpoints, GroupByOptions.Service, { provider: [], type: [] }, '')
);

expect(result.current.groupedEndpoints[0].groupId).toBe('Elastic');
});

it('should group endpoints with unknown model_id under unknown model group', () => {
const { result } = renderHook(() =>
useGroupedData(InferenceEndpoints, GroupByOptions.Model, { provider: [], type: [] }, '')
);

const unknownModelGroup = result.current.groupedEndpoints.find(
(group) => group.groupId === UNKNOWN_MODEL_ID_FALLBACK
);
expect(unknownModelGroup).toBeDefined();
expect(unknownModelGroup!.groupLabel).toBe('Unknown Model');
expect(unknownModelGroup!.endpoints).toHaveLength(2);
expect(result.current.groupedEndpoints[0].groupId).toBe('elastic');
});
});
Loading
Loading