Skip to content

Milestone 3 Report ‐ CMPE451

furkansenkal edited this page Dec 20, 2024 · 8 revisions

CMPE451 Group 2 Milestone 3 Report

Contributors

  • Cem Güngör
  • Rukiye Aslan
  • Furkan Şenkal
  • Rafet Oğuz Pançuk
  • Mahmut Buğra Mert
  • Kamil Deniz Coşkuner
  • Halil İbrahim Kasapoğlu
  • Muhammed Erkam Gökcepınar

Table of contents

1 Executive Summary

  • Provide a summary of your project status.
  • Explain the status of the deliverables.
  • Provide final release notes.
  • Describe any changes your team has made or planned based on previous milestones to improve the development process. Explain how those changes impacted the overall project.
  • Provide reflections related to your Final Milestone Demo, including lessons learned.
  • Describe what could have been done differently at the start of the project to finalize it, with reasons.

2 Progress Based on Teamwork

2.1 Summary of work:

Name Summary of Work
Cem Güngör
Rukiye Aslan
Furkan Şenkal
Rafet Oğuz Pançuk
Mahmut Buğra Mert I was a member of the frontend team for web development. In general, I was responsible with community page and its components. I was responsible of implementing comments, tags, like/unlike, annotation. I implemented the navigation an coordination between them. Also, I created a unit test for Assets Modal Page.
Kamil Deniz Coşkuner
Halil İbrahim Kasapoğlu
Muhammed Erkam Gökcepınar

2.2 Status of Requirements:

Functional Requirements

1.1 User Requirements

1.1.1 Register & Login
  • 1.1.1.1 Users shall be able to register with a unique username, e-mail address, and password. [Completed]
  • 1.1.1.2 User shall be registered with a secure password. [Completed]
  • 1.1.1.3 Users shall be able to log in using their registered credentials. [Completed]
  • 1.1.1.4 Users should have the option to reset their password via e-mail verification. [In Progress]
  • 1.1.1.5 Users shall be able to log out from the system. [Completed]
  • 1.1.1.6 Users shall accept the Terms of Use and Privacy Policy in order to register. [Not Started]
