-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #548 from bounswe/feature/MB-tests-portfolio-markets
Feature/mb tests portfolio markets
- Loading branch information
Showing
5 changed files
with
469 additions
and
11 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
import React from 'react'; | ||
import { render, fireEvent, waitFor } from '@testing-library/react-native'; | ||
import Markets from '../src/pages/Markets'; | ||
|
||
// Mock navigation | ||
const mockNavigate = jest.fn(); | ||
const mockNavigation = { navigate: mockNavigate }; | ||
|
||
// Mock fetch globally | ||
global.fetch = jest.fn(); | ||
|
||
describe('Markets Component', () => { | ||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
}); | ||
|
||
test('renders loading indicator initially', () => { | ||
const { getByTestId } = render(<Markets navigation={mockNavigation} />); | ||
expect(getByTestId('loading-indicator')).toBeTruthy(); | ||
}); | ||
|
||
test('displays stocks correctly after fetching', async () => { | ||
const mockStocks = [ | ||
{ id: 1, name: 'Stock A', symbol: 'A', price: 100, currency: { code: 'USD' } }, | ||
{ id: 2, name: 'Stock B', symbol: 'B', price: 200, currency: { code: 'USD' } }, | ||
]; | ||
|
||
global.fetch.mockResolvedValueOnce({ | ||
ok: true, | ||
json: () => Promise.resolve(mockStocks), | ||
}); | ||
|
||
const { getByText } = render(<Markets navigation={mockNavigation} />); | ||
|
||
await waitFor(() => expect(getByText('Stock A')).toBeTruthy()); | ||
expect(getByText('100.00 USD')).toBeTruthy(); | ||
expect(getByText('Stock B')).toBeTruthy(); | ||
expect(getByText('200.00 USD')).toBeTruthy(); | ||
}); | ||
|
||
test('shows an error alert if fetching fails', async () => { | ||
global.fetch.mockResolvedValueOnce({ | ||
ok: false, | ||
status: 500, | ||
}); | ||
|
||
const alertSpy = jest.spyOn(Alert, 'alert'); | ||
render(<Markets navigation={mockNavigation} />); | ||
|
||
await waitFor(() => | ||
expect(alertSpy).toHaveBeenCalledWith('Error', 'Unable to fetch stocks. Please try again later.') | ||
); | ||
}); | ||
|
||
test('search functionality filters results correctly', async () => { | ||
const mockSearchResults = [ | ||
{ id: 3, name: 'Stock C', symbol: 'C', price: 300, currency: { code: 'USD' } }, | ||
]; | ||
|
||
global.fetch | ||
.mockResolvedValueOnce({ | ||
ok: true, | ||
json: () => Promise.resolve([]), // Initial fetch | ||
}) | ||
.mockResolvedValueOnce({ | ||
ok: true, | ||
json: () => Promise.resolve(mockSearchResults), // Search fetch | ||
}); | ||
|
||
const { getByPlaceholderText, getByText } = render(<Markets navigation={mockNavigation} />); | ||
|
||
const searchInput = getByPlaceholderText('Search'); | ||
fireEvent.changeText(searchInput, 'Stock C'); | ||
|
||
await waitFor(() => expect(getByText('Stock C')).toBeTruthy()); | ||
expect(getByText('300.00 USD')).toBeTruthy(); | ||
}); | ||
|
||
test('triggers navigation to StockDetails when a stock is pressed', async () => { | ||
const mockStocks = [{ id: 1, name: 'Stock A', symbol: 'A', price: 100, currency: { code: 'USD' } }]; | ||
|
||
global.fetch.mockResolvedValueOnce({ | ||
ok: true, | ||
json: () => Promise.resolve(mockStocks), | ||
}); | ||
|
||
const { getByText } = render(<Markets navigation={mockNavigation} />); | ||
|
||
await waitFor(() => expect(getByText('Stock A')).toBeTruthy()); | ||
fireEvent.press(getByText('Stock A')); | ||
expect(mockNavigate).toHaveBeenCalledWith('StockDetails', { id: 1 }); | ||
}); | ||
|
||
test('loads more stocks when reaching the end of the list', async () => { | ||
const mockStocksPage1 = [ | ||
{ id: 1, name: 'Stock A', symbol: 'A', price: 100, currency: { code: 'USD' } }, | ||
]; | ||
const mockStocksPage2 = [ | ||
{ id: 2, name: 'Stock B', symbol: 'B', price: 200, currency: { code: 'USD' } }, | ||
]; | ||
|
||
global.fetch | ||
.mockResolvedValueOnce({ | ||
ok: true, | ||
json: () => Promise.resolve(mockStocksPage1), // First page | ||
}) | ||
.mockResolvedValueOnce({ | ||
ok: true, | ||
json: () => Promise.resolve(mockStocksPage2), // Second page | ||
}); | ||
|
||
const { getByText, getByTestId } = render(<Markets navigation={mockNavigation} />); | ||
|
||
await waitFor(() => expect(getByText('Stock A')).toBeTruthy()); | ||
|
||
fireEvent.scroll(getByTestId('flatlist'), { | ||
nativeEvent: { contentOffset: { y: 500 }, contentSize: { height: 1000 }, layoutMeasurement: { height: 500 } }, | ||
}); | ||
|
||
await waitFor(() => expect(getByText('Stock B')).toBeTruthy()); | ||
expect(global.fetch).toHaveBeenCalledTimes(2); | ||
}); | ||
}); |
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,71 @@ | ||
import React from 'react'; | ||
import { render, fireEvent, waitFor } from '@testing-library/react-native'; | ||
import Portfolio from '../src/pages/Portfolio'; | ||
import { useAuth } from '../src/pages/context/AuthContext'; | ||
|
||
// Mock AuthContext | ||
jest.mock('../context/AuthContext', () => ({ | ||
useAuth: jest.fn(), | ||
})); | ||
|
||
// Mock navigation | ||
const mockNavigate = jest.fn(); | ||
const mockNavigation = { navigate: mockNavigate }; | ||
|
||
describe('Portfolio Component', () => { | ||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
useAuth.mockReturnValue({ | ||
userId: 'testUserId', | ||
accessToken: 'testAccessToken', | ||
}); | ||
}); | ||
|
||
test('renders loading indicator while fetching data', async () => { | ||
const { getByTestId } = render(<Portfolio navigation={mockNavigation} />); | ||
expect(getByTestId('loading-indicator')).toBeTruthy(); | ||
}); | ||
|
||
test('displays "No portfolios yet" when no data is available', async () => { | ||
global.fetch = jest.fn(() => | ||
Promise.resolve({ | ||
ok: true, | ||
json: () => Promise.resolve([]), | ||
}) | ||
); | ||
|
||
const { getByText } = render(<Portfolio navigation={mockNavigation} />); | ||
await waitFor(() => expect(getByText('You have no portfolios yet.')).toBeTruthy()); | ||
}); | ||
|
||
test('renders portfolios correctly', async () => { | ||
const mockPortfolios = [ | ||
{ id: '1', name: 'Portfolio 1', stocks: [], totalProfitOrLoss: 100 }, | ||
]; | ||
global.fetch = jest.fn(() => | ||
Promise.resolve({ | ||
ok: true, | ||
json: () => Promise.resolve(mockPortfolios), | ||
}) | ||
); | ||
|
||
const { getByText } = render(<Portfolio navigation={mockNavigation} />); | ||
await waitFor(() => expect(getByText('Portfolio 1')).toBeTruthy()); | ||
}); | ||
|
||
test('navigates to PortfolioDetails on card press', async () => { | ||
const mockPortfolios = [ | ||
{ id: '1', name: 'Portfolio 1', stocks: [], totalProfitOrLoss: 100 }, | ||
]; | ||
global.fetch = jest.fn(() => | ||
Promise.resolve({ | ||
ok: true, | ||
json: () => Promise.resolve(mockPortfolios), | ||
}) | ||
); | ||
|
||
const { getByText } = render(<Portfolio navigation={mockNavigation} />); | ||
await waitFor(() => fireEvent.press(getByText('Portfolio 1'))); | ||
expect(mockNavigate).toHaveBeenCalledWith('PortfolioDetails', { portfolio: mockPortfolios[0] }); | ||
}); | ||
}); |
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,95 @@ | ||
import React from 'react'; | ||
import { render, fireEvent, waitFor } from '@testing-library/react-native'; | ||
import PortfolioDetails from '../src/pages/PortfolioDetails'; | ||
import { useAuth } from '../src/pages/context/AuthContext'; | ||
|
||
// Mock AuthContext | ||
jest.mock('../context/AuthContext', () => ({ | ||
useAuth: jest.fn(), | ||
})); | ||
|
||
describe('PortfolioDetails Component', () => { | ||
const mockPortfolio = { | ||
id: '1', | ||
name: 'My Portfolio', | ||
description: 'This is a test portfolio', | ||
created_at: '2023-01-01T00:00:00Z', | ||
stocks: [ | ||
{ | ||
stock: 'stock1', | ||
name: 'Stock 1', | ||
symbol: 'STK1', | ||
quantity: 10, | ||
price_bought: 100, | ||
currentPrice: 150, | ||
currency: 'USD', | ||
}, | ||
], | ||
}; | ||
|
||
beforeEach(() => { | ||
jest.clearAllMocks(); | ||
useAuth.mockReturnValue({ | ||
accessToken: 'testAccessToken', | ||
}); | ||
}); | ||
|
||
test('renders portfolio details', () => { | ||
const { getByText } = render(<PortfolioDetails route={{ params: { portfolio: mockPortfolio } }} />); | ||
expect(getByText('My Portfolio')).toBeTruthy(); | ||
expect(getByText('This is a test portfolio')).toBeTruthy(); | ||
expect(getByText('Created on: 1/1/2023')).toBeTruthy(); | ||
}); | ||
|
||
test('renders stock details correctly', () => { | ||
const { getByText } = render(<PortfolioDetails route={{ params: { portfolio: mockPortfolio } }} />); | ||
expect(getByText('Stock 1')).toBeTruthy(); | ||
expect(getByText('Quantity: 10, Bought at: 100.00 USD, Current: 150.00 USD')).toBeTruthy(); | ||
}); | ||
|
||
test('handles stock removal', async () => { | ||
global.fetch = jest.fn(() => | ||
Promise.resolve({ | ||
ok: true, | ||
json: () => Promise.resolve({}), | ||
}) | ||
); | ||
|
||
const { getByText, queryByText } = render( | ||
<PortfolioDetails route={{ params: { portfolio: mockPortfolio } }} /> | ||
); | ||
|
||
fireEvent.press(getByText('Remove')); | ||
await waitFor(() => expect(queryByText('Stock 1')).toBeNull()); | ||
}); | ||
|
||
test('handles adding a new stock', async () => { | ||
global.fetch = jest.fn(() => | ||
Promise.resolve({ | ||
ok: true, | ||
json: () => Promise.resolve({ | ||
id: 'stock2', | ||
name: 'Stock 2', | ||
symbol: 'STK2', | ||
price: 200, | ||
currency: { code: 'USD' }, | ||
}), | ||
}) | ||
); | ||
|
||
const { getByPlaceholderText, getByText } = render( | ||
<PortfolioDetails route={{ params: { portfolio: mockPortfolio } }} /> | ||
); | ||
|
||
fireEvent.changeText(getByPlaceholderText('Search Stocks'), 'Stock 2'); | ||
fireEvent.press(getByText('Search')); | ||
|
||
await waitFor(() => fireEvent.press(getByText('Stock 2 (STK2)'))); | ||
|
||
fireEvent.changeText(getByPlaceholderText('Price Bought (TRY)'), '200'); | ||
fireEvent.changeText(getByPlaceholderText('Quantity'), '5'); | ||
fireEvent.press(getByText('Add')); | ||
|
||
await waitFor(() => expect(getByText('Stock 2')).toBeTruthy()); | ||
}); | ||
}); |
Oops, something went wrong.