Skip to content

Commit

Permalink
Add no metrics state for compare runs metrics section
Browse files Browse the repository at this point in the history
  • Loading branch information
DaoDaoNoCode committed Jul 10, 2024
1 parent 3b48d99 commit b81f061
Show file tree
Hide file tree
Showing 11 changed files with 248 additions and 160 deletions.
138 changes: 73 additions & 65 deletions frontend/src/__mocks__/mlmd/mockGetArtifactsByContext.ts
Original file line number Diff line number Diff line change
@@ -1,113 +1,121 @@
import { Artifact, GetArtifactsByContextResponse } from '~/__mocks__/third_party/mlmd';
import createGrpcResponse, { GrpcResponse } from './utils';

const mockedScalarMetricArtifact: Artifact = {
const mockedScalarMetricArtifact = (noMetrics?: boolean): Artifact => ({
id: 7,
typeId: 17,
type: 'system.Metrics',
uri: 's3://aballant-pipelines/metrics-visualization-pipeline/f0b586ba-3e7b-4369-8d48-592e83cbbf73/digit-classification/metrics',
properties: {},
customProperties: {
accuracy: { doubleValue: 92 },
displayName: { stringValue: 'metrics' },
},
customProperties: noMetrics
? {}
: {
accuracy: { doubleValue: 92 },
displayName: { stringValue: 'metrics' },
},
state: 2,
createTimeSinceEpoch: 1711765118976,
lastUpdateTimeSinceEpoch: 1711765118976,
};
});

const mockedConfusionMatrixArtifact: Artifact = {
const mockedConfusionMatrixArtifact = (noMetrics?: boolean): Artifact => ({
id: 8,
typeId: 18,
type: 'system.ClassificationMetrics',
uri: 's3://aballant-pipelines/metrics-visualization-pipeline/ccdfe85e-06cc-4a63-b10d-a12d688d2ec3/iris-sgdclassifier/metrics',
properties: {},
customProperties: {
confusionMatrix: {
structValue: {
struct: {
annotationSpecs: [
{ displayName: 'Setosa' },
{ displayName: 'Versicolour' },
{ displayName: 'Virginica' },
],
rows: [
{
row: [38, 0, 0],
},
{
row: [2, 19, 9],
customProperties: noMetrics
? {}
: {
confusionMatrix: {
structValue: {
struct: {
annotationSpecs: [
{ displayName: 'Setosa' },
{ displayName: 'Versicolour' },
{ displayName: 'Virginica' },
],
rows: [
{
row: [38, 0, 0],
},
{
row: [2, 19, 9],
},
{
row: [1, 17, 19],
},
],
},
{
row: [1, 17, 19],
},
],
},
},
displayName: {
stringValue: 'metrics',
},
},
},
displayName: {
stringValue: 'metrics',
},
},
state: 2,
createTimeSinceEpoch: 1711765608345,
lastUpdateTimeSinceEpoch: 1711765608345,
};
});

const mockedRocCurveArtifact: Artifact = {
const mockedRocCurveArtifact = (noMetrics?: boolean): Artifact => ({
id: 9,
typeId: 18,
type: 'system.ClassificationMetrics',
uri: 's3://aballant-pipelines/metrics-visualization-pipeline/aa61378c-d507-4bde-aa18-9f8678b2beb6/wine-classification/metrics',
properties: {},
customProperties: {
confidenceMetrics: {
structValue: {
list: [
{ confidenceThreshold: 2, falsePositiveRate: 0, recall: 0 },
{ confidenceThreshold: 1, falsePositiveRate: 0, recall: 0.33962264150943394 },
{ confidenceThreshold: 0, falsePositiveRate: 0, recall: 0.6037735849056604 },
{ confidenceThreshold: 0.8, falsePositiveRate: 0, recall: 0.8490566037735849 },
{ confidenceThreshold: 0.6, falsePositiveRate: 0, recall: 0.8867924528301887 },
{ confidenceThreshold: 0.5, falsePositiveRate: 0.0125, recall: 0.9245283018867925 },
{ confidenceThreshold: 0.4, falsePositiveRate: 0.075, recall: 0.9622641509433962 },
{ confidenceThreshold: 0.3, falsePositiveRate: 0.0875, recall: 1 },
{ confidenceThreshold: 0.2, falsePositiveRate: 0.2375, recall: 1 },
{ confidenceThreshold: 0.1, falsePositiveRate: 0.475, recall: 1 },
{ confidenceThreshold: 0, falsePositiveRate: 1, recall: 1 },
],
customProperties: noMetrics
? {}
: {
confidenceMetrics: {
structValue: {
list: [
{ confidenceThreshold: 2, falsePositiveRate: 0, recall: 0 },
{ confidenceThreshold: 1, falsePositiveRate: 0, recall: 0.33962264150943394 },
{ confidenceThreshold: 0, falsePositiveRate: 0, recall: 0.6037735849056604 },
{ confidenceThreshold: 0.8, falsePositiveRate: 0, recall: 0.8490566037735849 },
{ confidenceThreshold: 0.6, falsePositiveRate: 0, recall: 0.8867924528301887 },
{ confidenceThreshold: 0.5, falsePositiveRate: 0.0125, recall: 0.9245283018867925 },
{ confidenceThreshold: 0.4, falsePositiveRate: 0.075, recall: 0.9622641509433962 },
{ confidenceThreshold: 0.3, falsePositiveRate: 0.0875, recall: 1 },
{ confidenceThreshold: 0.2, falsePositiveRate: 0.2375, recall: 1 },
{ confidenceThreshold: 0.1, falsePositiveRate: 0.475, recall: 1 },
{ confidenceThreshold: 0, falsePositiveRate: 1, recall: 1 },
],
},
},
displayName: {
stringValue: 'metrics',
},
},
},
displayName: {
stringValue: 'metrics',
},
},
state: 2,
createTimeSinceEpoch: 1711766424068,
lastUpdateTimeSinceEpoch: 1711766424068,
};
});

const mockedMarkdownArtifact: Artifact = {
const mockedMarkdownArtifact = (noMetrics?: boolean): Artifact => ({
id: 16,
typeId: 19,
type: 'system.Markdown',
uri: 's3://aballant-pipelines/metrics-visualization-pipeline/16dbff18-a3d5-4684-90ac-4e6198a9da0f/markdown-visualization/markdown_artifact',
properties: {},
customProperties: {
displayName: { stringValue: 'markdown_artifact' },
},
customProperties: noMetrics
? {}
: {
displayName: { stringValue: 'markdown_artifact' },
},
state: 2,
createTimeSinceEpoch: 1712841455267,
lastUpdateTimeSinceEpoch: 1712841455267,
};
});

export const mockGetArtifactsByContext = (): GrpcResponse => {
export const mockGetArtifactsByContext = (noMetrics?: boolean): GrpcResponse => {
const binary = GetArtifactsByContextResponse.encode({
artifacts: [
mockedScalarMetricArtifact,
mockedConfusionMatrixArtifact,
mockedRocCurveArtifact,
mockedMarkdownArtifact,
mockedScalarMetricArtifact(noMetrics),
mockedConfusionMatrixArtifact(noMetrics),
mockedRocCurveArtifact(noMetrics),
mockedMarkdownArtifact(noMetrics),
],
}).finish();
return createGrpcResponse(binary);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ class RocCurveFilterTableRow extends TableRow {

class CompareRunsRocCurve extends Contextual<HTMLElement> {
findRocCurveEmptyState() {
return this.find().findByTestId('compare-runs-roc-curve-empty-state');
}

findRocCurveTableEmptyState() {
return this.find().findByTestId('no-result-found-title');
}

Expand All @@ -123,13 +127,17 @@ class CompareRunsRocCurve extends Contextual<HTMLElement> {
);
}

findRocCruveSearchBar() {
findRocCurveSearchBar() {
return this.find().findByTestId('roc-curve-search');
}

findRocCurveGraph() {
return this.find().findByTestId('roc-curve-graph');
}

findRocCurveNoMetricsState() {
return this.find().findByTestId('compare-runs-roc-curve-no-data-state');
}
}

class CompareRunsScalarMetrics extends Contextual<HTMLDivElement> {
Expand All @@ -152,6 +160,10 @@ class CompareRunsScalarMetrics extends Contextual<HTMLDivElement> {
findScalarMetricsEmptyState() {
return this.find().findByTestId('compare-runs-scalar-metrics-empty-state');
}

findScalarMetricsNoMetricsState() {
return this.find().findByTestId('compare-runs-scalar-metrics-no-data-state');
}
}

class CompareRunsArtifactSelect extends Contextual<HTMLElement> {
Expand Down Expand Up @@ -188,6 +200,10 @@ class CompareRunsMarkdown extends Contextual<HTMLElement> {
this.find().findByTestId(`compare-runs-markdown-${runId}`),
);
}

findMarkdownNoMetricsState() {
return this.find().findByTestId('compare-runs-markdown-no-data-state');
}
}

class CompareRunsConfusionMatrix extends Contextual<HTMLElement> {
Expand All @@ -206,6 +222,10 @@ class CompareRunsConfusionMatrix extends Contextual<HTMLElement> {
this.find().findByTestId(`compare-runs-confusion-matrix-${runId}`),
);
}

findConfusionMatrixNoMetricsState() {
return this.find().findByTestId('compare-runs-confusion-matrix-no-data-state');
}
}

class ConfusionMatrixGraph extends Contextual<HTMLElement> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@ const mockRun2 = buildMockRunKF({
},
});

const mockRun3 = buildMockRunKF({
display_name: 'Run 3',
run_id: 'run-3',
pipeline_version_reference: {
pipeline_id: initialMockPipeline.pipeline_id,
pipeline_version_id: initialMockPipelineVersion.pipeline_version_id,
},
experiment_id: mockExperiment.experiment_id,
runtime_config: { parameters: {} },
});

describe('Compare runs', () => {
beforeEach(() => {
initIntercepts();
Expand Down Expand Up @@ -204,6 +215,7 @@ describe('Compare runs', () => {
compareRunsGlobal.visit(projectName, mockExperiment.experiment_id, [
mockRun.run_id,
mockRun2.run_id,
mockRun3.run_id,
]);
});

Expand All @@ -213,6 +225,15 @@ describe('Compare runs', () => {
.findScalarMetricsTabContent()
.findScalarMetricsEmptyState()
.should('exist');
compareRunsMetricsContent.findConfusionMatrixTab().click();
compareRunsMetricsContent
.findConfusionMatrixTabContent()
.findConfusionMatrixEmptyState()
.should('exist');
compareRunsMetricsContent.findRocCurveTab().click();
compareRunsMetricsContent.findRocCurveTabContent().findRocCurveEmptyState().should('exist');
compareRunsMetricsContent.findMarkdownTab().click();
compareRunsMetricsContent.findMarkdownTabContent().findMarkdownEmptyState().should('exist');
});

it('displays scalar metrics table data based on selections from Run list', () => {
Expand Down Expand Up @@ -297,13 +318,63 @@ describe('Compare runs', () => {
it('displays ROC curve empty state when no artifacts are found', () => {
compareRunsMetricsContent.findRocCurveTab().click();
const content = compareRunsMetricsContent.findRocCurveTabContent();
content.findRocCruveSearchBar().type('invalid');
content.findRocCurveEmptyState().should('exist');
content.findRocCurveSearchBar().type('invalid');
content.findRocCurveTableEmptyState().should('exist');
});
});

describe('No metrics', () => {
beforeEach(() => {
initIntercepts(true);
compareRunsGlobal.visit(projectName, mockExperiment.experiment_id, [
mockRun.run_id,
mockRun2.run_id,
mockRun3.run_id,
]);
});

it('shows no data state when the Runs list has selections but no metrics', () => {
compareRunsMetricsContent
.findScalarMetricsTabContent()
.findScalarMetricsNoMetricsState()
.should('exist');
compareRunsMetricsContent.findConfusionMatrixTab().click();
compareRunsMetricsContent
.findConfusionMatrixTabContent()
.findConfusionMatrixNoMetricsState()
.should('exist');
compareRunsMetricsContent.findRocCurveTab().click();
compareRunsMetricsContent
.findRocCurveTabContent()
.findRocCurveNoMetricsState()
.should('exist');
compareRunsMetricsContent.findMarkdownTab().click();
compareRunsMetricsContent
.findMarkdownTabContent()
.findMarkdownNoMetricsState()
.should('exist');
});

it('shows empty state when the Runs list has no selections', () => {
compareRunsListTable.findSelectAllCheckbox().click(); // Uncheck all
compareRunsMetricsContent
.findScalarMetricsTabContent()
.findScalarMetricsEmptyState()
.should('exist');
compareRunsMetricsContent.findConfusionMatrixTab().click();
compareRunsMetricsContent
.findConfusionMatrixTabContent()
.findConfusionMatrixEmptyState()
.should('exist');
compareRunsMetricsContent.findRocCurveTab().click();
compareRunsMetricsContent.findRocCurveTabContent().findRocCurveEmptyState().should('exist');
compareRunsMetricsContent.findMarkdownTab().click();
compareRunsMetricsContent.findMarkdownTabContent().findMarkdownEmptyState().should('exist');
});
});
});

const initIntercepts = () => {
const initIntercepts = (noMetrics?: boolean) => {
cy.interceptOdh(
'GET /api/config',
mockDashboardConfig({ disablePipelineExperiments: false, disableS3Endpoint: false }),
Expand Down Expand Up @@ -366,5 +437,13 @@ const initIntercepts = () => {
mockRun2,
);

initMlmdIntercepts(projectName);
cy.interceptOdh(
'GET /api/service/pipelines/:namespace/:serviceName/apis/v2beta1/runs/:runId',
{
path: { namespace: projectName, serviceName: 'dspa', runId: mockRun3.run_id },
},
mockRun3,
);

initMlmdIntercepts(projectName, { noMetrics });
};
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,6 @@ const initIntercepts = (interceptMlmd: boolean, isExecutionsEmpty?: boolean) =>
);

if (interceptMlmd) {
if (isExecutionsEmpty) {
initMlmdIntercepts(projectName, true);
} else {
initMlmdIntercepts(projectName, false);
}
initMlmdIntercepts(projectName, { isExecutionsEmpty });
}
};
Loading

0 comments on commit b81f061

Please sign in to comment.