1.1.2 User Types
1.1.2.1 Guest User
  • 1.1.2.1.1 Guest user shall be able to view posts. [Completed]
  • 1.1.2.1.2 Guest user shall be able to view stocks. [Completed]
  • 1.1.2.1.3 Guest user shall be able to view user profiles. [In progress]
  • 1.1.2.1.4 Guest user shall be able to search for users by their usernames. [In progress]
  • 1.1.2.1.5 Guest user shall be able to semantic search for posts. [Completed
  • 1.1.2.1.6 Guest user shall be able to view recent news about financial markets. [Completed]
1.1.2.2 Registered User
  • 1.1.2.2.1 Registered users shall be able to create and edit posts. [Completed]
  • 1.1.2.2.2 Registered users shall be able to like and unlike posts. [Completed]
  • 1.1.2.2.3 Registered users shall be able to write comments to posts. [Completed]
  • 1.1.2.2.4 Registered users shall be able to follow and unfollow other users on the platform. [In progress]
  • 1.1.2.2.5 Registered users shall be able to view her/his followers. [In progress]
  • 1.1.2.2.6 Registered users should be able to add graphs to their posts. [In progress]
  • 1.1.2.2.7 Registered users shall be able to perform the same actions as guest users. [In Progress]
1.1.2.3 Admin
  • 1.1.2.3.1 An admin shall be able to ban user accounts. [Not Started]
  • 1.1.2.3.2 An admin shall be able to remove(ban) posts. [Not Started]
  • 1.1.2.3.3 An admin shall be able to remove(hide) comments on posts. [Not Started]
  • 1.1.2.3.4 An admin shall be able to remove tag. [Not Started]
1.1.3 Profile Preferences
  • 1.1.3.1 Users shall be able to view profile information. [Completed]
  • 1.1.3.2 Users shall be able to update her/his profile information. [Not Started]
  • 1.1.3.3 Users should be able to add/remove a profile photo. [Not Started]

1.2 System Requirements

1.2.1 Search
1.2.1.1 Searching
  • 1.2.1.1.1 The system shall allow users to search for users. [In progress]
  • 1.2.1.1.2 The system shall allow users to search for posts through tags, titles, author. [Completed]
  • 1.2.1.1.3 The system shall allow users to search for stocks. [Completed]
1.2.1.2 Filtering
  • 1.2.1.2.1 The system shall allow users to filter the stocks as increasing and decreasing. [Not Started]
  • 1.2.1.2.2 The system shall allow users to filter for posts according to the post's portfolio, author and author's badges. [Not Started]
1.2.2 Portfolio
  • 1.2.2.1 Portfolios should be created by the users by entering purchase price and quantity of stock. [Completed]
  • 1.2.2.2 Portfolios shall include one or more stock. [Completed]
1.2.3 News
  • 1.2.3.1 The system shall include news about stocks. [Completed]
1.2.4 Posts
  • 1.2.4.1 The system shall require registered users to add title to posts. [Completed]
  • 1.2.4.2 The system shall allow registered users to add tags to posts. [Completed]
  • 1.2.4.3 The system shall allow registered users to add their portfolios to posts. [Not Started]
  • 1.2.4.4 The system shall allow registered users to add news to posts. [Completed]
  • 1.2.4.5 The system shall allow registered users to add ideas in the form of text to posts. [Completed]
  • 1.2.4.6 The system shall allow registered users to add line charts of stocks to posts. [Completed]
  • 1.2.4.7 The system shall store author of posts. [Completed]
  • 1.2.4.8 The system shall store creation date of posts. [Completed]
  • 1.2.4.9 The system shall store last edit date of posts. [Completed]
  • 1.2.4.10 The system shall store like count of posts. [Completed]
  • 1.2.4.11 The system shall be able to list comments related to a post. [Completed]
1.2.5 Badges
  • 1.2.5.1 The system shall include badges which gain new abilities to users. [Completed]
  • 1.2.5.2 The system shall have a badge type called "High-liked". [Completed]
  • 1.2.5.3 The system shall have a badge type called "Cretager". [Completed]
1.2.6 Tags
  • 1.2.6.1 The system shall limit tag length to 40 chars. [Completed]
  • 1.2.6.2 The system shall limit the tags to be lowercase and unique. [Completed]
1.2.7 Annotations
  • 1.2.7.1 The system shall use annotations that comply with the W3C Web Annotation Data Model. [Completed]
  • 1.2.7.2 The system shall use annotations appearing in the form of a highlighted text. [Completed]
  • 1.2.7.3 The system shall allow annotations only in post bodies. [Completed]

Non-Functional Requirements

2.1 Platforms & Compatibility

  • 2.1.1 The application shall be available for Web and Mobile platforms. [Completed]
  • 2.1.2 The web application shall be available for web browsers supporting ES6. [Completed]
  • 2.1.3 The web application shall support FHD (1920x1080) or higher resolutions, ensuring that all charts and graphs are rendered at a minimum resolution of 1080p for clarity and detail. [Completed]
  • 2.1.4 The mobile application shall be available for Android(API 33 or higher) operating systems. [Completed]
  • 2.1.5 The mobile application shall support portrait orientation on mobile devices. [Completed]
  • 2.1.6 The mobile application shall support FHD or higher resolutions, with charts and graphs rendered at a minimum resolution of 720p for clear visibility. [Completed]

2.2 Supported Languages

  • 2.2.1 Application shall be available in English Language. [Completed]

2.3 Security

  • 2.3.1 User authorization credentials shall be encrypted to ensure the confidentiality of user data. [Completed]
  • 2.3.2 User login sessions shall expire after 12 hours of inactivity, requiring re-authentication to enhance security. [Completed]
  • 2.3.3 User shall verify their email addresses after signing up to ensure the validity of accounts before logging into the system. [Completed]

2.4 Privacy

  • 2.4.1 The application shall comply with KVKK. [Not Started]
  • 2.4.2 The application shall provide a comprehensive privacy policy to users, clearly outlining data collection, usage, and sharing practices, and shall require user confirmation to operate. [Not Started]

2.5 Restricted Content

  • 2.5.1 The application shall not include or promote any adult content, ensuring a safe and professional environment for users engaging with financial information. [Not Started]
  • 2.5.2 The application shall provide clear disclaimers regarding the nature of financial content, indicating the risks associated with trading and investment activities. [Not Started]
  • 2.5.3 The application shall provide clear guidelines on acceptable use of content, including prohibiting the sharing of misleading financial advice or illegal activities. [Not Started]

2.6 Performance

  • 2.6.1 The application shall load within 3 seconds under normal network conditions. [Completed]

  • 2.6.2 The application shall not be unresponsive at a maximum of 10 seconds. [Completed]

  • 2.6.3 The application shall stay responsive for up to 5000 users concurrently. [Completed]

  • API Endpoints:

    • The API documentation.
    • Link to the API.
    • Three examples of API calls corresponding to core functionality, with instructions to access them. All information needed to replicate the calls must be provided (e.g., required parameter values). Postman collections may be shared.

2.4 User Interface / User Experience:

Mobile

Links to the code in the project repository for each page. (Screenshots are in the same order)

Screenshots

- Login - Register - Forgot Password Pages

Login Register Forgot Password

- Profile Page

Profile Page

- Home Page

Home

- Community - Post - Create Post Pages

Community Post Create Post

- News Page

News

- Markets - Stock Details Pages

Markets Stock Details

- Portfolio - Portfolio Details - Create Portfolio Pages

Community Post Create Post
  • Previously submitted interfaces can be reused with new additions appended.
  • Standards: Explain the work completed towards applying W3C standards.
  • Scenarios: Provide a scenario encompassing all core functionalities of your project. Describe in detail the features and work completed to realize this scenario.

3 Individual Documentation

Cem Güngör

  • Member: Name, group, and subgroup (e.g., backend, frontend, Android).
  • Responsibilities: Overall description of assigned responsibilities.
  • Main Contributions: Description of personal contributions to the project, including:
    • Code-Related Significant Issues: Issues contributing to the code base demonstrated during the demo.
    • Management-Related Significant Issues: Issues contributing to the management of the software project.
  • Pull Requests: Personal pull requests.
  • Unit Tests: All unit tests written personally.
  • Additional Information: Further relevant information about contributions (optional).

Rukiye Aslan

  • Member: Name, group, and subgroup (e.g., backend, frontend, Android).
  • Responsibilities: Overall description of assigned responsibilities.
  • Main Contributions: Description of personal contributions to the project, including:
    • Code-Related Significant Issues: Issues contributing to the code base demonstrated during the demo.
    • Management-Related Significant Issues: Issues contributing to the management of the software project.
  • Pull Requests: Personal pull requests.
  • Unit Tests: All unit tests written personally.
  • Additional Information: Further relevant information about contributions (optional).

Furkan Şenkal-Group2-android

  • Responsibilities:

I was a member of the mobile team and primarily responsible for the Markets, Portfolio, and News pages and their components. My tasks included remaking the Markets page with backend integration and creating the Stock Details page featuring real-time graphics. I implemented the Portfolio feature for mobile, which included developing the Portfolio page to allow users to view their portfolios, creating the Portfolio Details page with a pie chart and stock addition/removal functionalities, and designing the Create Portfolio page to enable users to create new portfolios. Additionally, I added new RSS feeds to the News page and handled the navigation and coordination between these pages. I also developed unit tests for the pages I was responsible for to ensure their functionality and reliability.

  • Main contributions:

    • Remade Markets page with backend integration. Made users able to search and see real time prices of stocks .

    • Created Stock Details page with backend integration to show 1 month graphics and other specialities of the stocks.

    • Created Portfolio page to allow users to view their portfolios.

    • Created Portfolio Details page with pie chart and stock addition/removal functionalities and connected to backend.

    • Created Create Portfolio page with backend integration. Made users able to create new portfolios.

    • Added new RSS feeds prepared by backend team to the news page.

    • Created four unit tests for Markets, Stock Details, Portfolio and Portfolio Details pages.

    • Code-related significant issues:

      • Issue #537. Create new markets page.
      • Issue #538. Implement portfolio features for mobile.
      • Issue #552. Implement connection of comments with Backend issue template.
      • Issue #553. Implement connection of like/unlike with Backend .
    • Management-Related Significant Issues:

      • Issue #436. Create checklist for primary features.
      • Issue #464. Document demo scenario for Persona 1.
  • Pull Requests:

    • PR #531. Added new markets and stock details pages with backend connection
    • PR #532. Added porfolio feature with details and creation page.
    • PR #543. Added graph to stock details page.
    • PR #547. Added new RSS feeds to news page.
    • PR #548. Added unit tests for portfolio, portfolio details, markets and stock details pages.
  • Unit Tests: Personally, I have written unit tests for Portfolio, Portfolio Details, Markets and Stock Details pages.

  • Portfolio Test:
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] });
  });
});
  • Portfolio Details Test
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());
  });
});
  • Markets Test
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);
  });
});
  • Stock Details Test
