-
Notifications
You must be signed in to change notification settings - Fork 0
Basic testing done with github actions #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
f8de2df
0692dbc
1047b7f
7f6162f
2c51162
64e625f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| name: CI | ||
|
|
||
| on: | ||
| push: | ||
| branches: [main, master, feature/*] | ||
| pull_request: | ||
| branches: [main, master] | ||
|
|
||
| jobs: | ||
| server-tests: | ||
| name: Server tests | ||
| runs-on: ubuntu-latest | ||
| defaults: | ||
| run: | ||
| working-directory: server/market-trading-service | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Use Node.js 20 | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: "20" | ||
|
|
||
| - name: Cache server node modules | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: server/market-trading-service/node_modules | ||
| key: ${{ runner.os }}-server-${{ hashFiles('server/market-trading-service/package-lock.json') }} | ||
| restore-keys: | | ||
| ${{ runner.os }}-server- | ||
|
|
||
| - name: Install server dependencies | ||
| run: npm ci | ||
|
|
||
| - name: Run server tests | ||
| run: npm test --silent | ||
|
|
||
| client-tests: | ||
| name: Client tests (conditional) | ||
| runs-on: ubuntu-latest | ||
| needs: server-tests | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Detect client test script | ||
| id: detect_client_tests | ||
| run: | | ||
| set -e | ||
| PKG=client/trading-dashboard/package.json | ||
| if [ -f "$PKG" ] && grep -q '"test"' "$PKG"; then | ||
| echo "has_tests=true" >> $GITHUB_OUTPUT | ||
| else | ||
| echo "has_tests=false" >> $GITHUB_OUTPUT | ||
| fi | ||
|
|
||
| - name: Use Node.js 20 | ||
| if: steps.detect_client_tests.outputs.has_tests == 'true' | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: "20" | ||
|
|
||
| - name: Cache client node modules | ||
| if: steps.detect_client_tests.outputs.has_tests == 'true' | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: client/trading-dashboard/node_modules | ||
| key: ${{ runner.os }}-client-${{ hashFiles('client/trading-dashboard/package-lock.json') }} | ||
| restore-keys: | | ||
| ${{ runner.os }}-client- | ||
|
|
||
| - name: Install client dependencies | ||
| if: steps.detect_client_tests.outputs.has_tests == 'true' | ||
| run: | | ||
| cd client/trading-dashboard | ||
| npm ci | ||
|
|
||
| - name: Run client tests | ||
| if: steps.detect_client_tests.outputs.has_tests == 'true' | ||
| run: | | ||
| cd client/trading-dashboard | ||
| npm test --silent |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| name: E2E (Cypress) | ||
|
|
||
| on: | ||
| push: | ||
| branches: [main, master, feature/*] | ||
| pull_request: | ||
| branches: [main, master] | ||
|
|
||
| jobs: | ||
| cypress-run: | ||
| runs-on: ubuntu-latest | ||
| timeout-minutes: 20 | ||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: Setup Node 20 | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: "20" | ||
|
|
||
| - name: Cache client deps | ||
| uses: actions/cache@v4 | ||
| with: | ||
| path: client/trading-dashboard/node_modules | ||
| key: ${{ runner.os }}-client-e2e-${{ hashFiles('client/trading-dashboard/package-lock.json') }} | ||
| restore-keys: | | ||
| ${{ runner.os }}-client-e2e- | ||
|
|
||
| - name: Install client deps & build | ||
| working-directory: client/trading-dashboard | ||
| run: | | ||
| npm ci | ||
| npm run build | ||
|
|
||
| - name: Start client & run Cypress (no backend) | ||
| uses: cypress-io/github-action@v6 | ||
| with: | ||
| start: npm --prefix client/trading-dashboard start | ||
| wait-on: "http://localhost:3000" | ||
| wait-on-timeout: 120 | ||
| browser: chrome | ||
| spec: client/trading-dashboard/cypress/e2e/**/*.cy.ts | ||
| env: | ||
| # Point to an unreachable host so fetch fails and client falls back to MOCK_TICKERS | ||
| NEXT_PUBLIC_MARKET_TRADING_URL: http://127.0.0.1:59999 | ||
| CYPRESS_BASE_URL: http://localhost:3000 | ||
|
|
||
| - name: Upload Cypress videos/screenshots (if failed) | ||
| if: failure() | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: cypress-artifacts | ||
| path: | | ||
| client/trading-dashboard/cypress/videos/** | ||
| client/trading-dashboard/cypress/screenshots/** | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,56 @@ | ||
| # multi-bank-coding-challenge | ||
| Full Stack real-time trading dashboard | ||
|
|
||
| Full-stack real-time trading dashboard used for the Multi Bank coding challenge. This repository contains two main projects and supporting documentation. | ||
|
|
||
| Project layout | ||
|
|
||
| - `client/trading-dashboard` — Next.js frontend (UI, E2E + unit tests). See: `client/trading-dashboard/README.md` and `client/trading-dashboard/README.md` for developer instructions. | ||
| - `server/market-trading-service` — Node + TypeScript microservice that simulates market data and exposes a small REST API. See: `server/market-trading-service/README.md`. | ||
| - `docs/` — architecture and project-scope documentation. | ||
| - `docker-compose.yml` & `README.DOCKER.md` — Docker setup for running both services together. | ||
|
|
||
| Quick start (recommended: Docker) | ||
|
|
||
| 1. From the repository root, build and start both services with docker-compose: | ||
|
|
||
| ```bash | ||
| docker-compose build | ||
| docker-compose up | ||
| ``` | ||
|
|
||
| This will start: | ||
|
|
||
| - Frontend: http://localhost:3000 | ||
| - Backend API: http://localhost:3005 (health endpoint: `/health`) | ||
|
|
||
| Local development (without Docker) | ||
|
|
||
| - Frontend: | ||
|
|
||
| ```bash | ||
| cd client/trading-dashboard | ||
| npm install | ||
| npm run dev | ||
| ``` | ||
|
|
||
| - Backend: | ||
|
|
||
| ```bash | ||
| cd server/market-trading-service | ||
| npm install | ||
| npm run dev | ||
| ``` | ||
|
|
||
| Tests | ||
|
|
||
| - Frontend unit tests: run in `client/trading-dashboard` with `npm run test` (Jest) | ||
| - Frontend E2E: run Cypress after starting the frontend (see `client/trading-dashboard/cypress.config.ts`) | ||
|
|
||
| Notes | ||
|
|
||
| - Each subproject includes its own README with more detailed developer and testing instructions. If you plan to contribute, please follow the subproject README before opening a PR. | ||
| - If you want CI/CD integration, I can add GitHub Actions workflows that run unit tests and optional Cypress E2E tests. | ||
|
|
||
| License | ||
|
|
||
| This project is available under the repository LICENSE file. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| import { render, screen } from "@testing-library/react"; | ||
| import Index from "../page"; | ||
| // IMPORTANT: mock child components BEFORE importing the page so the page uses the mocked versions. | ||
| jest.mock("@/components/Hero", () => ({ | ||
| __esModule: true, | ||
| default: () => <div data-testid="hero">Hero Component</div>, | ||
| })); | ||
|
|
||
| jest.mock("@/components/TickerGrid", () => ({ | ||
| __esModule: true, | ||
| default: () => <div data-testid="ticker-grid">TickerGrid Component</div>, | ||
| })); | ||
|
|
||
| jest.mock("@/components/NewsFeed", () => ({ | ||
| __esModule: true, | ||
| default: () => <div data-testid="news-feed">NewsFeed Component</div>, | ||
| })); | ||
|
|
||
| describe("Homepage (Index)", () => { | ||
| it("renders all main sections: Hero, TickerGrid, and NewsFeed", () => { | ||
| render(<Index />); | ||
| expect(screen.getByTestId("hero")).toBeInTheDocument(); | ||
| expect(screen.getByTestId("ticker-grid")).toBeInTheDocument(); | ||
| expect(screen.getByTestId("news-feed")).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it("has correct layout structure with min-h-screen and bg-background", () => { | ||
| const { container } = render(<Index />); | ||
| const mainDiv = container.querySelector(".min-h-screen.bg-background"); | ||
| expect(mainDiv).toBeInTheDocument(); | ||
| }); | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -49,7 +49,7 @@ const NewsFeed = () => { | |
| }, | ||
| { | ||
| title: "Energy Sector Stocks Rise on Supply Chain Improvements", | ||
| source: "Financial Times", | ||
| source: "The Guardian", | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Critical: Test will fail due to inconsistent data. The news source was changed from "Financial Times" to "The Guardian", but the test file at Apply this fix to the test file: - expect(screen.getByText("Financial Times")).toBeInTheDocument();
+ expect(screen.getByText("The Guardian")).toBeInTheDocument();Alternatively, revert this change to keep "Financial Times" if there was no intentional reason for the change.
🤖 Prompt for AI Agents |
||
| time: "10 hours ago", | ||
| category: "Energy", | ||
| url: "#", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| import React from "react"; | ||
| import { render, screen } from "@testing-library/react"; | ||
| import Hero from "../Hero"; | ||
|
|
||
| describe("Hero", () => { | ||
| it('renders the main heading with "Real-Time Market Intelligence"', () => { | ||
| render(<Hero />); | ||
|
|
||
| expect(screen.getByText("Real-Time Market")).toBeInTheDocument(); | ||
| expect(screen.getByText("Intelligence")).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it("displays the Live Market Data badge", () => { | ||
| render(<Hero />); | ||
|
|
||
| expect(screen.getByText("Live Market Data")).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it("shows the tagline description", () => { | ||
| render(<Hero />); | ||
|
|
||
| expect( | ||
| screen.getByText(/Stay ahead with live ticker updates/i) | ||
| ).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it("displays feature cards with Live and 24/7 stats", () => { | ||
| render(<Hero />); | ||
|
|
||
| expect(screen.getByText("Live")).toBeInTheDocument(); | ||
| expect(screen.getByText("Price Updates")).toBeInTheDocument(); | ||
| expect(screen.getByText("24/7")).toBeInTheDocument(); | ||
| expect(screen.getByText("Market Coverage")).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it("has proper section structure with gradient background", () => { | ||
| const { container } = render(<Hero />); | ||
|
|
||
| const section = container.querySelector("section"); | ||
| expect(section).toHaveClass("bg-gradient-to-br"); | ||
| }); | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Next.js env vars must be set during build.
Next.js bakes
NEXT_PUBLIC_*environment variables at build time, not runtime. SettingNEXT_PUBLIC_MARKET_TRADING_URLin the Cypress step (Line 46) won't affect the already-built application.Apply this diff to set the environment variable during the build:
- name: Install client deps & build working-directory: client/trading-dashboard + env: + NEXT_PUBLIC_MARKET_TRADING_URL: http://127.0.0.1:59999 run: | npm ci npm run buildThen update the Cypress step to remove the redundant env var from there since it's now baked into the build.
📝 Committable suggestion
🤖 Prompt for AI Agents