Skip to content

Commit 36b07cb

Browse files
Merge branch 'main' into fix/registry-name-field-validation
2 parents e48950c + 6a0fbf3 commit 36b07cb

52 files changed

Lines changed: 2610 additions & 276 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

frontend/src/pages/modelRegistrySettings/ModelRegistriesTableRow.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { BellIcon, InfoCircleIcon } from '@patternfly/react-icons';
66
import { ModelRegistryKind, RoleBindingKind } from '#~/k8sTypes';
77
import { FetchStateObject } from '#~/utilities/useFetch';
88
import ResourceNameTooltip from '#~/components/ResourceNameTooltip';
9+
import TruncatedText from '#~/components/TruncatedText';
910
import { filterRoleBindingSubjects } from '#~/concepts/roleBinding/utils';
1011
import { RoleBindingPermissionsRBType } from '#~/concepts/roleBinding/types';
1112
import { ModelRegistryTableRowStatus } from './ModelRegistryTableRowStatus';
@@ -85,7 +86,10 @@ const ModelRegistriesTableRow: React.FC<ModelRegistriesTableRowProps> = ({
8586
)}
8687
</Flex>
8788
{mr.metadata.annotations?.['openshift.io/description'] && (
88-
<p>{mr.metadata.annotations['openshift.io/description']}</p>
89+
<TruncatedText
90+
maxLines={2}
91+
content={mr.metadata.annotations['openshift.io/description']}
92+
/>
8993
)}
9094
</Td>
9195
<Td dataLabel="Status">

frontend/src/pages/modelServing/screens/metrics/__tests__/utils.spec.ts

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import { convertInputType } from '#~/pages/modelServing/screens/metrics/utils';
1+
import {
2+
convertInputType,
3+
toPercentage,
4+
per100,
5+
} from '#~/pages/modelServing/screens/metrics/utils';
26

37
describe('convertInputType', () => {
48
describe('string inputs', () => {
@@ -40,3 +44,82 @@ describe('convertInputType', () => {
4044
});
4145
});
4246
});
47+
48+
describe('toPercentage', () => {
49+
it('should round percentage values to 2 decimal places', () => {
50+
const input = { x: 1000, y: 0.09896161479334678, name: 'test' };
51+
const result = toPercentage(input);
52+
expect(result.y).toBe(9.9);
53+
});
54+
55+
it('should handle values that round up', () => {
56+
const input = { x: 1000, y: Number('0.15228456789012345'), name: 'test' };
57+
const result = toPercentage(input);
58+
expect(result.y).toBe(15.23);
59+
});
60+
61+
it('should handle values that round down', () => {
62+
const input = { x: 1000, y: 0.15224, name: 'test' };
63+
const result = toPercentage(input);
64+
expect(result.y).toBe(15.22);
65+
});
66+
67+
it('should handle edge case near 100%', () => {
68+
const input = { x: 1000, y: 0.999999, name: 'test' };
69+
const result = toPercentage(input);
70+
expect(result.y).toBe(100);
71+
});
72+
73+
it('should handle edge case near 0%', () => {
74+
const input = { x: 1000, y: 0.005, name: 'test' };
75+
const result = toPercentage(input);
76+
expect(result.y).toBe(0.5);
77+
});
78+
79+
it('should handle exact zero', () => {
80+
const input = { x: 1000, y: 0, name: 'test' };
81+
const result = toPercentage(input);
82+
expect(result.y).toBe(0);
83+
});
84+
85+
it('should preserve x and name properties', () => {
86+
const input = { x: 12345, y: 0.5, name: 'Memory Usage' };
87+
const result = toPercentage(input);
88+
expect(result.x).toBe(12345);
89+
expect(result.name).toBe('Memory Usage');
90+
});
91+
92+
it('should handle floating-point precision artifacts', () => {
93+
// Test that floating-point errors like 99.99999999999999 get properly rounded
94+
const input = { x: 1000, y: 0.9999999999999999, name: 'test' };
95+
const result = toPercentage(input);
96+
expect(result.y).toBe(100);
97+
});
98+
});
99+
100+
describe('per100', () => {
101+
it('should divide by 100 and round to 2 decimal places', () => {
102+
const input = { x: 1000, y: 989.6161479334678, name: 'test' };
103+
const result = per100(input);
104+
expect(result.y).toBe(9.9);
105+
});
106+
107+
it('should handle values that round up', () => {
108+
const input = { x: 1000, y: Number('1522.8456789012345'), name: 'test' };
109+
const result = per100(input);
110+
expect(result.y).toBe(15.23);
111+
});
112+
113+
it('should handle exact zero', () => {
114+
const input = { x: 1000, y: 0, name: 'test' };
115+
const result = per100(input);
116+
expect(result.y).toBe(0);
117+
});
118+
119+
it('should preserve x and name properties', () => {
120+
const input = { x: 12345, y: 5000, name: 'CPU Usage' };
121+
const result = per100(input);
122+
expect(result.x).toBe(12345);
123+
expect(result.name).toBe('CPU Usage');
124+
});
125+
});

frontend/src/pages/modelServing/screens/metrics/utils.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ export const per100: TranslatePoint = (point) => ({
107107

108108
export const toPercentage: TranslatePoint = (point) => ({
109109
...point,
110-
y: point.y * 100,
110+
y: Number((point.y * 100).toFixed(2)),
111111
});
112112

113113
export const createGraphMetricLine = ({

packages/cypress/cypress/pages/modelsAsAService.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,30 @@ class APIKeysPage {
409409
findCreateApiKeyButton(): Cypress.Chainable<JQuery<HTMLElement>> {
410410
return cy.findByTestId('create-api-key-button');
411411
}
412+
413+
findStatusFilterToggle(): Cypress.Chainable<JQuery<HTMLElement>> {
414+
return cy.findByTestId('api-key-status-filter-toggle');
415+
}
416+
417+
findStatusFilterOption(status: string): Cypress.Chainable<JQuery<HTMLElement>> {
418+
return cy.findByRole('menuitem', { name: new RegExp(status, 'i') });
419+
}
420+
421+
findColumnSortButton(columnLabel: string): Cypress.Chainable<JQuery<HTMLElement>> {
422+
return this.findTable().find('thead').contains('th', columnLabel).findByRole('button');
423+
}
424+
425+
findFilterInput(): Cypress.Chainable<JQuery<HTMLElement>> {
426+
return cy.findByTestId('username-filter-input');
427+
}
428+
429+
findFilterSearchButton(): Cypress.Chainable<JQuery<HTMLElement>> {
430+
return this.findFilterInput().find('button[type="submit"]');
431+
}
432+
433+
findUsernameFilterTooltip(): Cypress.Chainable<JQuery<HTMLElement>> {
434+
return cy.findByTestId('username-filter-tooltip');
435+
}
412436
}
413437

414438
class APIKeyTableRow extends TableRow {

packages/cypress/cypress/support/commands/odh.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1118,11 +1118,6 @@ declare global {
11181118
type: 'POST /maas/api/v1/api-keys/search',
11191119
response: { data: OdhResponse<APIKeyListResponse> },
11201120
) => Cypress.Chainable<null>) &
1121-
((
1122-
type: 'POST /maas/api/v1/api-keys/search',
1123-
options: { query?: { page?: string; limit?: string } },
1124-
response: { data: OdhResponse<APIKeyListResponse> },
1125-
) => Cypress.Chainable<null>) &
11261121
((
11271122
type: 'POST /maas/api/v1/api-keys/bulk-revoke',
11281123
response: { data: OdhResponse<BulkRevokeResponse> },

0 commit comments

Comments
 (0)