import React from 'react';
import { render, waitFor } from '@testing-library/react-native';
import StockDetails from '../src/pages/StockDetails';
import { NavigationContainer } from '@react-navigation/native';

global.fetch = jest.fn();

const mockNavigation = {
    navigate: jest.fn(),
};

const mockRoute = {
    params: { id: 1 },
};

describe('StockDetails Component', () => {
    beforeEach(() => {
        jest.clearAllMocks();
    });

    test('renders correctly', () => {
        const { getByText } = render(
            <NavigationContainer>
                <StockDetails route={mockRoute} navigation={mockNavigation} />
            </NavigationContainer>
        );

        expect(getByText('Unable to load stock details.')).toBeTruthy(); // Default fallback when no data is available.
    });

    test('shows a loading indicator while fetching', async () => {
        const { getByTestId } = render(
            <NavigationContainer>
                <StockDetails route={mockRoute} navigation={mockNavigation} />
            </NavigationContainer>
        );

        expect(getByTestId('activity-indicator')).toBeTruthy();
    });

    test('fetches and displays stock details', async () => {
        const mockStockDetails = {
            name: 'Test Stock',
            symbol: 'TS',
            currency: { code: 'TRY' },
            detail: {
                currentPrice: 100,
                marketCap: 500000,
                fiftyTwoWeekHigh: 120,
                fiftyTwoWeekLow: 80,
                volume: 10000,
                averageVolume: 8000,
                open: 95,
                dayLow: 90,
                dayHigh: 105,
                sector: 'Technology',
                industry: 'Software',
                longBusinessSummary: 'This is a test stock used for testing purposes.',
            },
        };

        fetch.mockResolvedValueOnce({
            ok: true,
            json: async () => mockStockDetails,
        });

        const { getByText } = render(
            <NavigationContainer>
                <StockDetails route={mockRoute} navigation={mockNavigation} />
            </NavigationContainer>
        );

        await waitFor(() => {
            expect(getByText('Test Stock')).toBeTruthy();
            expect(getByText('TS')).toBeTruthy();
            expect(getByText('TRY 100')).toBeTruthy();
            expect(getByText('Market Cap: TRY 500000')).toBeTruthy();
            expect(getByText('52-Week High: TRY 120')).toBeTruthy();
            expect(getByText('52-Week Low: TRY 80')).toBeTruthy();
            expect(getByText('Technology')).toBeTruthy();
            expect(getByText('Software')).toBeTruthy();
            expect(getByText('This is a test stock used for testing purposes.')).toBeTruthy();
        });
    });

    test('displays error message if fetch fails', async () => {
        fetch.mockRejectedValueOnce(new Error('Fetch failed'));

        const { getByText } = render(
            <NavigationContainer>
                <StockDetails route={mockRoute} navigation={mockNavigation} />
            </NavigationContainer>
        );

        await waitFor(() => {
            expect(getByText('Unable to fetch stock details. Please try again later.')).toBeTruthy();
        });
    });

    test('hides optional fields like business summary if not available', async () => {
        const mockStockDetails = {
            name: 'Test Stock',
            symbol: 'TS',
            currency: { code: 'TRY' },
            detail: {
                currentPrice: 100,
                marketCap: 500000,
            },
        };

        fetch.mockResolvedValueOnce({
            ok: true,
            json: async () => mockStockDetails,
        });

        const { queryByText } = render(
            <NavigationContainer>
                <StockDetails route={mockRoute} navigation={mockNavigation} />
            </NavigationContainer>
        );

        await waitFor(() => {
            expect(queryByText('Business Summary')).toBeNull();
        });
    });

    test('ensures correct API call', async () => {
        const mockStockDetails = {
            name: 'Test Stock',
            symbol: 'TS',
            currency: { code: 'TRY' },
            detail: {
                currentPrice: 100,
                marketCap: 500000,
            },
        };

        fetch.mockResolvedValueOnce({
            ok: true,
            json: async () => mockStockDetails,
        });

        render(
            <NavigationContainer>
                <StockDetails route={mockRoute} navigation={mockNavigation} />
            </NavigationContainer>
        );

        await waitFor(() => {
            expect(fetch).toHaveBeenCalledWith('http://159.223.28.163:30002/stocks/1/', {
                method: 'GET',
                headers: {
                    accept: 'application/json',
                    Authorization: 'Basic ZnVya2Fuc2Vua2FsOkxvc29sdmlkYWRvcy41NQ==',
                    'X-CSRFToken': 'HN4gYGlxSnwtGKK91OG9c6WC6gr8091Pm5Kof3t0WoTHOe0Z2ToubTZUdlOkjR34',
                },
            });
        });
    });
});
  • Additional Information: I actively participated in all labs and team meetings, consistently contributing to my team and our project. Additionally, I made significant contributions to the preparation of the Milestone 3 report and deliverables by working on the status of requirements, user interface/user experience (for mobile), and the system manual (for mobile) parts.

