diff options
Diffstat (limited to 'spec/frontend/vue_shared/components/awards_list_spec.js')
-rw-r--r-- | spec/frontend/vue_shared/components/awards_list_spec.js | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/spec/frontend/vue_shared/components/awards_list_spec.js b/spec/frontend/vue_shared/components/awards_list_spec.js new file mode 100644 index 00000000000..bb3e60ab9e2 --- /dev/null +++ b/spec/frontend/vue_shared/components/awards_list_spec.js @@ -0,0 +1,213 @@ +import { shallowMount } from '@vue/test-utils'; +import AwardsList from '~/vue_shared/components/awards_list.vue'; + +const createUser = (id, name) => ({ id, name }); +const createAward = (name, user) => ({ name, user }); + +const USERS = { + root: createUser(1, 'Root'), + ada: createUser(2, 'Ada'), + marie: createUser(3, 'Marie'), + jane: createUser(4, 'Jane'), + leonardo: createUser(5, 'Leonardo'), +}; + +const EMOJI_SMILE = 'smile'; +const EMOJI_OK = 'ok_hand'; +const EMOJI_THUMBSUP = 'thumbsup'; +const EMOJI_THUMBSDOWN = 'thumbsdown'; +const EMOJI_A = 'a'; +const EMOJI_B = 'b'; +const EMOJI_CACTUS = 'cactus'; +const EMOJI_100 = '100'; + +const TEST_AWARDS = [ + createAward(EMOJI_SMILE, USERS.ada), + createAward(EMOJI_OK, USERS.ada), + createAward(EMOJI_THUMBSUP, USERS.ada), + createAward(EMOJI_THUMBSDOWN, USERS.ada), + createAward(EMOJI_SMILE, USERS.jane), + createAward(EMOJI_OK, USERS.jane), + createAward(EMOJI_OK, USERS.leonardo), + createAward(EMOJI_THUMBSUP, USERS.leonardo), + createAward(EMOJI_THUMBSUP, USERS.marie), + createAward(EMOJI_THUMBSDOWN, USERS.marie), + createAward(EMOJI_THUMBSDOWN, USERS.root), + createAward(EMOJI_OK, USERS.root), + // Test that emoji list preserves order of occurrence, not alphabetical order + createAward(EMOJI_CACTUS, USERS.root), + createAward(EMOJI_A, USERS.marie), + createAward(EMOJI_B, USERS.root), +]; +const TEST_ADD_BUTTON_CLASS = 'js-test-add-button-class'; + +describe('vue_shared/components/awards_list', () => { + let wrapper; + + afterEach(() => { + wrapper.destroy(); + wrapper = null; + }); + + const createComponent = (props = {}) => { + if (wrapper) { + throw new Error('There should only be one wrapper created per test'); + } + + wrapper = shallowMount(AwardsList, { propsData: props }); + }; + const matchingEmojiTag = name => expect.stringMatching(`gl-emoji data-name="${name}"`); + const findAwardButtons = () => wrapper.findAll('[data-testid="award-button"'); + const findAwardsData = () => + findAwardButtons().wrappers.map(x => { + return { + classes: x.classes(), + title: x.attributes('data-original-title'), + html: x.find('[data-testid="award-html"]').element.innerHTML, + count: Number(x.find('.js-counter').text()), + }; + }); + const findAddAwardButton = () => wrapper.find('.js-add-award'); + + describe('default', () => { + beforeEach(() => { + createComponent({ + awards: TEST_AWARDS, + canAwardEmoji: true, + currentUserId: USERS.root.id, + addButtonClass: TEST_ADD_BUTTON_CLASS, + }); + }); + + it('matches snapshot', () => { + expect(wrapper.element).toMatchSnapshot(); + }); + + it('shows awards in correct order', () => { + expect(findAwardsData()).toEqual([ + { + classes: ['btn', 'award-control'], + count: 3, + html: matchingEmojiTag(EMOJI_THUMBSUP), + title: 'Ada, Leonardo, and Marie', + }, + { + classes: ['btn', 'award-control', 'active'], + count: 3, + html: matchingEmojiTag(EMOJI_THUMBSDOWN), + title: 'You, Ada, and Marie', + }, + { + classes: ['btn', 'award-control'], + count: 2, + html: matchingEmojiTag(EMOJI_SMILE), + title: 'Ada and Jane', + }, + { + classes: ['btn', 'award-control', 'active'], + count: 4, + html: matchingEmojiTag(EMOJI_OK), + title: 'You, Ada, Jane, and Leonardo', + }, + { + classes: ['btn', 'award-control', 'active'], + count: 1, + html: matchingEmojiTag(EMOJI_CACTUS), + title: 'You', + }, + { + classes: ['btn', 'award-control'], + count: 1, + html: matchingEmojiTag(EMOJI_A), + title: 'Marie', + }, + { + classes: ['btn', 'award-control', 'active'], + count: 1, + html: matchingEmojiTag(EMOJI_B), + title: 'You', + }, + ]); + }); + + it('with award clicked, it emits award', () => { + expect(wrapper.emitted().award).toBeUndefined(); + + findAwardButtons() + .at(2) + .trigger('click'); + + expect(wrapper.emitted().award).toEqual([[EMOJI_SMILE]]); + }); + + it('shows add award button', () => { + const btn = findAddAwardButton(); + + expect(btn.exists()).toBe(true); + expect(btn.classes(TEST_ADD_BUTTON_CLASS)).toBe(true); + }); + }); + + describe('with numeric award', () => { + beforeEach(() => { + createComponent({ + awards: [createAward(EMOJI_100, USERS.ada)], + canAwardEmoji: true, + currentUserId: USERS.root.id, + }); + }); + + it('when clicked, it emits award as number', () => { + expect(wrapper.emitted().award).toBeUndefined(); + + findAwardButtons() + .at(0) + .trigger('click'); + + expect(wrapper.emitted().award).toEqual([[Number(EMOJI_100)]]); + }); + }); + + describe('with no awards', () => { + beforeEach(() => { + createComponent({ + awards: [], + canAwardEmoji: true, + }); + }); + + it('has no award buttons', () => { + expect(findAwardButtons().length).toBe(0); + }); + }); + + describe('when cannot award emoji', () => { + beforeEach(() => { + createComponent({ + awards: [createAward(EMOJI_CACTUS, USERS.root.id)], + canAwardEmoji: false, + currentUserId: USERS.marie.id, + }); + }); + + it('does not have add button', () => { + expect(findAddAwardButton().exists()).toBe(false); + }); + }); + + describe('with no user', () => { + beforeEach(() => { + createComponent({ + awards: TEST_AWARDS, + canAwardEmoji: false, + }); + }); + + it('disables award buttons', () => { + const buttons = findAwardButtons(); + + expect(buttons.length).toBe(7); + expect(buttons.wrappers.every(x => x.classes('disabled'))).toBe(true); + }); + }); +}); |