diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-15 15:07:19 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-15 15:07:19 +0300 |
commit | e6fed37d941271b897d37820fd3b571feab280b0 (patch) | |
tree | c81c9a7d38d6a8b0c1dc5f8ebb784fce68acb288 /spec/frontend | |
parent | 45a8c43afe8a17de19a92708b380b29b6ae04ce6 (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec/frontend')
7 files changed, 138 insertions, 153 deletions
diff --git a/spec/frontend/boards/components/sidebar/board_sidebar_title_spec.js b/spec/frontend/boards/components/sidebar/board_sidebar_title_spec.js index fae3b0c5d1a..1b526e6fbec 100644 --- a/spec/frontend/boards/components/sidebar/board_sidebar_title_spec.js +++ b/spec/frontend/boards/components/sidebar/board_sidebar_title_spec.js @@ -1,9 +1,9 @@ import { GlAlert, GlFormInput, GlForm, GlLink } from '@gitlab/ui'; -import { shallowMount } from '@vue/test-utils'; import Vue, { nextTick } from 'vue'; import VueApollo from 'vue-apollo'; import createMockApollo from 'helpers/mock_apollo_helper'; import waitForPromises from 'helpers/wait_for_promises'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; import BoardEditableItem from '~/boards/components/sidebar/board_editable_item.vue'; import BoardSidebarTitle from '~/boards/components/sidebar/board_sidebar_title.vue'; import { createStore } from '~/boards/stores'; @@ -32,6 +32,7 @@ const TEST_ISSUE_B = { describe('BoardSidebarTitle', () => { let wrapper; let store; + let storeDispatch; let mockApollo; const issueSetTitleMutationHandlerSuccess = jest.fn().mockResolvedValue(updateIssueTitleResponse); @@ -52,8 +53,9 @@ describe('BoardSidebarTitle', () => { [issueSetTitleMutation, issueSetTitleMutationHandlerSuccess], [updateEpicTitleMutation, updateEpicTitleMutationHandlerSuccess], ]); + storeDispatch = jest.spyOn(store, 'dispatch'); - wrapper = shallowMount(BoardSidebarTitle, { + wrapper = shallowMountExtended(BoardSidebarTitle, { store, apolloProvider: mockApollo, provide: { @@ -78,9 +80,9 @@ describe('BoardSidebarTitle', () => { const findFormInput = () => wrapper.findComponent(GlFormInput); const findGlLink = () => wrapper.findComponent(GlLink); const findEditableItem = () => wrapper.findComponent(BoardEditableItem); - const findCancelButton = () => wrapper.find('[data-testid="cancel-button"]'); - const findTitle = () => wrapper.find('[data-testid="item-title"]'); - const findCollapsed = () => wrapper.find('[data-testid="collapsed-content"]'); + const findCancelButton = () => wrapper.findByTestId('cancel-button'); + const findTitle = () => wrapper.findByTestId('item-title'); + const findCollapsed = () => wrapper.findByTestId('collapsed-content'); it('renders title and reference', () => { createWrapper(); @@ -105,9 +107,6 @@ describe('BoardSidebarTitle', () => { beforeEach(async () => { createWrapper(); - jest.spyOn(wrapper.vm, 'setActiveItemTitle').mockImplementation(() => { - store.state.boardItems[TEST_ISSUE_A.id].title = TEST_TITLE; - }); findFormInput().vm.$emit('input', TEST_TITLE); findForm().vm.$emit('submit', { preventDefault: () => {} }); await nextTick(); @@ -116,29 +115,34 @@ describe('BoardSidebarTitle', () => { it('collapses sidebar and renders new title', async () => { await waitForPromises(); expect(findCollapsed().isVisible()).toBe(true); - expect(findTitle().text()).toContain(TEST_TITLE); }); it('commits change to the server', () => { - expect(wrapper.vm.setActiveItemTitle).toHaveBeenCalledWith({ - title: TEST_TITLE, + expect(storeDispatch).toHaveBeenCalledWith('setActiveItemTitle', { projectPath: 'h/b', + title: 'New item title', }); }); + + it('renders correct title', async () => { + createWrapper({ item: { ...TEST_ISSUE_A, title: TEST_TITLE } }); + await waitForPromises(); + + expect(findTitle().text()).toContain(TEST_TITLE); + }); }); describe('when submitting and invalid title', () => { beforeEach(async () => { createWrapper(); - jest.spyOn(wrapper.vm, 'setActiveItemTitle').mockImplementation(() => {}); findFormInput().vm.$emit('input', ''); findForm().vm.$emit('submit', { preventDefault: () => {} }); await nextTick(); }); it('commits change to the server', () => { - expect(wrapper.vm.setActiveItemTitle).not.toHaveBeenCalled(); + expect(storeDispatch).not.toHaveBeenCalled(); }); }); @@ -169,7 +173,7 @@ describe('BoardSidebarTitle', () => { }); it('sets title, expands item and shows alert', () => { - expect(wrapper.vm.title).toBe(TEST_TITLE); + expect(findFormInput().attributes('value')).toBe(TEST_TITLE); expect(findCollapsed().isVisible()).toBe(false); expect(findAlert().exists()).toBe(true); }); @@ -179,16 +183,13 @@ describe('BoardSidebarTitle', () => { beforeEach(async () => { createWrapper({ item: TEST_ISSUE_B }); - jest.spyOn(wrapper.vm, 'setActiveItemTitle').mockImplementation(() => { - store.state.boardItems[TEST_ISSUE_B.id].title = TEST_TITLE; - }); findFormInput().vm.$emit('input', TEST_TITLE); findCancelButton().vm.$emit('click'); await nextTick(); }); it('collapses sidebar and render former title', () => { - expect(wrapper.vm.setActiveItemTitle).not.toHaveBeenCalled(); + expect(storeDispatch).not.toHaveBeenCalled(); expect(findCollapsed().isVisible()).toBe(true); expect(findTitle().text()).toBe(TEST_ISSUE_B.title); }); @@ -198,10 +199,6 @@ describe('BoardSidebarTitle', () => { beforeEach(async () => { createWrapper({ item: TEST_ISSUE_B }); - jest.spyOn(wrapper.vm, 'setActiveItemTitle').mockImplementation(() => { - throw new Error(['failed mutation']); - }); - jest.spyOn(wrapper.vm, 'setError').mockImplementation(() => {}); findFormInput().vm.$emit('input', 'Invalid title'); findForm().vm.$emit('submit', { preventDefault: () => {} }); await nextTick(); @@ -210,7 +207,10 @@ describe('BoardSidebarTitle', () => { it('collapses sidebar and renders former item title', () => { expect(findCollapsed().isVisible()).toBe(true); expect(findTitle().text()).toContain(TEST_ISSUE_B.title); - expect(wrapper.vm.setError).toHaveBeenCalled(); + expect(storeDispatch).toHaveBeenCalledWith( + 'setError', + expect.objectContaining({ message: 'An error occurred when updating the title' }), + ); }); }); diff --git a/spec/frontend/google_cloud/aiml/panel_spec.js b/spec/frontend/google_cloud/aiml/panel_spec.js new file mode 100644 index 00000000000..374e125c509 --- /dev/null +++ b/spec/frontend/google_cloud/aiml/panel_spec.js @@ -0,0 +1,43 @@ +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import Panel from '~/google_cloud/aiml/panel.vue'; +import IncubationBanner from '~/google_cloud/components/incubation_banner.vue'; +import GoogleCloudMenu from '~/google_cloud/components/google_cloud_menu.vue'; +import ServiceTable from '~/google_cloud/aiml/service_table.vue'; + +describe('google_cloud/databases/panel', () => { + let wrapper; + + const props = { + configurationUrl: 'configuration-url', + deploymentsUrl: 'deployments-url', + databasesUrl: 'databases-url', + aimlUrl: 'aiml-url', + visionAiUrl: 'vision-ai-url', + translationAiUrl: 'translation-ai-url', + languageAiUrl: 'language-ai-url', + }; + + beforeEach(() => { + wrapper = shallowMountExtended(Panel, { propsData: props }); + }); + + it('contains incubation banner', () => { + const target = wrapper.findComponent(IncubationBanner); + expect(target.exists()).toBe(true); + }); + + it('contains google cloud menu with `aiml` active', () => { + const target = wrapper.findComponent(GoogleCloudMenu); + expect(target.exists()).toBe(true); + expect(target.props('active')).toBe('aiml'); + expect(target.props('configurationUrl')).toBe(props.configurationUrl); + expect(target.props('deploymentsUrl')).toBe(props.deploymentsUrl); + expect(target.props('databasesUrl')).toBe(props.databasesUrl); + expect(target.props('aimlUrl')).toBe(props.aimlUrl); + }); + + it('contains service table', () => { + const target = wrapper.findComponent(ServiceTable); + expect(target.exists()).toBe(true); + }); +}); diff --git a/spec/frontend/google_cloud/components/google_cloud_menu_spec.js b/spec/frontend/google_cloud/components/google_cloud_menu_spec.js index a0c988830ed..f1ee96ff870 100644 --- a/spec/frontend/google_cloud/components/google_cloud_menu_spec.js +++ b/spec/frontend/google_cloud/components/google_cloud_menu_spec.js @@ -9,6 +9,7 @@ describe('google_cloud/components/google_cloud_menu', () => { configurationUrl: 'configuration-url', deploymentsUrl: 'deployments-url', databasesUrl: 'databases-url', + aimlUrl: 'aiml-url', }; beforeEach(() => { @@ -33,4 +34,10 @@ describe('google_cloud/components/google_cloud_menu', () => { expect(link.text()).toBe(GoogleCloudMenu.i18n.databases.title); expect(link.attributes('href')).toBe(props.databasesUrl); }); + + it('contains ai/ml link', () => { + const link = wrapper.findByTestId('aimlLink'); + expect(link.text()).toBe(GoogleCloudMenu.i18n.aiml.title); + expect(link.attributes('href')).toBe(props.aimlUrl); + }); }); diff --git a/spec/frontend/lib/utils/sticky_spec.js b/spec/frontend/lib/utils/sticky_spec.js deleted file mode 100644 index ec9e746c838..00000000000 --- a/spec/frontend/lib/utils/sticky_spec.js +++ /dev/null @@ -1,77 +0,0 @@ -import { setHTMLFixture } from 'helpers/fixtures'; -import { isSticky } from '~/lib/utils/sticky'; - -const TEST_OFFSET_TOP = 500; - -describe('sticky', () => { - let el; - let offsetTop; - - beforeEach(() => { - setHTMLFixture( - ` - <div class="parent"> - <div id="js-sticky"></div> - </div> - `, - ); - - offsetTop = TEST_OFFSET_TOP; - el = document.getElementById('js-sticky'); - Object.defineProperty(el, 'offsetTop', { - get() { - return offsetTop; - }, - }); - }); - - afterEach(() => { - el = null; - }); - - describe('when stuck', () => { - it('does not remove is-stuck class', () => { - isSticky(el, 0, el.offsetTop); - isSticky(el, 0, el.offsetTop); - - expect(el.classList.contains('is-stuck')).toBe(true); - }); - - it('adds is-stuck class', () => { - isSticky(el, 0, el.offsetTop); - - expect(el.classList.contains('is-stuck')).toBe(true); - }); - - it('inserts placeholder element', () => { - isSticky(el, 0, el.offsetTop, true); - - expect(document.querySelector('.sticky-placeholder')).not.toBeNull(); - }); - }); - - describe('when not stuck', () => { - it('removes is-stuck class', () => { - jest.spyOn(el.classList, 'remove'); - - isSticky(el, 0, el.offsetTop); - isSticky(el, 0, 0); - - expect(el.classList.remove).toHaveBeenCalledWith('is-stuck'); - expect(el.classList.contains('is-stuck')).toBe(false); - }); - - it('does not add is-stuck class', () => { - isSticky(el, 0, 0); - - expect(el.classList.contains('is-stuck')).toBe(false); - }); - - it('removes placeholder', () => { - isSticky(el, 0, el.offsetTop, true); - isSticky(el, 0, 0, true); - - expect(document.querySelector('.sticky-placeholder')).toBeNull(); - }); - }); -}); diff --git a/spec/frontend/notes/components/noteable_note_spec.js b/spec/frontend/notes/components/noteable_note_spec.js index 1e7470ace8e..5d81a7a9a0f 100644 --- a/spec/frontend/notes/components/noteable_note_spec.js +++ b/spec/frontend/notes/components/noteable_note_spec.js @@ -1,7 +1,7 @@ -import { mount } from '@vue/test-utils'; import Vue, { nextTick } from 'vue'; import Vuex from 'vuex'; import { GlAvatar } from '@gitlab/ui'; +import { mountExtended } from 'helpers/vue_test_utils_helper'; import waitForPromises from 'helpers/wait_for_promises'; import DiffsModule from '~/diffs/store/modules'; import NoteActions from '~/notes/components/note_actions.vue'; @@ -37,7 +37,9 @@ describe('issue_note', () => { const REPORT_ABUSE_PATH = '/abuse_reports/add_category'; - const findMultilineComment = () => wrapper.find('[data-testid="multiline-comment"]'); + const findNoteBody = () => wrapper.findComponent(NoteBody); + + const findMultilineComment = () => wrapper.findByTestId('multiline-comment'); const createWrapper = (props = {}, storeUpdater = (s) => s) => { store = new Vuex.Store( @@ -52,7 +54,7 @@ describe('issue_note', () => { store.dispatch('setNoteableData', noteableDataMock); store.dispatch('setNotesData', notesDataMock); - wrapper = mount(issueNote, { + wrapper = mountExtended(issueNote, { store, propsData: { note, @@ -250,21 +252,17 @@ describe('issue_note', () => { }); it('should render issue body', () => { - const noteBody = wrapper.findComponent(NoteBody); - const noteBodyProps = noteBody.props(); - - expect(noteBodyProps.note).toBe(note); - expect(noteBodyProps.line).toBe(null); - expect(noteBodyProps.canEdit).toBe(note.current_user.can_edit); - expect(noteBodyProps.isEditing).toBe(false); - expect(noteBodyProps.helpPagePath).toBe(''); + expect(findNoteBody().props().note).toBe(note); + expect(findNoteBody().props().line).toBe(null); + expect(findNoteBody().props().canEdit).toBe(note.current_user.can_edit); + expect(findNoteBody().props().isEditing).toBe(false); + expect(findNoteBody().props().helpPagePath).toBe(''); }); it('prevents note preview xss', async () => { const noteBody = '<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" onload="alert(1)" />'; const alertSpy = jest.spyOn(window, 'alert').mockImplementation(() => {}); - const noteBodyComponent = wrapper.findComponent(NoteBody); store.hotUpdate({ modules: { @@ -277,7 +275,7 @@ describe('issue_note', () => { }, }); - noteBodyComponent.vm.$emit('handleFormUpdate', { + findNoteBody().vm.$emit('handleFormUpdate', { noteText: noteBody, parentElement: null, callback: () => {}, @@ -285,7 +283,7 @@ describe('issue_note', () => { await waitForPromises(); expect(alertSpy).not.toHaveBeenCalled(); - expect(wrapper.vm.note.note_html).toBe( + expect(findNoteBody().props().note.note_html).toBe( '<img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">', ); }); @@ -321,26 +319,21 @@ describe('issue_note', () => { }, }, }); - const noteBody = wrapper.findComponent(NoteBody); - noteBody.vm.resetAutoSave = () => {}; - noteBody.vm.$emit('handleFormUpdate', { + findNoteBody().vm.$emit('handleFormUpdate', { noteText: updatedText, parentElement: null, callback: () => {}, }); await nextTick(); - let noteBodyProps = noteBody.props(); - expect(noteBodyProps.note.note_html).toBe(`<p dir="auto">${updatedText}</p>\n`); + expect(findNoteBody().props().note.note_html).toBe(`<p dir="auto">${updatedText}</p>\n`); - noteBody.vm.$emit('cancelForm', {}); + findNoteBody().vm.$emit('cancelForm', {}); await nextTick(); - noteBodyProps = noteBody.props(); - - expect(noteBodyProps.note.note_html).toBe(note.note_html); + expect(findNoteBody().props().note.note_html).toBe(note.note_html); }); }); @@ -371,7 +364,7 @@ describe('issue_note', () => { it('responds to handleFormUpdate', () => { createWrapper(); updateActions(); - wrapper.findComponent(NoteBody).vm.$emit('handleFormUpdate', params); + findNoteBody().vm.$emit('handleFormUpdate', params); expect(wrapper.emitted('handleUpdateNote')).toHaveLength(1); }); @@ -380,16 +373,14 @@ describe('issue_note', () => { createWrapper(); updateActions(); - wrapper - .findComponent(NoteBody) - .vm.$emit('handleFormUpdate', { ...params, noteText: sensitiveMessage }); + findNoteBody().vm.$emit('handleFormUpdate', { ...params, noteText: sensitiveMessage }); expect(updateNote).not.toHaveBeenCalled(); }); it('does not stringify empty position', () => { createWrapper(); updateActions(); - wrapper.findComponent(NoteBody).vm.$emit('handleFormUpdate', params); + findNoteBody().vm.$emit('handleFormUpdate', params); expect(updateNote.mock.calls[0][1].note.note.position).toBeUndefined(); }); @@ -398,7 +389,7 @@ describe('issue_note', () => { const expectation = JSON.stringify(position); createWrapper({ note: { ...note, position } }); updateActions(); - wrapper.findComponent(NoteBody).vm.$emit('handleFormUpdate', params); + findNoteBody().vm.$emit('handleFormUpdate', params); expect(updateNote.mock.calls[0][1].note.note.position).toBe(expectation); }); }); @@ -423,7 +414,7 @@ describe('issue_note', () => { createWrapper({ note: noteDef, discussionFile: null }, storeUpdater); - expect(wrapper.vm.diffFile).toBe(null); + expect(findNoteBody().props().file).toBe(null); }, ); @@ -441,7 +432,7 @@ describe('issue_note', () => { }, ); - expect(wrapper.vm.diffFile.testId).toBe('diffFileTest'); + expect(findNoteBody().props().file.testId).toBe('diffFileTest'); }); it('returns the provided diff file if the more robust getters fail', () => { @@ -457,7 +448,7 @@ describe('issue_note', () => { }, ); - expect(wrapper.vm.diffFile.testId).toBe('diffFileTest'); + expect(findNoteBody().props().file.testId).toBe('diffFileTest'); }); }); }); diff --git a/spec/frontend/vue_shared/components/diff_stats_dropdown_spec.js b/spec/frontend/vue_shared/components/diff_stats_dropdown_spec.js index 930d2fc8cfe..2a4037d76b7 100644 --- a/spec/frontend/vue_shared/components/diff_stats_dropdown_spec.js +++ b/spec/frontend/vue_shared/components/diff_stats_dropdown_spec.js @@ -58,7 +58,6 @@ describe('Diff Stats Dropdown', () => { const findChangedFiles = () => findChanged().findAllComponents(GlDropdownItem); const findNoFilesText = () => findChanged().findComponent(GlDropdownText); const findCollapsed = () => wrapper.findByTestId('diff-stats-additions-deletions-expanded'); - const findExpanded = () => wrapper.findByTestId('diff-stats-additions-deletions-collapsed'); const findSearchBox = () => wrapper.findComponent(GlSearchBoxByType); describe('file item', () => { @@ -88,24 +87,17 @@ describe('Diff Stats Dropdown', () => { }); describe.each` - changed | added | deleted | expectedDropdownHeader | expectedAddedDeletedExpanded | expectedAddedDeletedCollapsed - ${0} | ${0} | ${0} | ${'0 changed files'} | ${'+0 -0'} | ${'with 0 additions and 0 deletions'} - ${2} | ${0} | ${2} | ${'2 changed files'} | ${'+0 -2'} | ${'with 0 additions and 2 deletions'} - ${2} | ${2} | ${0} | ${'2 changed files'} | ${'+2 -0'} | ${'with 2 additions and 0 deletions'} - ${2} | ${1} | ${1} | ${'2 changed files'} | ${'+1 -1'} | ${'with 1 addition and 1 deletion'} - ${1} | ${0} | ${1} | ${'1 changed file'} | ${'+0 -1'} | ${'with 0 additions and 1 deletion'} - ${1} | ${1} | ${0} | ${'1 changed file'} | ${'+1 -0'} | ${'with 1 addition and 0 deletions'} - ${4} | ${2} | ${2} | ${'4 changed files'} | ${'+2 -2'} | ${'with 2 additions and 2 deletions'} + changed | added | deleted | expectedDropdownHeader | expectedAddedDeletedCollapsed + ${0} | ${0} | ${0} | ${'0 changed files'} | ${'with 0 additions and 0 deletions'} + ${2} | ${0} | ${2} | ${'2 changed files'} | ${'with 0 additions and 2 deletions'} + ${2} | ${2} | ${0} | ${'2 changed files'} | ${'with 2 additions and 0 deletions'} + ${2} | ${1} | ${1} | ${'2 changed files'} | ${'with 1 addition and 1 deletion'} + ${1} | ${0} | ${1} | ${'1 changed file'} | ${'with 0 additions and 1 deletion'} + ${1} | ${1} | ${0} | ${'1 changed file'} | ${'with 1 addition and 0 deletions'} + ${4} | ${2} | ${2} | ${'4 changed files'} | ${'with 2 additions and 2 deletions'} `( 'when there are $changed changed file(s), $added added and $deleted deleted file(s)', - ({ - changed, - added, - deleted, - expectedDropdownHeader, - expectedAddedDeletedExpanded, - expectedAddedDeletedCollapsed, - }) => { + ({ changed, added, deleted, expectedDropdownHeader, expectedAddedDeletedCollapsed }) => { beforeEach(() => { createComponent({ changed, added, deleted }); }); @@ -114,10 +106,6 @@ describe('Diff Stats Dropdown', () => { expect(findChanged().props('text')).toBe(expectedDropdownHeader); }); - it(`added and deleted count in expanded section should be '${expectedAddedDeletedExpanded}'`, () => { - expect(findExpanded().text()).toBe(expectedAddedDeletedExpanded); - }); - it(`added and deleted count in collapsed section should be '${expectedAddedDeletedCollapsed}'`, () => { expect(findCollapsed().text()).toBe(expectedAddedDeletedCollapsed); }); diff --git a/spec/frontend/vue_shared/components/projects_list/projects_list_item_spec.js b/spec/frontend/vue_shared/components/projects_list/projects_list_item_spec.js index dc67097d763..3e4d5c558f6 100644 --- a/spec/frontend/vue_shared/components/projects_list/projects_list_item_spec.js +++ b/spec/frontend/vue_shared/components/projects_list/projects_list_item_spec.js @@ -12,6 +12,7 @@ import { import UserAccessRoleBadge from '~/vue_shared/components/user_access_role_badge.vue'; import { ACCESS_LEVEL_LABELS } from '~/access_level/constants'; import { FEATURABLE_DISABLED, FEATURABLE_ENABLED } from '~/featurable/constants'; +import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue'; jest.mock('lodash/uniqueId', () => (prefix) => `${prefix}1`); @@ -36,6 +37,7 @@ describe('ProjectsListItem', () => { const findForksLink = () => wrapper.findByRole('link', { name: ProjectsListItem.i18n.forks }); const findProjectTopics = () => wrapper.findByTestId('project-topics'); const findPopover = () => findProjectTopics().findComponent(GlPopover); + const findProjectDescription = () => wrapper.findByTestId('project-description'); it('renders project avatar', () => { createComponent(); @@ -105,6 +107,12 @@ describe('ProjectsListItem', () => { expect(starsLink.findComponent(GlIcon).props('name')).toBe('star-o'); }); + it('renders updated at', () => { + createComponent(); + + expect(wrapper.findComponent(TimeAgoTooltip).props('time')).toBe(project.updatedAt); + }); + describe('when issues are enabled', () => { it('renders issues count', () => { createComponent(); @@ -230,4 +238,29 @@ describe('ProjectsListItem', () => { }); }); }); + + describe('when project has a description', () => { + it('renders description', () => { + const descriptionHtml = '<p>Foo bar</p>'; + + createComponent({ + propsData: { + project: { + ...project, + descriptionHtml, + }, + }, + }); + + expect(findProjectDescription().element.innerHTML).toBe(descriptionHtml); + }); + }); + + describe('when project does not have a description', () => { + it('does not render description', () => { + createComponent(); + + expect(findProjectDescription().exists()).toBe(false); + }); + }); }); |