Mahmut Buğra Mert-Group2-frontend

  • Responsibilities: I was a member of the frontend team for web development. In general, I was responsible with community page and its components. I was responsible of implementing comments, tags, like/unlike, annotation. I implemented the navigation an coordination between them. Also, I created a unit test for Assets Modal Page.

  • Main contributions:

    • Connected tags with backend. Made users able to add tags while creating posts. Displayed tags in both community and post view pages. Later, implemented filtering posts through tags.
    • Connected comments with backend. Made users able to share their comments about the posts and see other users' comments about posts.
    • Connected like/unlike with backend. Made users able to like and unlike a post. Displayed posts like number on community page.
    • Implemented annotation and connected it with backend. Made users able to enable and disable display of annotations and add their own annotations the posts' descriptions.
    • Created a unit test for Assets Modal component.
    • Code-related significant issues:
      • Issue #448. Implement tags for web.
      • Issue #452. Implement usernames and dates on posts..
      • Issue #446. Implement connection of comments with Backend issue template.
      • Issue #481. Implement connection of like/unlike with Backend .
    • Management-Related Significant Issues:
      • Issue #440. Create checklist for Testing Strategies.
      • Issue #441. Document Lab Meeting Notes #8.
      • There are also issues I created in the lab sessions to provide task division between team members and plan the subtasks of the issue. Lab8: #436, #437, #438, #439. Lab9: #464, #465, #466, #467.
  • Pull Requests:

    • PR #457. Add tags, username, and publish dates to posts.
    • PR #482. Add comments, likes. Fix tags.
    • PR #520. View tags on posts.
    • PR #551. Add annotation and filter posts by tags.
    • PR #434. Lab8
  • Unit Tests: Personally, I have written Asset Modal's unit test.

