-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add better fallbacks for missing avatar image and name (#88)
* Add better fallbacks for missing avatar image and name * Add initial fallbacks to first_name and email * Add tests for fallback behavior * update vite to latest
- Loading branch information
1 parent
f97ea4f
commit f647fde
Showing
8 changed files
with
1,475 additions
and
156 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,16 @@ | ||
<script lang="ts"> | ||
import type { Models } from '@kittycad/lib' | ||
import Person from 'components/Icons/Person.svelte' | ||
import { paths } from '$lib/paths' | ||
import Person from './Icons/Person.svelte' | ||
export let user: Models['User_type'] | ||
let open = false | ||
let displayImage = true | ||
let shouldDisplayImage = Boolean(user?.image && user.image !== '') | ||
let shouldDisplayInitial = | ||
!shouldDisplayImage && | ||
((user?.name && user.name.length > 0) || | ||
(user?.first_name && user.first_name.length > 0) || | ||
(user?.email && user.email.length > 0)) | ||
function dismiss(e: KeyboardEvent) { | ||
if (e.key === 'Escape') { | ||
|
@@ -16,32 +21,41 @@ | |
|
||
<div class={'relative flex justify-center items-center ' + (open ? 'open' : '')}> | ||
<button | ||
class={'toggle border border-solid hover:border-green overflow-hidden bg-currentColor w-8 h-8 md:w-12 md:h-12 ' + | ||
(displayImage ? 'rounded-full' : '')} | ||
class={'toggle grid place-content-center border border-solid hover:border-green overflow-hidden bg-currentColor w-8 h-8 md:w-12 md:h-12 ' + | ||
(shouldDisplayInitial || shouldDisplayImage ? 'rounded-full' : 'rounded')} | ||
on:click={() => { | ||
open = !open | ||
}} | ||
on:keydown={dismiss} | ||
> | ||
{#if displayImage} | ||
<img | ||
src={user.image} | ||
alt="Avatar" | ||
class="object-fill" | ||
referrerpolicy="no-referrer" | ||
on:error={() => { | ||
displayImage = false | ||
}} | ||
<img | ||
src={user.image} | ||
alt="Avatar" | ||
class="object-fill" | ||
style={`display: ${shouldDisplayImage ? 'block' : 'none'}`} | ||
referrerpolicy="no-referrer" | ||
/> | ||
{#if shouldDisplayInitial} | ||
<span | ||
class="w-5 h-5 font-bold text-xl leading-[1] pt-0.5 text-center text-chalkboard-10 dark:text-chalkboard-120" | ||
data-testid="initial">{user.name[0] || user.first_name[0] || user.email[0]}</span | ||
> | ||
{:else if !shouldDisplayImage} | ||
<Person | ||
data-testid="person-icon" | ||
class="w-full text-chalkboard-10 dark:text-chalkboard-120" | ||
/> | ||
{:else} | ||
<Person class="object-fill p-1 block text-chalkboard-10 dark:text-chalkboard-120" /> | ||
{/if} | ||
<span class="sr-only">Open menu</span> | ||
</button> | ||
<dialog class="menu"> | ||
<menu class="contents"> | ||
<div class="p-4 pb-2"> | ||
<p class="font-mono">{user?.name || 'Unnamed User'}</p> | ||
<p class="font-mono"> | ||
{user?.first_name | ||
? user.first_name + (user.last_name ? user.last_name : '') | ||
: user?.name || 'Unnamed User'} | ||
</p> | ||
<p class="font-mono text-sm text-chalkboard-70 dark:text-chalkboard-40"> | ||
{user?.email || '[email protected]'} | ||
</p> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
import { render } from '@testing-library/svelte' | ||
import AccountMenu from './AccountMenu.svelte' | ||
import type { Models } from '@kittycad/lib' | ||
|
||
const FULL_USER: Models['User_type'] = { | ||
id: 'some_id', | ||
name: 'Frank Noirot', | ||
email: '[email protected]', | ||
image: | ||
'https://lh3.googleusercontent.com/a/ACg8ocIiX1-R981041VeC5g5SCFVUzS2rUvkNPSVgD35gSy_lEU=s96-c', | ||
phone: '', | ||
first_name: 'Another', | ||
last_name: 'Alias', | ||
created_at: '1993-09-16T19:33:17.783Z', | ||
updated_at: '2023-10-13T19:33:17.783Z', | ||
company: '', | ||
discord: '', | ||
github: '' | ||
} | ||
const NAME_USER: Models['User_type'] = { | ||
...FULL_USER, | ||
image: '' | ||
} | ||
const FIRST_NAME_USER: Models['User_type'] = { | ||
...NAME_USER, | ||
name: '' | ||
} | ||
const EMAIL_USER: Models['User_type'] = { | ||
...FIRST_NAME_USER, | ||
first_name: '' | ||
} | ||
const FAILED_USER: Models['User_type'] = { | ||
...EMAIL_USER, | ||
email: '' | ||
} | ||
|
||
describe('AccountMenu', async () => { | ||
it('avatar image appears if available', async () => { | ||
const component = await render(AccountMenu, { | ||
props: { | ||
user: FULL_USER | ||
} | ||
}) | ||
|
||
expect(component.getByAltText('Avatar')).toBeVisible() | ||
}) | ||
|
||
it('fallback initial appears if name is available', async () => { | ||
const component = await render(AccountMenu, { | ||
props: { | ||
user: NAME_USER | ||
} | ||
}) | ||
|
||
expect(component.getByAltText('Avatar')).not.toBeVisible() | ||
const initial = await component.getByTestId('initial') | ||
expect(initial).toBeVisible() | ||
expect(initial.textContent).toBe(NAME_USER.name[0]) | ||
}) | ||
|
||
it('fallback initial appears if first_name is available', async () => { | ||
const component = await render(AccountMenu, { | ||
props: { | ||
user: FIRST_NAME_USER | ||
} | ||
}) | ||
|
||
expect(component.getByAltText('Avatar')).not.toBeVisible() | ||
const initial = await component.getByTestId('initial') | ||
expect(initial).toBeVisible() | ||
expect(initial.textContent).toBe(FIRST_NAME_USER.first_name[0]) | ||
}) | ||
|
||
it('fallback initial appears if email is available', async () => { | ||
const component = await render(AccountMenu, { | ||
props: { | ||
user: EMAIL_USER | ||
} | ||
}) | ||
|
||
expect(component.getByAltText('Avatar')).not.toBeVisible() | ||
const initial = await component.getByTestId('initial') | ||
expect(initial).toBeVisible() | ||
expect(initial.textContent).toBe(FIRST_NAME_USER.email[0]) | ||
}) | ||
|
||
it('user outline appears if all other options fail', async () => { | ||
const component = await render(AccountMenu, { | ||
props: { | ||
user: FAILED_USER | ||
} | ||
}) | ||
|
||
expect(component.getByAltText('Avatar')).not.toBeVisible() | ||
expect(await component.getByTestId('person-icon')).toBeVisible() | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
import 'vitest-dom/extend-expect' |
Oops, something went wrong.