summaryrefslogtreecommitdiff
path: root/spec/frontend/ml/experiment_tracking/components
diff options
context:
space:
mode:
Diffstat (limited to 'spec/frontend/ml/experiment_tracking/components')
-rw-r--r--spec/frontend/ml/experiment_tracking/components/__snapshots__/ml_candidate_spec.js.snap8
-rw-r--r--spec/frontend/ml/experiment_tracking/components/__snapshots__/ml_experiment_spec.js.snap761
-rw-r--r--spec/frontend/ml/experiment_tracking/components/incubation_alert_spec.js27
-rw-r--r--spec/frontend/ml/experiment_tracking/components/ml_candidate_spec.js2
-rw-r--r--spec/frontend/ml/experiment_tracking/components/ml_experiment_spec.js359
5 files changed, 272 insertions, 885 deletions
diff --git a/spec/frontend/ml/experiment_tracking/components/__snapshots__/ml_candidate_spec.js.snap b/spec/frontend/ml/experiment_tracking/components/__snapshots__/ml_candidate_spec.js.snap
index 0c3d3e78038..7d7eee2bc2c 100644
--- a/spec/frontend/ml/experiment_tracking/components/__snapshots__/ml_candidate_spec.js.snap
+++ b/spec/frontend/ml/experiment_tracking/components/__snapshots__/ml_candidate_spec.js.snap
@@ -24,14 +24,14 @@ exports[`MlCandidate renders correctly 1`] = `
<h2
class="gl-alert-title"
>
- Machine Learning Experiment Tracking is in Incubating Phase
+ Machine learning experiment tracking is in incubating phase
</h2>
<div
class="gl-alert-body"
>
- GitLab incubates features to explore new use cases. These features are updated regularly, and support is limited
+ GitLab incubates features to explore new use cases. These features are updated regularly, and support is limited.
<a
class="gl-link"
@@ -39,7 +39,7 @@ exports[`MlCandidate renders correctly 1`] = `
rel="noopener noreferrer"
target="_blank"
>
- Learn more
+ Learn more about incubating features
</a>
</div>
@@ -58,7 +58,7 @@ exports[`MlCandidate renders correctly 1`] = `
class="gl-button-text"
>
- Feedback
+ Give feedback on this feature
</span>
</a>
diff --git a/spec/frontend/ml/experiment_tracking/components/__snapshots__/ml_experiment_spec.js.snap b/spec/frontend/ml/experiment_tracking/components/__snapshots__/ml_experiment_spec.js.snap
deleted file mode 100644
index 3ee2c1cc075..00000000000
--- a/spec/frontend/ml/experiment_tracking/components/__snapshots__/ml_experiment_spec.js.snap
+++ /dev/null
@@ -1,761 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`MlExperiment with candidates renders correctly 1`] = `
-<div>
- <div
- class="gl-alert gl-alert-warning"
- >
- <svg
- aria-hidden="true"
- class="gl-icon s16 gl-alert-icon"
- data-testid="warning-icon"
- role="img"
- >
- <use
- href="#warning"
- />
- </svg>
-
- <div
- aria-live="assertive"
- class="gl-alert-content"
- role="alert"
- >
- <h2
- class="gl-alert-title"
- >
- Machine Learning Experiment Tracking is in Incubating Phase
- </h2>
-
- <div
- class="gl-alert-body"
- >
-
- GitLab incubates features to explore new use cases. These features are updated regularly, and support is limited
-
- <a
- class="gl-link"
- href="https://about.gitlab.com/handbook/engineering/incubation/"
- rel="noopener noreferrer"
- target="_blank"
- >
- Learn more
- </a>
- </div>
-
- <div
- class="gl-alert-actions"
- >
- <a
- class="btn gl-alert-action btn-confirm btn-md gl-button"
- href="https://gitlab.com/gitlab-org/gitlab/-/issues/381660"
- >
- <!---->
-
- <!---->
-
- <span
- class="gl-button-text"
- >
-
- Feedback
-
- </span>
- </a>
- </div>
- </div>
-
- <button
- aria-label="Dismiss"
- class="btn gl-dismiss-btn btn-default btn-sm gl-button btn-default-tertiary btn-icon"
- type="button"
- >
- <!---->
-
- <svg
- aria-hidden="true"
- class="gl-button-icon gl-icon s16"
- data-testid="close-icon"
- role="img"
- >
- <use
- href="#close"
- />
- </svg>
-
- <!---->
- </button>
- </div>
-
- <h3>
-
- Experiment candidates
-
- </h3>
-
- <table
- aria-busy="false"
- aria-colcount="9"
- class="table b-table gl-table gl-mt-0! ml-candidate-table table-sm"
- role="table"
- >
- <!---->
- <!---->
- <thead
- class=""
- role="rowgroup"
- >
- <!---->
- <tr
- class=""
- role="row"
- >
- <th
- aria-colindex="1"
- class=""
- role="columnheader"
- scope="col"
- >
- <div>
- Name
- </div>
- </th>
- <th
- aria-colindex="2"
- class=""
- role="columnheader"
- scope="col"
- >
- <div>
- Created at
- </div>
- </th>
- <th
- aria-colindex="3"
- class=""
- role="columnheader"
- scope="col"
- >
- <div>
- User
- </div>
- </th>
- <th
- aria-colindex="4"
- class=""
- role="columnheader"
- scope="col"
- >
- <div>
- L1 Ratio
- </div>
- </th>
- <th
- aria-colindex="5"
- class=""
- role="columnheader"
- scope="col"
- >
- <div>
- Rmse
- </div>
- </th>
- <th
- aria-colindex="6"
- class=""
- role="columnheader"
- scope="col"
- >
- <div>
- Auc
- </div>
- </th>
- <th
- aria-colindex="7"
- class=""
- role="columnheader"
- scope="col"
- >
- <div>
- Mae
- </div>
- </th>
- <th
- aria-colindex="8"
- aria-label="Details"
- class=""
- role="columnheader"
- scope="col"
- >
- <div />
- </th>
- <th
- aria-colindex="9"
- aria-label="Artifact"
- class=""
- role="columnheader"
- scope="col"
- >
- <div />
- </th>
- </tr>
- </thead>
- <tbody
- role="rowgroup"
- >
- <!---->
- <tr
- class=""
- role="row"
- >
- <td
- aria-colindex="1"
- class=""
- role="cell"
- >
- <div
- title="aCandidate"
- >
- aCandidate
- </div>
- </td>
- <td
- aria-colindex="2"
- class=""
- role="cell"
- >
- <time
- class=""
- datetime="2023-01-05T14:07:02.975Z"
- title="2023-01-05T14:07:02.975Z"
- >
- in 2 years
- </time>
- </td>
- <td
- aria-colindex="3"
- class=""
- role="cell"
- >
- <a
- class="gl-link"
- href="/root"
- title="root"
- >
- @root
- </a>
- </td>
- <td
- aria-colindex="4"
- class=""
- role="cell"
- >
- <div
- title="0.4"
- >
- 0.4
- </div>
- </td>
- <td
- aria-colindex="5"
- class=""
- role="cell"
- >
- <div
- title="1"
- >
- 1
- </div>
- </td>
- <td
- aria-colindex="6"
- class=""
- role="cell"
- >
- <div
- title=""
- >
-
- </div>
- </td>
- <td
- aria-colindex="7"
- class=""
- role="cell"
- >
- <div
- title=""
- >
-
- </div>
- </td>
- <td
- aria-colindex="8"
- class=""
- role="cell"
- >
- <a
- class="gl-link"
- href="link_to_candidate1"
- title="Details"
- >
- Details
- </a>
- </td>
- <td
- aria-colindex="9"
- class=""
- role="cell"
- >
- <a
- class="gl-link"
- href="link_to_artifact"
- rel="noopener"
- target="_blank"
- title="Artifacts"
- >
- Artifacts
- </a>
- </td>
- </tr>
- <tr
- class=""
- role="row"
- >
- <td
- aria-colindex="1"
- class=""
- role="cell"
- >
- <div
- title=""
- >
-
- </div>
- </td>
- <td
- aria-colindex="2"
- class=""
- role="cell"
- >
- <time
- class=""
- datetime="2023-01-05T14:07:02.975Z"
- title="2023-01-05T14:07:02.975Z"
- >
- in 2 years
- </time>
- </td>
- <td
- aria-colindex="3"
- class=""
- role="cell"
- >
- <div>
- -
- </div>
- </td>
- <td
- aria-colindex="4"
- class=""
- role="cell"
- >
- <div
- title="0.5"
- >
- 0.5
- </div>
- </td>
- <td
- aria-colindex="5"
- class=""
- role="cell"
- >
- <div
- title=""
- >
-
- </div>
- </td>
- <td
- aria-colindex="6"
- class=""
- role="cell"
- >
- <div
- title="0.3"
- >
- 0.3
- </div>
- </td>
- <td
- aria-colindex="7"
- class=""
- role="cell"
- >
- <div
- title=""
- >
-
- </div>
- </td>
- <td
- aria-colindex="8"
- class=""
- role="cell"
- >
- <a
- class="gl-link"
- href="link_to_candidate2"
- title="Details"
- >
- Details
- </a>
- </td>
- <td
- aria-colindex="9"
- class=""
- role="cell"
- >
- <div
- title="Artifacts"
- >
-
- -
-
- </div>
- </td>
- </tr>
- <tr
- class=""
- role="row"
- >
- <td
- aria-colindex="1"
- class=""
- role="cell"
- >
- <div
- title=""
- >
-
- </div>
- </td>
- <td
- aria-colindex="2"
- class=""
- role="cell"
- >
- <time
- class=""
- datetime="2023-01-05T14:07:02.975Z"
- title="2023-01-05T14:07:02.975Z"
- >
- in 2 years
- </time>
- </td>
- <td
- aria-colindex="3"
- class=""
- role="cell"
- >
- <div>
- -
- </div>
- </td>
- <td
- aria-colindex="4"
- class=""
- role="cell"
- >
- <div
- title="0.5"
- >
- 0.5
- </div>
- </td>
- <td
- aria-colindex="5"
- class=""
- role="cell"
- >
- <div
- title=""
- >
-
- </div>
- </td>
- <td
- aria-colindex="6"
- class=""
- role="cell"
- >
- <div
- title="0.3"
- >
- 0.3
- </div>
- </td>
- <td
- aria-colindex="7"
- class=""
- role="cell"
- >
- <div
- title=""
- >
-
- </div>
- </td>
- <td
- aria-colindex="8"
- class=""
- role="cell"
- >
- <a
- class="gl-link"
- href="link_to_candidate3"
- title="Details"
- >
- Details
- </a>
- </td>
- <td
- aria-colindex="9"
- class=""
- role="cell"
- >
- <div
- title="Artifacts"
- >
-
- -
-
- </div>
- </td>
- </tr>
- <tr
- class=""
- role="row"
- >
- <td
- aria-colindex="1"
- class=""
- role="cell"
- >
- <div
- title=""
- >
-
- </div>
- </td>
- <td
- aria-colindex="2"
- class=""
- role="cell"
- >
- <time
- class=""
- datetime="2023-01-05T14:07:02.975Z"
- title="2023-01-05T14:07:02.975Z"
- >
- in 2 years
- </time>
- </td>
- <td
- aria-colindex="3"
- class=""
- role="cell"
- >
- <div>
- -
- </div>
- </td>
- <td
- aria-colindex="4"
- class=""
- role="cell"
- >
- <div
- title="0.5"
- >
- 0.5
- </div>
- </td>
- <td
- aria-colindex="5"
- class=""
- role="cell"
- >
- <div
- title=""
- >
-
- </div>
- </td>
- <td
- aria-colindex="6"
- class=""
- role="cell"
- >
- <div
- title="0.3"
- >
- 0.3
- </div>
- </td>
- <td
- aria-colindex="7"
- class=""
- role="cell"
- >
- <div
- title=""
- >
-
- </div>
- </td>
- <td
- aria-colindex="8"
- class=""
- role="cell"
- >
- <a
- class="gl-link"
- href="link_to_candidate4"
- title="Details"
- >
- Details
- </a>
- </td>
- <td
- aria-colindex="9"
- class=""
- role="cell"
- >
- <div
- title="Artifacts"
- >
-
- -
-
- </div>
- </td>
- </tr>
- <tr
- class=""
- role="row"
- >
- <td
- aria-colindex="1"
- class=""
- role="cell"
- >
- <div
- title=""
- >
-
- </div>
- </td>
- <td
- aria-colindex="2"
- class=""
- role="cell"
- >
- <time
- class=""
- datetime="2023-01-05T14:07:02.975Z"
- title="2023-01-05T14:07:02.975Z"
- >
- in 2 years
- </time>
- </td>
- <td
- aria-colindex="3"
- class=""
- role="cell"
- >
- <div>
- -
- </div>
- </td>
- <td
- aria-colindex="4"
- class=""
- role="cell"
- >
- <div
- title="0.5"
- >
- 0.5
- </div>
- </td>
- <td
- aria-colindex="5"
- class=""
- role="cell"
- >
- <div
- title=""
- >
-
- </div>
- </td>
- <td
- aria-colindex="6"
- class=""
- role="cell"
- >
- <div
- title="0.3"
- >
- 0.3
- </div>
- </td>
- <td
- aria-colindex="7"
- class=""
- role="cell"
- >
- <div
- title=""
- >
-
- </div>
- </td>
- <td
- aria-colindex="8"
- class=""
- role="cell"
- >
- <a
- class="gl-link"
- href="link_to_candidate5"
- title="Details"
- >
- Details
- </a>
- </td>
- <td
- aria-colindex="9"
- class=""
- role="cell"
- >
- <div
- title="Artifacts"
- >
-
- -
-
- </div>
- </td>
- </tr>
- <!---->
- <!---->
- </tbody>
- <!---->
- </table>
-
- <!---->
-</div>
-`;
diff --git a/spec/frontend/ml/experiment_tracking/components/incubation_alert_spec.js b/spec/frontend/ml/experiment_tracking/components/incubation_alert_spec.js
deleted file mode 100644
index 7dca360c7ee..00000000000
--- a/spec/frontend/ml/experiment_tracking/components/incubation_alert_spec.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import { mount } from '@vue/test-utils';
-import { GlAlert, GlButton } from '@gitlab/ui';
-import IncubationAlert from '~/ml/experiment_tracking/components/incubation_alert.vue';
-
-describe('IncubationAlert', () => {
- let wrapper;
-
- const findAlert = () => wrapper.findComponent(GlAlert);
-
- const findButton = () => wrapper.findComponent(GlButton);
-
- beforeEach(() => {
- wrapper = mount(IncubationAlert);
- });
-
- it('displays link to issue', () => {
- expect(findButton().attributes().href).toBe(
- 'https://gitlab.com/gitlab-org/gitlab/-/issues/381660',
- );
- });
-
- it('is removed if dismissed', async () => {
- await wrapper.find('[aria-label="Dismiss"]').trigger('click');
-
- expect(findAlert().exists()).toBe(false);
- });
-});
diff --git a/spec/frontend/ml/experiment_tracking/components/ml_candidate_spec.js b/spec/frontend/ml/experiment_tracking/components/ml_candidate_spec.js
index fb45c4b07a4..483e454d7d7 100644
--- a/spec/frontend/ml/experiment_tracking/components/ml_candidate_spec.js
+++ b/spec/frontend/ml/experiment_tracking/components/ml_candidate_spec.js
@@ -28,7 +28,7 @@ describe('MlCandidate', () => {
},
};
- return mountExtended(MlCandidate, { provide: { candidate } });
+ return mountExtended(MlCandidate, { propsData: { candidate } });
};
const findAlert = () => wrapper.findComponent(GlAlert);
diff --git a/spec/frontend/ml/experiment_tracking/components/ml_experiment_spec.js b/spec/frontend/ml/experiment_tracking/components/ml_experiment_spec.js
index abcaf17303f..f307d2c5a58 100644
--- a/spec/frontend/ml/experiment_tracking/components/ml_experiment_spec.js
+++ b/spec/frontend/ml/experiment_tracking/components/ml_experiment_spec.js
@@ -1,140 +1,315 @@
-import { GlAlert, GlPagination } from '@gitlab/ui';
+import { GlAlert, GlTable, GlLink } from '@gitlab/ui';
+import { nextTick } from 'vue';
import { mountExtended } from 'helpers/vue_test_utils_helper';
import MlExperiment from '~/ml/experiment_tracking/components/ml_experiment.vue';
+import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
+import Pagination from '~/vue_shared/components/incubation/pagination.vue';
+import setWindowLocation from 'helpers/set_window_location_helper';
+import * as urlHelpers from '~/lib/utils/url_utility';
describe('MlExperiment', () => {
let wrapper;
+ const startCursor = 'eyJpZCI6IjE2In0';
+ const defaultPageInfo = {
+ startCursor,
+ endCursor: 'eyJpZCI6IjIifQ',
+ hasNextPage: true,
+ hasPreviousPage: true,
+ };
+
const createWrapper = (
candidates = [],
metricNames = [],
paramNames = [],
- pagination = { page: 1, isLastPage: false, per_page: 2, totalItems: 0 },
+ pageInfo = defaultPageInfo,
) => {
- return mountExtended(MlExperiment, {
- provide: { candidates, metricNames, paramNames, pagination },
+ wrapper = mountExtended(MlExperiment, {
+ provide: { candidates, metricNames, paramNames, pageInfo },
});
};
- const findAlert = () => wrapper.findComponent(GlAlert);
+ const candidates = [
+ {
+ rmse: 1,
+ l1_ratio: 0.4,
+ details: 'link_to_candidate1',
+ artifact: 'link_to_artifact',
+ name: 'aCandidate',
+ created_at: '2023-01-05T14:07:02.975Z',
+ user: { username: 'root', path: '/root' },
+ },
+ {
+ auc: 0.3,
+ l1_ratio: 0.5,
+ details: 'link_to_candidate2',
+ created_at: '2023-01-05T14:07:02.975Z',
+ name: null,
+ user: null,
+ },
+ {
+ auc: 0.3,
+ l1_ratio: 0.5,
+ details: 'link_to_candidate3',
+ created_at: '2023-01-05T14:07:02.975Z',
+ name: null,
+ user: null,
+ },
+ {
+ auc: 0.3,
+ l1_ratio: 0.5,
+ details: 'link_to_candidate4',
+ created_at: '2023-01-05T14:07:02.975Z',
+ name: null,
+ user: null,
+ },
+ {
+ auc: 0.3,
+ l1_ratio: 0.5,
+ details: 'link_to_candidate5',
+ created_at: '2023-01-05T14:07:02.975Z',
+ name: null,
+ user: null,
+ },
+ ];
+
+ const createWrapperWithCandidates = (pageInfo = defaultPageInfo) => {
+ createWrapper(candidates, ['rmse', 'auc', 'mae'], ['l1_ratio'], pageInfo);
+ };
- const findEmptyState = () => wrapper.findByText('This experiment has no logged candidates');
+ const findAlert = () => wrapper.findComponent(GlAlert);
+ const findPagination = () => wrapper.findComponent(Pagination);
+ const findEmptyState = () => wrapper.findByText('No candidates to display');
+ const findRegistrySearch = () => wrapper.findComponent(RegistrySearch);
+ const findTable = () => wrapper.findComponent(GlTable);
+ const findTableHeaders = () => findTable().findAll('th');
+ const findTableRows = () => findTable().findAll('tbody > tr');
+ const findNthTableRow = (idx) => findTableRows().at(idx);
+ const findColumnInRow = (row, col) => findNthTableRow(row).findAll('td').at(col);
+ const hrefInRowAndColumn = (row, col) =>
+ findColumnInRow(row, col).findComponent(GlLink).attributes().href;
it('shows incubation warning', () => {
- wrapper = createWrapper();
+ createWrapper();
expect(findAlert().exists()).toBe(true);
});
- describe('no candidates', () => {
- it('shows empty state', () => {
- wrapper = createWrapper();
+ describe('default inputs', () => {
+ beforeEach(async () => {
+ createWrapper();
+ await nextTick();
+ });
+
+ it('shows empty state', () => {
expect(findEmptyState().exists()).toBe(true);
});
it('does not show pagination', () => {
- wrapper = createWrapper();
+ expect(findPagination().exists()).toBe(false);
+ });
- expect(wrapper.findComponent(GlPagination).exists()).toBe(false);
+ it('there are no columns', () => {
+ expect(findTable().findAll('th')).toHaveLength(0);
+ });
+
+ it('initializes sorting correctly', () => {
+ expect(findRegistrySearch().props('sorting')).toMatchObject({
+ orderBy: 'created_at',
+ sort: 'desc',
+ });
+ });
+
+ it('initializes filters correctly', () => {
+ expect(findRegistrySearch().props('filters')).toMatchObject([{ value: { data: '' } }]);
});
});
- describe('with candidates', () => {
- const defaultPagination = { page: 1, isLastPage: false, per_page: 2, totalItems: 5 };
-
- const createWrapperWithCandidates = (pagination = defaultPagination) => {
- return createWrapper(
- [
- {
- rmse: 1,
- l1_ratio: 0.4,
- details: 'link_to_candidate1',
- artifact: 'link_to_artifact',
- name: 'aCandidate',
- created_at: '2023-01-05T14:07:02.975Z',
- user: { username: 'root', path: '/root' },
- },
- {
- auc: 0.3,
- l1_ratio: 0.5,
- details: 'link_to_candidate2',
- created_at: '2023-01-05T14:07:02.975Z',
- name: null,
- user: null,
- },
- {
- auc: 0.3,
- l1_ratio: 0.5,
- details: 'link_to_candidate3',
- created_at: '2023-01-05T14:07:02.975Z',
- name: null,
- user: null,
- },
- {
- auc: 0.3,
- l1_ratio: 0.5,
- details: 'link_to_candidate4',
- created_at: '2023-01-05T14:07:02.975Z',
- name: null,
- user: null,
- },
- {
- auc: 0.3,
- l1_ratio: 0.5,
- details: 'link_to_candidate5',
- created_at: '2023-01-05T14:07:02.975Z',
- name: null,
- user: null,
- },
- ],
- ['rmse', 'auc', 'mae'],
- ['l1_ratio'],
- pagination,
- );
- };
-
- it('renders correctly', () => {
- wrapper = createWrapperWithCandidates();
-
- expect(wrapper.element).toMatchSnapshot();
- });
-
- describe('Pagination behaviour', () => {
- it('should show', () => {
- wrapper = createWrapperWithCandidates();
-
- expect(wrapper.findComponent(GlPagination).exists()).toBe(true);
+ describe('Search', () => {
+ it('shows search box', () => {
+ createWrapper();
+
+ expect(findRegistrySearch().exists()).toBe(true);
+ });
+
+ it('metrics are added as options for sorting', () => {
+ createWrapper([], ['bar']);
+
+ const labels = findRegistrySearch()
+ .props('sortableFields')
+ .map((e) => e.orderBy);
+ expect(labels).toContain('metric.bar');
+ });
+
+ it('sets the component filters based on the querystring', () => {
+ setWindowLocation('https://blah?name=A&orderBy=B&sort=C');
+
+ createWrapper();
+
+ expect(findRegistrySearch().props('filters')).toMatchObject([{ value: { data: 'A' } }]);
+ });
+
+ it('sets the component sort based on the querystring', () => {
+ setWindowLocation('https://blah?name=A&orderBy=B&sort=C');
+
+ createWrapper();
+
+ expect(findRegistrySearch().props('sorting')).toMatchObject({ orderBy: 'B', sort: 'c' });
+ });
+
+ it('sets the component sort based on the querystring, when order by is a metric', () => {
+ setWindowLocation('https://blah?name=A&orderBy=B&sort=C&orderByType=metric');
+
+ createWrapper();
+
+ expect(findRegistrySearch().props('sorting')).toMatchObject({
+ orderBy: 'metric.B',
+ sort: 'c',
+ });
+ });
+
+ describe('Search submit', () => {
+ beforeEach(() => {
+ setWindowLocation('https://blah.com/?name=query&orderBy=name&orderByType=column&sort=asc');
+ jest.spyOn(urlHelpers, 'visitUrl').mockImplementation(() => {});
+
+ createWrapper();
+ });
+
+ it('On submit, resets the cursor and reloads to correct page', () => {
+ findRegistrySearch().vm.$emit('filter:submit');
+
+ expect(urlHelpers.visitUrl).toHaveBeenCalledTimes(1);
+ expect(urlHelpers.visitUrl).toHaveBeenCalledWith(
+ 'https://blah.com/?name=query&orderBy=name&orderByType=column&sort=asc',
+ );
});
- it('should get the page number from the URL', () => {
- wrapper = createWrapperWithCandidates({ ...defaultPagination, page: 2 });
+ it('On sorting changed, resets cursor and reloads to correct page', () => {
+ findRegistrySearch().vm.$emit('sorting:changed', { orderBy: 'created_at' });
- expect(wrapper.findComponent(GlPagination).props().value).toBe(2);
+ expect(urlHelpers.visitUrl).toHaveBeenCalledTimes(1);
+ expect(urlHelpers.visitUrl).toHaveBeenCalledWith(
+ 'https://blah.com/?name=query&orderBy=created_at&orderByType=column&sort=asc',
+ );
});
- it('should not have a prevPage if the page is 1', () => {
- wrapper = createWrapperWithCandidates();
+ it('On sorting changed and is metric, resets cursor and reloads to correct page', () => {
+ findRegistrySearch().vm.$emit('sorting:changed', { orderBy: 'metric.auc' });
- expect(wrapper.findComponent(GlPagination).props().prevPage).toBe(null);
+ expect(urlHelpers.visitUrl).toHaveBeenCalledTimes(1);
+ expect(urlHelpers.visitUrl).toHaveBeenCalledWith(
+ 'https://blah.com/?name=query&orderBy=auc&orderByType=metric&sort=asc',
+ );
});
- it('should set the prevPage to 1 if the page is 2', () => {
- wrapper = createWrapperWithCandidates({ ...defaultPagination, page: 2 });
+ it('On direction changed, reloads to correct page', () => {
+ findRegistrySearch().vm.$emit('sorting:changed', { sort: 'desc' });
- expect(wrapper.findComponent(GlPagination).props().prevPage).toBe(1);
+ expect(urlHelpers.visitUrl).toHaveBeenCalledTimes(1);
+ expect(urlHelpers.visitUrl).toHaveBeenCalledWith(
+ 'https://blah.com/?name=query&orderBy=name&orderByType=column&sort=desc',
+ );
});
+ });
+ });
+
+ describe('Pagination behaviour', () => {
+ beforeEach(() => {
+ createWrapperWithCandidates();
+ });
+
+ it('should show', () => {
+ expect(findPagination().exists()).toBe(true);
+ });
- it('should not have a nextPage if isLastPage is true', async () => {
- wrapper = createWrapperWithCandidates({ ...defaultPagination, isLastPage: true });
+ it('Passes pagination to pagination component', () => {
+ createWrapperWithCandidates();
+
+ expect(findPagination().props('startCursor')).toBe(startCursor);
+ });
+ });
+
+ describe('Candidate table', () => {
+ const firstCandidateIndex = 0;
+ const secondCandidateIndex = 1;
+ const firstCandidate = candidates[firstCandidateIndex];
+
+ beforeEach(() => {
+ createWrapperWithCandidates();
+ });
+
+ it('renders all rows', () => {
+ expect(findTableRows()).toHaveLength(candidates.length);
+ });
+
+ it('sets the correct columns in the table', () => {
+ const expectedColumnNames = [
+ 'Name',
+ 'Created at',
+ 'User',
+ 'L1 Ratio',
+ 'Rmse',
+ 'Auc',
+ 'Mae',
+ '',
+ '',
+ ];
+
+ expect(findTableHeaders().wrappers.map((h) => h.text())).toEqual(expectedColumnNames);
+ });
- expect(wrapper.findComponent(GlPagination).props().nextPage).toBe(null);
+ describe('Artifact column', () => {
+ const artifactColumnIndex = -1;
+
+ it('shows the a link to the artifact', () => {
+ expect(hrefInRowAndColumn(firstCandidateIndex, artifactColumnIndex)).toBe(
+ firstCandidate.artifact,
+ );
+ });
+
+ it('shows empty state when no artifact', () => {
+ expect(findColumnInRow(secondCandidateIndex, artifactColumnIndex).text()).toBe('-');
+ });
+ });
+
+ describe('User column', () => {
+ const userColumn = 2;
+
+ it('creates a link to the user', () => {
+ const column = findColumnInRow(firstCandidateIndex, userColumn).findComponent(GlLink);
+
+ expect(column.attributes().href).toBe(firstCandidate.user.path);
+ expect(column.text()).toBe(`@${firstCandidate.user.username}`);
+ });
+
+ it('when there is no user shows empty state', () => {
+ createWrapperWithCandidates();
+
+ expect(findColumnInRow(secondCandidateIndex, userColumn).text()).toBe('-');
});
+ });
+
+ describe('Candidate name column', () => {
+ const nameColumnIndex = 0;
+
+ it('Sets the name', () => {
+ expect(findColumnInRow(firstCandidateIndex, nameColumnIndex).text()).toBe(
+ firstCandidate.name,
+ );
+ });
+
+ it('when there is no user shows nothing', () => {
+ expect(findColumnInRow(secondCandidateIndex, nameColumnIndex).text()).toBe('');
+ });
+ });
- it('should set the nextPage to 2 if the page is 1', () => {
- wrapper = createWrapperWithCandidates();
+ describe('Detail column', () => {
+ const detailColumn = -2;
- expect(wrapper.findComponent(GlPagination).props().nextPage).toBe(2);
+ it('is a link to details', () => {
+ expect(hrefInRowAndColumn(firstCandidateIndex, detailColumn)).toBe(firstCandidate.details);
});
});
});