import { render, fireEvent, screen, waitFor } from "@testing-library/react";
import AssetModal from "./AssetModal";
import { StockService } from "../../service/stockService";

jest.mock("../../service/stockService", () => ({
  fetchSimilarStocks: jest.fn(),
}));

describe("AssetModal", () => {
  test("renders input fields and buttons", () => {
    render(<AssetModal onClose={jest.fn()} onSubmit={jest.fn()} />);

    // Check if the input fields and buttons are rendered
    expect(screen.getByPlaceholderText("Stock Code")).toBeInTheDocument();
    expect(screen.getByPlaceholderText("Stock Price")).toBeInTheDocument();
    expect(screen.getByPlaceholderText("Quantity")).toBeInTheDocument();
    expect(screen.getByText("Submit")).toBeInTheDocument();
    expect(screen.getByText("Cancel")).toBeInTheDocument();
  });

  test("handles stock code input and selects a stock", async () => {
    const mockStockResults = [
      { id: 1, code: "AAPL", name: "Apple", price: 150 },
      { id: 2, code: "GOOGL", name: "Google", price: 2800 },
    ];

    StockService.fetchSimilarStocks.mockResolvedValue(mockStockResults);

    render(<AssetModal onClose={jest.fn()} onSubmit={jest.fn()} />);

    const stockCodeInput = screen.getByPlaceholderText("Stock Code");

    // Simulate entering a stock code and the search function being triggered
    fireEvent.change(stockCodeInput, { target: { value: "AAPL" } });

    await waitFor(() => {
      expect(StockService.fetchSimilarStocks).toHaveBeenCalledWith("AAPL", 5);
    });

    // Check that the search results are rendered
    expect(screen.getByText("AAPL - Apple")).toBeInTheDocument();

    // Simulate selecting a stock
    fireEvent.click(screen.getByText("AAPL - Apple"));

    // Check if stock information is updated in the input fields
    expect(screen.getByPlaceholderText("Stock Code").value).toBe("AAPL");
    expect(screen.getByPlaceholderText("Stock Price").value).toBe("150");
  });

  test("calls onSubmit with correct values when submit button is clicked", async () => {
    const mockOnSubmit = jest.fn();
    const mockStockResults = [
      { id: 1, code: "AAPL", name: "Apple", price: 150 },
    ];

    StockService.fetchSimilarStocks.mockResolvedValue(mockStockResults);

    render(<AssetModal onClose={jest.fn()} onSubmit={mockOnSubmit} />);

    fireEvent.change(screen.getByPlaceholderText("Stock Code"), {
      target: { value: "AAPL" },
    });
    await waitFor(() => {
      expect(screen.getByText("AAPL - Apple")).toBeInTheDocument();
    });

    fireEvent.click(screen.getByText("AAPL - Apple"));
    fireEvent.change(screen.getByPlaceholderText("Stock Price"), {
      target: { value: "150" },
    });
    fireEvent.change(screen.getByPlaceholderText("Quantity"), {
      target: { value: "10" },
    });

    fireEvent.click(screen.getByText("Submit"));

    await waitFor(() => {
      expect(mockOnSubmit).toHaveBeenCalledWith({
        stockId: 1,
        stockCode: "AAPL",
        stockPrice: 150,
        quantity: 10,
      });
    });
  });
});
  • Additional Information: Attended all of the labs and team meetings. Tried to actively contribute my team and our project.

