Skip to content

Commit

Permalink
feat(frontend): filter carousel dApps using user profile (#3811)
Browse files Browse the repository at this point in the history
# Motivation

With PR #3770 , we introduces a list of hidden dApps in the carousel,
saved in the user profile.

Now we filter the daps accordingly.

# Changes

- Extract dapps filter function.
- Add filter by hidden dApps from the User Profile. 

# Tests

Tests provided.

---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
  • Loading branch information
AntonioVentilii and github-actions[bot] authored Dec 6, 2024
1 parent b390208 commit ab390e3
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 11 deletions.
11 changes: 8 additions & 3 deletions src/frontend/src/lib/components/dapps/DappsCarousel.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,24 @@
import { nonNullish } from '@dfinity/utils';
import Carousel from '$lib/components/carousel/Carousel.svelte';
import DappsCarouselSlide from '$lib/components/dapps/DappsCarouselSlide.svelte';
import { userSettings } from '$lib/derived/user-profile.derived';
import {
type CarouselSlideOisyDappDescription,
dAppDescriptions
dAppDescriptions,
type OisyDappDescription
} from '$lib/types/dapp-description';
import { filterCarouselDapps } from '$lib/utils/dapps.utils';
export let styleClass: string | undefined = undefined;
let hiddenDappsIds: OisyDappDescription['id'][];
$: hiddenDappsIds = $userSettings?.dapp.dapp_carousel.hidden_dapp_ids ?? [];
let dappsCarouselSlides: CarouselSlideOisyDappDescription[];
$: dappsCarouselSlides = filterCarouselDapps(dAppDescriptions);
$: dappsCarouselSlides = filterCarouselDapps({ dAppDescriptions, hiddenDappsIds });
</script>

{#if nonNullish(dappsCarouselSlides) && dappsCarouselSlides.length > 0}
{#if nonNullish($userSettings) && nonNullish(dappsCarouselSlides) && dappsCarouselSlides.length > 0}
<!-- To align controls section with slide text - 100% - logo width (4rem) - margin logo-text (1rem) -->
<Carousel controlsWidthStyleClass="w-[calc(100%-5rem)]" styleClass={`w-full ${styleClass ?? ''}`}>
{#each dappsCarouselSlides as dappsCarouselSlide}
Expand Down
14 changes: 9 additions & 5 deletions src/frontend/src/lib/utils/dapps.utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@ import {
} from '$lib/types/dapp-description';
import { nonNullish } from '@dfinity/utils';

export const filterCarouselDapps = (
dAppDescriptions: OisyDappDescription[]
): CarouselSlideOisyDappDescription[] =>
dAppDescriptions.filter(({ carousel }) =>
nonNullish(carousel)
export const filterCarouselDapps = ({
dAppDescriptions,
hiddenDappsIds
}: {
dAppDescriptions: OisyDappDescription[];
hiddenDappsIds: OisyDappDescription['id'][];
}): CarouselSlideOisyDappDescription[] =>
dAppDescriptions.filter(
({ id, carousel }) => nonNullish(carousel) && !hiddenDappsIds.includes(id)
) as CarouselSlideOisyDappDescription[];
48 changes: 48 additions & 0 deletions src/frontend/src/tests/lib/components/dapps/DappsCarousel.spec.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import type { Settings, UserProfile } from '$declarations/backend/backend.did';
import DappsCarousel from '$lib/components/dapps/DappsCarousel.svelte';
import { CAROUSEL_CONTAINER } from '$lib/constants/test-ids.constants';
import { userProfileStore } from '$lib/stores/user-profile.store';
import * as dapps from '$lib/types/dapp-description';
import { mockDappsDescriptions } from '$tests/mocks/dapps.mock';
import { mockUserProfile, mockUserSettings } from '$tests/mocks/user-profile.mock';
import { toNullable } from '@dfinity/utils';
import { render } from '@testing-library/svelte';
import { describe, expect, it } from 'vitest';

describe('DappsCarousel', () => {
beforeEach(() => {
vi.clearAllMocks();

userProfileStore.set({ profile: mockUserProfile, certified: false });
});

it('should render nothing if there is no dApps', () => {
Expand All @@ -26,6 +32,48 @@ describe('DappsCarousel', () => {
expect(container.innerHTML).toBe('');
});

it('should render nothing if all dApps were hidden', () => {
const settings: Settings = {
...mockUserSettings,
dapp: {
...mockUserSettings.dapp,
dapp_carousel: {
...mockUserSettings.dapp.dapp_carousel,
hidden_dapp_ids: mockDappsDescriptions.map(({ id }) => id)
}
}
};

const userProfile: UserProfile = {
...mockUserProfile,
settings: toNullable(settings)
};

userProfileStore.set({ profile: userProfile, certified: false });

const { container } = render(DappsCarousel);
expect(container.innerHTML).toBe('');
});

it('should render nothing if the user profile is nullish', () => {
userProfileStore.reset();

const { container } = render(DappsCarousel);
expect(container.innerHTML).toBe('');
});

it('should render nothing if the user settings are nullish', () => {
const userProfile: UserProfile = {
...mockUserProfile,
settings: []
};

userProfileStore.set({ profile: userProfile, certified: false });

const { container } = render(DappsCarousel);
expect(container.innerHTML).toBe('');
});

it('should render the Carousel when data exist', () => {
const { getByTestId } = render(DappsCarousel);
expect(getByTestId(CAROUSEL_CONTAINER)).toBeInTheDocument();
Expand Down
34 changes: 31 additions & 3 deletions src/frontend/src/tests/lib/utils/dapps.utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,44 @@ describe('dapps.utils', () => {
...mockDapps.slice(1)
];

expect(filterCarouselDapps(dAppDescriptions)).toStrictEqual(mockDapps.slice(1));
expect(filterCarouselDapps({ dAppDescriptions, hiddenDappsIds: [] })).toStrictEqual(
mockDapps.slice(1)
);
});

it('should filter out dApps whose ids are in hiddenDappsIds', () => {
expect(
filterCarouselDapps({
dAppDescriptions: mockDapps,
hiddenDappsIds: [mockDapps[0].id]
})
).toEqual(mockDapps.slice(1));
});

it('should return an empty array if all dApps are filtered out', () => {
expect(
filterCarouselDapps({
dAppDescriptions: mockDapps,
hiddenDappsIds: mockDapps.map(({ id }) => id)
})
).toEqual([]);
});

it('should return the same array if no dApps are filtered out', () => {
expect(filterCarouselDapps(mockDapps)).toEqual(mockDapps);
expect(
filterCarouselDapps({
dAppDescriptions: mockDapps,
hiddenDappsIds: []
})
).toEqual(mockDapps);
});

it('should return an empty array if all dApps have nullish carousel property', () => {
expect(
filterCarouselDapps(mockDapps.map((dapps) => ({ ...dapps, carousel: undefined })))
filterCarouselDapps({
dAppDescriptions: mockDapps.map((dapps) => ({ ...dapps, carousel: undefined })),
hiddenDappsIds: []
})
).toEqual([]);
});
});
Expand Down

0 comments on commit ab390e3

Please sign in to comment.