Commit 87a4c229 authored by Eric Eastwood's avatar Eric Eastwood

Add lazy option to UserAvatarImage

parent 0bf399f5
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
Sample configuration: Sample configuration:
<user-avatar-image <user-avatar-image
:lazy="true"
:img-src="userAvatarSrc" :img-src="userAvatarSrc"
:img-alt="tooltipText" :img-alt="tooltipText"
:tooltip-text="tooltipText" :tooltip-text="tooltipText"
...@@ -16,11 +17,17 @@ ...@@ -16,11 +17,17 @@
*/ */
import defaultAvatarUrl from 'images/no_avatar.png'; import defaultAvatarUrl from 'images/no_avatar.png';
import { placeholderImage } from '../../../lazy_loader';
import tooltip from '../../directives/tooltip'; import tooltip from '../../directives/tooltip';
export default { export default {
name: 'UserAvatarImage', name: 'UserAvatarImage',
props: { props: {
lazy: {
type: Boolean,
required: false,
default: false,
},
imgSrc: { imgSrc: {
type: String, type: String,
required: false, required: false,
...@@ -56,18 +63,21 @@ export default { ...@@ -56,18 +63,21 @@ export default {
tooltip, tooltip,
}, },
computed: { computed: {
// API response sends null when gravatar is disabled and
// we provide an empty string when we use it inside user avatar link.
// In both cases we should render the defaultAvatarUrl
sanitizedSource() {
return this.imgSrc === '' || this.imgSrc === null ? defaultAvatarUrl : this.imgSrc;
},
resultantSrcAttribute() {
return this.lazy ? placeholderImage : this.sanitizedSource;
},
tooltipContainer() { tooltipContainer() {
return this.tooltipText ? 'body' : null; return this.tooltipText ? 'body' : null;
}, },
avatarSizeClass() { avatarSizeClass() {
return `s${this.size}`; return `s${this.size}`;
}, },
// API response sends null when gravatar is disabled and
// we provide an empty string when we use it inside user avatar link.
// In both cases we should render the defaultAvatarUrl
imageSource() {
return this.imgSrc === '' || this.imgSrc === null ? defaultAvatarUrl : this.imgSrc;
},
}, },
}; };
</script> </script>
...@@ -76,11 +86,16 @@ export default { ...@@ -76,11 +86,16 @@ export default {
<img <img
v-tooltip v-tooltip
class="avatar" class="avatar"
:class="[avatarSizeClass, cssClasses]" :class="{
:src="imageSource" lazy,
[avatarSizeClass]: true,
[cssClasses]: true
}"
:src="resultantSrcAttribute"
:width="size" :width="size"
:height="size" :height="size"
:alt="imgAlt" :alt="imgAlt"
:data-src="sanitizedSource"
:data-container="tooltipContainer" :data-container="tooltipContainer"
:data-placement="tooltipPlacement" :data-placement="tooltipPlacement"
:title="tooltipText" :title="tooltipText"
......
---
title: Add lazy option to UserAvatarImage
merge_request: 14895
author:
type: changed
import Vue from 'vue'; import Vue from 'vue';
import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue'; import { placeholderImage } from '~/lazy_loader';
import userAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
import mountComponent from '../../../helpers/vue_mount_component_helper';
const UserAvatarImageComponent = Vue.extend(UserAvatarImage); const DEFAULT_PROPS = {
describe('User Avatar Image Component', function () {
describe('Initialization', function () {
beforeEach(function () {
this.propsData = {
size: 99, size: 99,
imgSrc: 'myavatarurl.com', imgSrc: 'myavatarurl.com',
imgAlt: 'mydisplayname', imgAlt: 'mydisplayname',
cssClasses: 'myextraavatarclass', cssClasses: 'myextraavatarclass',
tooltipText: 'tooltip text', tooltipText: 'tooltip text',
tooltipPlacement: 'bottom', tooltipPlacement: 'bottom',
}; };
this.userAvatarImage = new UserAvatarImageComponent({ describe('User Avatar Image Component', function () {
propsData: this.propsData, let vm;
let UserAvatarImage;
beforeEach(() => {
UserAvatarImage = Vue.extend(userAvatarImage);
});
describe('Initialization', function () {
beforeEach(function () {
vm = mountComponent(UserAvatarImage, {
...DEFAULT_PROPS,
}).$mount(); }).$mount();
}); });
it('should return a defined Vue component', function () { it('should return a defined Vue component', function () {
expect(this.userAvatarImage).toBeDefined(); expect(vm).toBeDefined();
}); });
it('should have <img> as a child element', function () { it('should have <img> as a child element', function () {
expect(this.userAvatarImage.$el.tagName).toBe('IMG'); expect(vm.$el.tagName).toBe('IMG');
expect(vm.$el.getAttribute('src')).toBe(DEFAULT_PROPS.imgSrc);
expect(vm.$el.getAttribute('data-src')).toBe(DEFAULT_PROPS.imgSrc);
expect(vm.$el.getAttribute('alt')).toBe(DEFAULT_PROPS.imgAlt);
}); });
it('should properly compute tooltipContainer', function () { it('should properly compute tooltipContainer', function () {
expect(this.userAvatarImage.tooltipContainer).toBe('body'); expect(vm.tooltipContainer).toBe('body');
}); });
it('should properly render tooltipContainer', function () { it('should properly render tooltipContainer', function () {
expect(this.userAvatarImage.$el.getAttribute('data-container')).toBe('body'); expect(vm.$el.getAttribute('data-container')).toBe('body');
}); });
it('should properly compute avatarSizeClass', function () { it('should properly compute avatarSizeClass', function () {
expect(this.userAvatarImage.avatarSizeClass).toBe('s99'); expect(vm.avatarSizeClass).toBe('s99');
}); });
it('should properly render img css', function () { it('should properly render img css', function () {
const classList = this.userAvatarImage.$el.classList; const classList = vm.$el.classList;
const containsAvatar = classList.contains('avatar'); const containsAvatar = classList.contains('avatar');
const containsSizeClass = classList.contains('s99'); const containsSizeClass = classList.contains('s99');
const containsCustomClass = classList.contains('myextraavatarclass'); const containsCustomClass = classList.contains(DEFAULT_PROPS.cssClasses);
const lazyClass = classList.contains('lazy');
expect(containsAvatar).toBe(true); expect(containsAvatar).toBe(true);
expect(containsSizeClass).toBe(true); expect(containsSizeClass).toBe(true);
expect(containsCustomClass).toBe(true); expect(containsCustomClass).toBe(true);
expect(lazyClass).toBe(false);
});
});
describe('Initialization when lazy', function () {
beforeEach(function () {
vm = mountComponent(UserAvatarImage, {
...DEFAULT_PROPS,
lazy: true,
}).$mount();
});
it('should add lazy attributes', function () {
const classList = vm.$el.classList;
const lazyClass = classList.contains('lazy');
expect(lazyClass).toBe(true);
expect(vm.$el.getAttribute('src')).toBe(placeholderImage);
expect(vm.$el.getAttribute('data-src')).toBe(DEFAULT_PROPS.imgSrc);
}); });
}); });
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment