Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/OWASP/Nest into cleanup-dep…
Browse files Browse the repository at this point in the history
…endencies
  • Loading branch information
shining-bluemoon-11 committed Jan 25, 2025
2 parents 623a80e + 342b980 commit e92689e
Show file tree
Hide file tree
Showing 36 changed files with 2,367 additions and 1,877 deletions.
6 changes: 6 additions & 0 deletions .github/ansible/production/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,9 @@
- name: Retart services
shell:
cmd: docker compose up -d

- name: Index data
async: 1800 # 30 minutes
poll: 0
shell: |
make index-data > /var/log/nest/index-data.log 2>&1
6 changes: 6 additions & 0 deletions .github/ansible/staging/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,9 @@
- name: Retart services
shell:
cmd: docker compose up -d

- name: Index data
async: 1800 # 30 minutes
poll: 0
shell: |
make index-data > /var/log/nest/index-data.log 2>&1
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ __pycache__
.python-version
.ruff_cache
.vscode
venv/
*.code-workspace
*.local
*.log
Expand Down
1 change: 0 additions & 1 deletion backend/apps/slack/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ class SlackConfig(AppConfig):

app = (
App(
request_verification_enabled=False,
signing_secret=settings.SLACK_SIGNING_SECRET,
token=settings.SLACK_BOT_TOKEN,
)
Expand Down
209 changes: 152 additions & 57 deletions backend/poetry.lock

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ omit = [
]

[tool.poetry.dependencies]
algoliasearch = "^4.12.0"
algoliasearch = "^4.13.0"
algoliasearch-django = "^4.0.0"
django = "^5.1"
django-configurations = "^2.5.1"
Expand All @@ -34,7 +34,7 @@ gunicorn = "^23.0.0"
humanize = "^4.11.0"
lxml = "^5.3.0"
markdown = "^3.7"
openai = "^1.59.9"
openai = "^1.60.0"
psycopg = "^3.2.4"
pygithub = "^2.5.0"
python = "^3.13"
Expand All @@ -48,7 +48,7 @@ slack-bolt = "^1.22.0"
djlint = "^1.36.4"
isort = "^5.13.2"
pre-commit = "^4.1.0"
ruff = "^0.9.2"
ruff = "^0.9.3"

[tool.poetry.group.test.dependencies]
pytest = "^8.3.4"
Expand Down
55 changes: 55 additions & 0 deletions frontend/__tests__/src/data/mockChapterDetailsData.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
export const mockChaterDetailsData = {
name: 'OWASP Test Chapter',
suggested_location: 'Test City, Test Country',
region: 'Test Region',
is_active: true,
tags: 'test-tag',
updated_at: 1652129718,
url: 'https://owasp.org/test-chapter',
related_urls: [
'https://discord.com/test',
'https://www.instagram.com/test',
'https://www.linkedin.com/test',
'https://www.youtube.com/test',
'https://twitter.com/test',
'https://meetup.com/test',
],
summary: 'This is a test chapter summary.',
top_contributors: [
{
avatar_url: 'https://example.com/avatar1.jpg',
name: 'Contributor 1',
contributions_count: 10,
},
{
avatar_url: 'https://example.com/avatar2.jpg',
name: 'Contributor 2',
contributions_count: 8,
},
{
avatar_url: 'https://example.com/avatar3.jpg',
name: 'Contributor 3',
contributions_count: 6,
},
{
avatar_url: 'https://example.com/avatar4.jpg',
name: 'Contributor 4',
contributions_count: 4,
},
{
avatar_url: 'https://example.com/avatar5.jpg',
name: 'Contributor 5',
contributions_count: 2,
},
{
avatar_url: 'https://example.com/avatar6.jpg',
name: 'Contributor 6',
contributions_count: 1,
},
{
avatar_url: 'https://example.com/avatar7.jpg',
name: 'Contributor 7',
contributions_count: 1,
},
],
}
77 changes: 60 additions & 17 deletions frontend/__tests__/src/pages/ChapterDetails.test.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,24 @@
import { screen, waitFor } from '@testing-library/react'

import { fetchAlgoliaData } from 'api/fetchAlgoliaData'
import { ChapterDetailsPage } from 'pages'
import { render } from 'wrappers/testUtil'
import { mockChaterDetailsData } from '@tests/data/mockChapterDetailsData'
jest.mock('api/fetchAlgoliaData')

import { mockChapterData } from '@tests/data/mockChapterData'

jest.mock('api/fetchAlgoliaData', () => ({
fetchAlgoliaData: jest.fn(),
}))
jest.mock('react-router-dom', () => ({
...jest.requireActual('react-router-dom'),
useNavigate: jest.fn(),
useParams: () => ({
chapterKey: 'test-chapter',
}),
}))

describe('ChapterDetailsPage Component', () => {
describe('chapterDetailsPage Component', () => {
beforeEach(() => {
;(fetchAlgoliaData as jest.Mock).mockResolvedValue({
hits: mockChapterData.chapters,
totalPages: 2,
})
;(fetchAlgoliaData as jest.Mock).mockImplementation(() =>
Promise.resolve({
hits: [mockChaterDetailsData],
})
)
})

afterEach(() => {
Expand All @@ -37,18 +36,62 @@ describe('ChapterDetailsPage Component', () => {
test('renders chapter data correctly', async () => {
render(<ChapterDetailsPage />)
await waitFor(() => {
expect(screen.getByText('Chapter 1')).toBeInTheDocument()
expect(screen.getByText('Test City, Test Country')).toBeInTheDocument()
})
expect(screen.getByText('This is a summary of Chapter 1.')).toBeInTheDocument()
const viewButton = screen.getByText('Join')
expect(viewButton).toBeInTheDocument()
expect(screen.getByText('Test Region')).toBeInTheDocument()
expect(screen.getByText('Test-tag')).toBeInTheDocument()
expect(screen.getByText('https://owasp.org/test-chapter')).toBeInTheDocument()
expect(screen.getByText('This is a test chapter summary.')).toBeInTheDocument()
})

test('displays "Chapter not found" when there are no chapters', async () => {
test('displays "No chapters found" when there are no chapters', async () => {
;(fetchAlgoliaData as jest.Mock).mockResolvedValue({ hits: [], totalPages: 0 })
render(<ChapterDetailsPage />)
await waitFor(() => {
expect(screen.getByText('Chapter not found')).toBeInTheDocument()
})
})

test('contributors visibility check', async () => {
render(<ChapterDetailsPage />)
await waitFor(() => {
expect(screen.getByText('Contributor 1')).toBeInTheDocument()
})
expect(screen.queryByText('Contributor 7')).not.toBeInTheDocument()
})

test('renders chapter URL as clickable link', async () => {
render(<ChapterDetailsPage />)

await waitFor(() => {
const link = screen.getByText('https://owasp.org/test-chapter')
expect(link.tagName).toBe('A')
expect(link).toHaveAttribute('href', 'https://owasp.org/test-chapter')
})
})

test('handles contributors with missing names gracefully', async () => {
const chapterDataWithIncompleteContributors = {
...mockChaterDetailsData,
top_contributors: [
{
name: 'user1',
avatar_url: 'https://example.com/avatar1.jpg',
contributions_count: 30,
},
],
}

;(fetchAlgoliaData as jest.Mock).mockImplementation(() =>
Promise.resolve({
hits: [chapterDataWithIncompleteContributors],
})
)

render(<ChapterDetailsPage />)

await waitFor(() => {
expect(screen.getByText('user1')).toBeInTheDocument()
})
})
})
21 changes: 20 additions & 1 deletion frontend/__tests__/src/pages/ProjectDetails.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import { within } from '@testing-library/dom'
import { screen, waitFor, fireEvent } from '@testing-library/react'
import { fetchAlgoliaData } from 'api/fetchAlgoliaData'
import { useNavigate } from 'react-router-dom'
import { formatDate } from 'utils/dateFormatter'
import { render } from 'wrappers/testUtil'
import ProjectDetailsPage, { formatDate } from 'pages/ProjectDetails'
import ProjectDetailsPage from 'pages/ProjectDetails'
import { mockProjectDetailsData } from '@tests/data/mockProjectDetailsData'
jest.mock('api/fetchAlgoliaData')

Expand All @@ -27,6 +28,24 @@ describe('ProjectDetailsPage', () => {
afterEach(() => {
jest.clearAllMocks()
})
test('renders loading spinner initially', async () => {
render(<ProjectDetailsPage />)
const loadingSpinner = screen.getAllByAltText('Loading indicator')
await waitFor(() => {
expect(loadingSpinner.length).toBeGreaterThan(0)
})
})

test('renders project data correctly', async () => {
render(<ProjectDetailsPage />)
await waitFor(() => {
expect(screen.getByText('Test Project')).toBeInTheDocument()
})
expect(screen.getByText('This is a test project description')).toBeInTheDocument()
expect(screen.getByText('Tool')).toBeInTheDocument()
expect(screen.getByText('Flagship')).toBeInTheDocument()
expect(screen.getByText('OWASP')).toBeInTheDocument()
})

test('displays error when project is not found', async () => {
;(fetchAlgoliaData as jest.Mock).mockImplementationOnce(() => Promise.resolve({ hits: [] }))
Expand Down
Loading

0 comments on commit e92689e

Please sign in to comment.