Skip to content

Commit

Permalink
Merge pull request #136 from miksrv/develop
Browse files Browse the repository at this point in the history
Migrate to next.js 15, added UI Unit tests
  • Loading branch information
miksrv authored Nov 2, 2024
2 parents a64bd39 + c5a0475 commit a2c412b
Show file tree
Hide file tree
Showing 16 changed files with 8,681 additions and 695 deletions.
55 changes: 52 additions & 3 deletions .github/workflows/sonarcloud.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,68 @@ on:
push:
branches:
- main
tags:
- 'v*'
pull_request:
types: [opened, synchronize, reopened]

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:
QualityGate:
sonarcloud:
if: github.event.pull_request.draft == false
name: SonarCloud
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Install Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'yarn'
cache-dependency-path: 'client/yarn.lock'

- name: Cache node modules
uses: actions/cache@v4
id: cache-npm
with:
path: |
client/node_modules
~/.npm
key: ${{ runner.os }}-modules-${{ hashFiles('yarn.lock') }}
restore-keys: |
${{ runner.os }}-modules-
${{ runner.os }}-
- if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }}
name: Install dependencies
run: yarn install
working-directory: client

- name: UI Unit Tests
run: yarn test:coverage
working-directory: client

- name: Extract version from tag or branch
id: version
run: |
if [[ "${GITHUB_REF}" == refs/tags/* ]]; then
echo "VERSION=${GITHUB_REF/refs\/tags\//}" >> $GITHUB_ENV
else
echo "VERSION=$(jq -r '.version' package.json)" >> $GITHUB_ENV
fi
- name: SonarCloud Scan
uses: SonarSource/sonarcloud-github-action@master
uses: sonarsource/sonarcloud-github-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
with:
args: >
-Dsonar.projectVersion=${{ env.VERSION }}
8 changes: 4 additions & 4 deletions .github/workflows/ui-checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ jobs:
- if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }}
name: Install dependencies
working-directory: client
run: yarn workspaces focus
working-directory: client

- name: Linter
run: yarn eslint:check
Expand All @@ -70,9 +70,9 @@ jobs:
NEXT_PUBLIC_SITE_LINK = '${{ secrets.NEXT_PUBLIC_SITE_LINK }}'" > .env
working-directory: client

# - name: UI Unit Tests
# run: yarn test
# working-directory: client
- name: UI Unit Tests
run: yarn test
working-directory: client

- if: ${{ steps.cache-build.outputs.cache-hit != 'true' }}
name: Build UI
Expand Down
Binary file modified client/.yarn/install-state.gz
Binary file not shown.
2 changes: 2 additions & 0 deletions client/.yarnrc.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
npmRegistryServer: https://registry.npmjs.org

nodeLinker: node-modules

yarnPath: .yarn/releases/yarn-4.5.0.cjs
43 changes: 43 additions & 0 deletions client/components/footer/Footer.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React from 'react'

import '@testing-library/jest-dom'

import Footer from './Footer'

import { formatDate } from '@/tools/date'
import { render, screen } from '@testing-library/react'

jest.mock('@/package.json', () => ({
name: 'TestApp',
version: '1.0.0'
}))

jest.mock('@/tools/date', () => ({
formatDate: jest.fn()
}))

jest.mock('@/update', () => new Date(2023, 0, 1, 12, 0, 0)) // 1 января 2023 года, 12:00

describe('Footer Component', () => {
it('displays the correct copyright information', () => {
;(formatDate as jest.Mock).mockImplementation((date, format) =>
format === 'YYYY' ? '2023' : '01.01.2023, 12:00'
)

render(<Footer />)

expect(screen.getByText('Copyright © TestApp 2023')).toBeInTheDocument()
})

it('displays the correct version information', () => {
;(formatDate as jest.Mock).mockImplementation((date, format) =>
format === 'DD.MM.YYYY, HH:mm' ? '01.01.2023, 12:00' : '2023'
)

render(<Footer />)

expect(screen.getByText('Version')).toBeInTheDocument()
expect(screen.getByText('1.0.0')).toBeInTheDocument()
expect(screen.getByText('(01.01.2023, 12:00)')).toBeInTheDocument()
})
})
6 changes: 4 additions & 2 deletions client/components/widget-summary/WidgetSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@ const WidgetSummary: React.FC<WidgetSummaryProps> = ({ loading, weather }) => {

<div className={styles.value}>
{loading ? (
<Skeleton style={{ width: 75, height: 75, marginTop: 10, marginRight: 15 }} />
<Skeleton
style={{ width: 75, height: 65, marginTop: 10, marginBottom: 10, marginRight: 15 }}
/>
) : (
<WeatherIcon
weatherId={weather?.weatherId as number}
Expand All @@ -49,7 +51,7 @@ const WidgetSummary: React.FC<WidgetSummaryProps> = ({ loading, weather }) => {
)}

{loading ? (
<Skeleton style={{ width: 130, height: 75, marginTop: 10 }} />
<Skeleton style={{ width: 130, height: 65, marginTop: 10, marginBottom: 10 }} />
) : (
<div className={styles.temperature}>
{round(weather?.temperature || 0, 1)}
Expand Down
36 changes: 36 additions & 0 deletions client/components/wind-direction-icon/WindDirectionIcon.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react'

import '@testing-library/jest-dom'

import styles from './styles.module.sass'
import WindDirectionIcon from './WindDirectionIcon'

import { render } from '@testing-library/react'

describe('WindDirectionIcon Component', () => {
it('renders SVG element with correct viewBox attribute', () => {
const { container } = render(<WindDirectionIcon />)
const svgElement = container.querySelector('svg')
expect(svgElement).toBeInTheDocument()
expect(svgElement).toHaveAttribute('viewBox', '0 0 30 30')
})

it('applies default rotation when direction is not provided', () => {
const { container } = render(<WindDirectionIcon />)
const svgElement = container.querySelector('svg')
expect(svgElement).toHaveStyle('transform: rotate(0deg)')
})

it('applies correct rotation based on direction prop', () => {
const testDirection = 45
const { container } = render(<WindDirectionIcon direction={testDirection} />)
const svgElement = container.querySelector('svg')
expect(svgElement).toHaveStyle(`transform: rotate(${testDirection}deg)`)
})

it('applies correct CSS class for styling', () => {
const { container } = render(<WindDirectionIcon />)
const svgElement = container.querySelector('svg')
expect(svgElement).toHaveClass(styles.weatherIcon)
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const WindDirectionIcon: React.FC<WindDirectionIconProps> = ({ direction }) => (
<svg
viewBox='0 0 30 30'
className={styles.weatherIcon}
style={{ transform: `rotate(${direction}deg)` }}
style={{ transform: `rotate(${direction || 0}deg)` }}
>
<path
d='M3.74,14.5c0-2.04,0.51-3.93,1.52-5.66s2.38-3.1,4.11-4.11s3.61-1.51,5.64-1.51c1.52,0,2.98,0.3,4.37,0.89
Expand Down
56 changes: 17 additions & 39 deletions client/jest.config.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,25 @@
import type { Config } from '@jest/types'
import type { Config } from 'jest'

const config: Config.InitialOptions = {
collectCoverage: true,
collectCoverageFrom: [
'**/*.{js,jsx,ts,tsx}',
'!**/*.d.ts',
'!**/node_modules/**',
'!<rootDir>/out/**',
'!<rootDir>/.next/**',
'!<rootDir>/*.config.js',
'!<rootDir>/coverage/**'
],
coverageProvider: 'v8',
globals: {
'ts-jest': {
tsconfig: 'tsconfig.node.json'
}
},
const config: Config = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
moduleNameMapper: {
'^.+\\.(png|jpg|jpeg|gif|webp|avif|ico|bmp|svg)$': 'identity-obj-proxy',

// Handle CSS imports (with CSS modules)
// https://jestjs.io/docs/webpack#mocking-css-modules
'^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy',

// Handle module aliases
'^@/(.*)$': '<rootDir>/$1',
'^@/api/(.*)$': '<rootDir>/api/$1',
'^@/components/(.*)$': '<rootDir>/components/$1',
'^@/functions/(.*)$': '<rootDir>/functions/$1',
'^@/public/(.*)$': '<rootDir>/public/$1',
'^@/styles/(.*)$': '<rootDir>/styles/$1'
'\\.(css|sass|scss)$': 'identity-obj-proxy',
'\\.(jpg|jpeg|png)$': 'identity-obj-proxy',
'^@/(.*)$': '<rootDir>/$1'
},
setupFilesAfterEnv: ['<rootDir>/setupTests.config.tsx'],
silent: true, // hide all warnings
testEnvironment: 'jsdom',
testPathIgnorePatterns: ['<rootDir>/node_modules/', '<rootDir>/.next/'],
transform: {
// Use babel-jest to transpile tests with the next/babel preset
// https://jestjs.io/docs/configuration#transform-objectstring-pathtotransformer--pathtotransformer-object
'^.+\\.(js|jsx|ts|tsx)$': ['babel-jest', { presets: ['next/babel'] }]
'^.+\\.tsx?$': [
'ts-jest',
{
babel: true,
tsconfig: 'tsconfig.jest.json'
}
]
},
transformIgnorePatterns: ['/node_modules/', '^.+\\.module\\.(css|sass|scss)$']
collectCoverageFrom: ['components/**/*.{ts,tsx}', '!components/**/*.d.ts', '!components/**/*.test.tsx', '!*.d.ts'],
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
transformIgnorePatterns: ['node_modules/(?!(module-to-transform)/)', '/.next/']
}

export default config
15 changes: 2 additions & 13 deletions client/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,10 @@ const nextConfig = {
// size, or format. Defaults to false.
unoptimized: false
},
output: 'standalone',

transpilePackages: ['@uiw/react-md-editor', 'leaflet', 'leaflet.heat'],

webpack(config) {
config.resolve.fallback = {
// if you miss it, all the other options in fallback, specified
// by next.js will be dropped.
...config.resolve.fallback,

fs: false // the solution
}
output: 'standalone',

return config
}
transpilePackages: ['echarts']
}

module.exports = nextConfig
Loading

0 comments on commit a2c412b

Please sign in to comment.