Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1 +1 @@
VITE_API_URL="http://localhost:8083"
VITE_API_URL="http://localhost:8080/v1/"
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { MantineProvider } from '@mantine/core';
import MyCollectionsContent from './index';
import Collection from '../../../../models/user/collection';
import { mockCollection } from '../../../../test-utils/mocks/models/collection';
import { mockPagination } from '../../../../test-utils/mocks';
import { mockPagination } from '../../../../test-utils/mocks/pagination';

// Mock the CollectionCard component
jest.mock('./CollectionCard', () => ({
Expand Down
2 changes: 1 addition & 1 deletion src/components/Dashboard/MyCollections/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import MyCollections from './index';
import User from '../../../models/user/user';
import { UserCollectionsContext, UserCollectionsContextState } from '../../../contexts/UserCollectionsContext';
import CollectionManagementRequests from '../../../services/requests/CollectionManagementRequests';
import { mockPagination } from '../../../test-utils/mocks';
import { mockPagination } from '../../../test-utils/mocks/pagination';
import { renderWithProviders } from '../../../test-utils';
import Collection from '../../../models/user/collection';
import CollectionItem from '../../../models/user/collection-items';
Expand Down
3 changes: 2 additions & 1 deletion src/components/Template/Page/index.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ describe('Page', () => {
renderWithRouter(<Page />);

// Check for sidebar
expect(screen.getByRole('link', { name: /home/i })).toBeInTheDocument();
const homeLink = document.querySelector('a[href="/"]');
expect(homeLink).toBeInTheDocument();

// Check for navigation
expect(screen.getByText('Header Title')).toBeInTheDocument();
Expand Down
55 changes: 11 additions & 44 deletions src/contexts/UserCollectionsContext.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {
BasePaginatedContextProviderProps,
BasePaginatedContextState, createCallbacks,
defaultBaseContext,
defaultBaseContext, prepareContextState,
} from './BasePaginatedContext';
import React, {PropsWithChildren, useCallback, useEffect, useMemo, useState, Dispatch, SetStateAction} from 'react';
import React, {PropsWithChildren, useEffect, useState} from 'react';
import Collection from "../models/user/collection";

/**
Expand All @@ -13,13 +13,12 @@ export interface UserCollectionsContextState extends BasePaginatedContextState<C

/**
* This lets us persist the loaded state across multiple instances of the provider
* For initial load only.
*/
const initialPersistentContextState = createDefaultState();
let persistentContext = createDefaultState();

function createDefaultState(): UserCollectionsContextState {
return {
...defaultBaseContext<Collection>(), // Specify Model type
...defaultBaseContext(),
loadAll: true,
order: {
'created_at': 'desc',
Expand All @@ -38,47 +37,15 @@ export interface UserCollectionsContextProviderProps extends BasePaginatedContex
}

export const UserCollectionsContextProvider: React.FC<PropsWithChildren<UserCollectionsContextProviderProps>> = (props => {
const [userCollectionsState, setUserCollectionsState] = useState<UserCollectionsContextState>(initialPersistentContextState);

const wrappedSetUserCollectionsState: Dispatch<SetStateAction<BasePaginatedContextState<Collection>>> =
useCallback((action) => {
setUserCollectionsState(currentUserCollectionsState => {
const baseStateChanges = typeof action === 'function'
? (action as (prevState: BasePaginatedContextState<Collection>) => BasePaginatedContextState<Collection>)(currentUserCollectionsState)
: action;
return { ...currentUserCollectionsState, ...baseStateChanges } as UserCollectionsContextState;
});
}, [setUserCollectionsState]);

const [userCollectionsState, setUserCollectionsState] = useState(persistentContext);
useEffect(() => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
setUserCollectionsState(_prevState => {
let newState = createDefaultState();

newState = createCallbacks<Collection>(
wrappedSetUserCollectionsState,
newState,
`/users/${props.userId}/collections`
);

newState.refreshData(false).catch(console.error);
prepareContextState(setUserCollectionsState, userCollectionsState, '/users/' + props.userId + '/collections')
}, [props.userId, userCollectionsState]);

return {
...newState,
loadedData: [],
lastLoadedPage: undefined,
noResults: false,
refreshing: true,
initialLoadComplete: false,
initiated: true,
};
});
}, [props.userId, setUserCollectionsState, wrappedSetUserCollectionsState]);

const fullContext = useMemo(() => ({
...userCollectionsState,
...createCallbacks<Collection>(wrappedSetUserCollectionsState, userCollectionsState, `/users/${props.userId}/collections`)
}), [userCollectionsState, wrappedSetUserCollectionsState, props.userId]);
const fullContext = {
...persistentContext,
...createCallbacks(setUserCollectionsState, persistentContext, '/users/' + props.userId + '/collections')
}

return (
<UserCollectionsContext.Provider value={fullContext}>
Expand Down
102 changes: 6 additions & 96 deletions src/test-utils/mocks/api.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,5 @@
/* eslint-disable */
// @ts-nocheck
import { mockUser } from './models/user';
import { mockCategory } from './models/category';
import { mockCollection } from './models/collection';
import { mockCollectionItem } from './models/collection-items';
import { mockOrganization } from './models/organization';
import { mockBusiness } from './models/business';
import { mockPostResponse } from './models/post-response';
import { mockLocation } from './models/location';
import { mockRole } from './models/role';
import { mockOrganizationManager } from '../../../models/organization/organization-manager';
import { mockPage } from '../../../models/page';

export interface ApiConfig {
params?: Record<string, any>;
params?: Record<string, unknown>;
signal?: AbortSignal;
}

Expand All @@ -28,81 +14,19 @@ export interface Page<T> {
data: T[];
}

// Export mock data for use in tests
export { mockPlatform, mockPlatformGroup };

const api = {
get: jest.fn().mockImplementation((url: string, config?: ApiConfig): Promise<ApiResponse<any>> => {
get: jest.fn().mockImplementation((url: string, config?: ApiConfig): Promise<ApiResponse<Page<unknown>>> => {
// Parse URL parameters from both URL and config
const urlParams = new URLSearchParams(url.split('?')[1] || '');
const configParams = config?.params || {};

// Merge URL params with config params
Object.entries(configParams).forEach(([key, value]) => {
if (value !== undefined) {
if (value !== undefined && value !== null) {
urlParams.set(key, value.toString());
}
});

const expand = urlParams.get('expand[platforms]') === '*';
const page = parseInt(urlParams.get('page') || '1');
const limit = parseInt(urlParams.get('limit') || '10');

// Handle paginated endpoints
if (url === '/platforms') {
const response: Page<any> = {
current_page: page,
last_page: 1,
total: 1,
data: [mockPlatform]
};
return Promise.resolve({ data: response });
}

if (url === '/platform-groups') {
const response: Page<any> = {
current_page: page,
last_page: 1,
total: 1,
data: [mockPlatformGroup]
};
return Promise.resolve({ data: response });
}

// Handle single platform group endpoint
const platformGroupMatch = url.match(/\/platform-groups\/(\d+)/);
if (platformGroupMatch) {
const groupId = parseInt(platformGroupMatch[1]);
if (groupId === mockPlatformGroup.id) {
const response = {
...mockPlatformGroup,
platforms: expand ? [mockPlatform] : undefined
};
return Promise.resolve({ data: response });
}
return Promise.reject({
response: {
data: { error: 'Platform group not found' },
status: 404
}
});
}

// Handle single platform endpoint
const platformMatch = url.match(/\/platforms\/(\d+)/);
if (platformMatch) {
const platformId = parseInt(platformMatch[1]);
if (platformId === mockPlatform.id) {
return Promise.resolve({ data: mockPlatform });
}
return Promise.reject({
response: {
data: { error: 'Platform not found' },
status: 404
}
});
}

// Default response for unhandled endpoints
return Promise.resolve({
data: {
Expand All @@ -114,29 +38,15 @@ const api = {
});
}),

post: jest.fn().mockImplementation((url: string, data: any): Promise<ApiResponse<any>> => {
if (url === '/platform-groups') {
return Promise.resolve({ data: { ...mockPlatformGroup, ...data } });
}
if (url === '/platforms') {
return Promise.resolve({ data: { ...mockPlatform, ...data } });
}
post: jest.fn().mockImplementation((): Promise<ApiResponse<unknown>> => {
return Promise.resolve({ data: null });
}),

put: jest.fn().mockImplementation((url: string, data: any): Promise<ApiResponse<any>> => {
const platformGroupMatch = url.match(/\/platform-groups\/(\d+)/);
if (platformGroupMatch) {
return Promise.resolve({ data: { ...mockPlatformGroup, ...data } });
}
const platformMatch = url.match(/\/platforms\/(\d+)/);
if (platformMatch) {
return Promise.resolve({ data: { ...mockPlatform, ...data } });
}
put: jest.fn().mockImplementation((): Promise<ApiResponse<unknown>> => {
return Promise.resolve({ data: null });
}),

delete: jest.fn().mockImplementation((url: string): Promise<ApiResponse<any>> => {
delete: jest.fn().mockImplementation((): Promise<ApiResponse<{ success: boolean }>> => {
return Promise.resolve({ data: { success: true } });
})
};
Expand Down
138 changes: 0 additions & 138 deletions src/test-utils/mocks/contexts.tsx

This file was deleted.

Loading
Loading