Kamil Deniz Coşkuner

  • Member: Name, group, and subgroup (e.g., backend, frontend, Android).
  • Responsibilities: Overall description of assigned responsibilities.
  • Main Contributions: Description of personal contributions to the project, including:
    • Code-Related Significant Issues: Issues contributing to the code base demonstrated during the demo.
    • Management-Related Significant Issues: Issues contributing to the management of the software project.
  • Pull Requests: Personal pull requests.
  • Unit Tests: All unit tests written personally.
  • Additional Information: Further relevant information about contributions (optional).

Halil İbrahim Kasapoğlu

  • Member: Name, group, and subgroup (e.g., backend, frontend, Android).
  • Responsibilities: Overall description of assigned responsibilities.
  • Main Contributions: Description of personal contributions to the project, including:
    • Code-Related Significant Issues: Issues contributing to the code base demonstrated during the demo.
    • Management-Related Significant Issues: Issues contributing to the management of the software project.
  • Pull Requests: Personal pull requests.
  • Unit Tests: All unit tests written personally.
  • Additional Information: Further relevant information about contributions (optional).

Muhammed Erkam Gökcepınar

  • Member: Name, group, and subgroup (e.g., backend, frontend, Android).
  • Responsibilities: Overall description of assigned responsibilities.
  • Main Contributions: Description of personal contributions to the project, including:
    • Code-Related Significant Issues: Issues contributing to the code base demonstrated during the demo.
    • Management-Related Significant Issues: Issues contributing to the management of the software project.
  • Pull Requests: Personal pull requests.
  • Unit Tests: All unit tests written personally.
  • Additional Information: Further relevant information about contributions (optional).

Rafet Oğuz Pançuk

  • Member: Name, group, and subgroup (e.g., backend, frontend, Android).
  • Responsibilities: Overall description of assigned responsibilities.
  • Main Contributions: Description of personal contributions to the project, including:
    • Code-Related Significant Issues: Issues contributing to the code base demonstrated during the demo.
    • Management-Related Significant Issues: Issues contributing to the management of the software project.
  • Pull Requests: Personal pull requests.
  • Unit Tests: All unit tests written personally.
  • Additional Information: Further relevant information about contributions (optional).

📋 Lab Reports

📆 Meeting Notes

🧪 Lab Meetings

🗓️ General Meetings

⚙️ Backend Meetings

📝 Milestone Reports

📑 Project Artifacts

📖 Manuals

📑 Other Artifacts

📋 Software Requirements Specification

📊 Software Design Documents

✏️ User Scenarios & Mockups

🗂 Project Plan

🧪 Unit Tests

📜 Docs

👥 Team

SemanticFlix Archieve

📝 Milestone Reports

📆 Meeting Notes

🧾 Requirements

Project Plan

📊 Diagrams

👥 Team

📝 Researches

Repository Documentations

📁 Templates

Clone this wiki locally