diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-20 13:49:51 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-02-20 13:49:51 +0000 |
commit | 71786ddc8e28fbd3cb3fcc4b3ff15e5962a1c82e (patch) | |
tree | 6a2d93ef3fb2d353bb7739e4b57e6541f51cdd71 /spec/frontend/ml/experiment_tracking/components | |
parent | a7253423e3403b8c08f8a161e5937e1488f5f407 (diff) | |
download | gitlab-ce-71786ddc8e28fbd3cb3fcc4b3ff15e5962a1c82e.tar.gz |
Add latest changes from gitlab-org/gitlab@15-9-stable-eev15.9.0-rc42
Diffstat (limited to 'spec/frontend/ml/experiment_tracking/components')
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); }); }); }); |