Skip to content

Commit

Permalink
Merge branch 'master' of github.com:sashko9807/podkrepibg-frontend in…
Browse files Browse the repository at this point in the history
…to new-campaign-statuses
  • Loading branch information
sashko9807 committed Dec 7, 2024
2 parents aab5886 + 62de3c5 commit 3c418af
Show file tree
Hide file tree
Showing 28 changed files with 224 additions and 80 deletions.
18 changes: 18 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -904,6 +904,24 @@
"contributions": [
"code"
]
},
{
"login": "nikolay-yankov",
"name": "Nikolay Yankov",
"avatar_url": "https://avatars.githubusercontent.com/u/36303598?v=4",
"profile": "https://github.com/nikolay-yankov",
"contributions": [
"code"
]
},
{
"login": "katina-anachkova",
"name": "Katina Anachkova",
"avatar_url": "https://avatars.githubusercontent.com/u/82702355?v=4",
"profile": "https://github.com/katina-anachkova",
"contributions": [
"code"
]
}
],
"contributorsPerLine": 10,
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/playwright.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ jobs:
name: playwright-report
path: ./frontend/e2e/test-results/
retention-days: 14
overwrite: true

- uses: actions/upload-artifact@v4
if: always()
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,9 @@ Watch releases of this repository to be notified about future updates:
## Contributors ✨

<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-84-orange.svg?style=flat-square)](#contributors-)

[![All Contributors](https://img.shields.io/badge/all_contributors-86-orange.svg?style=flat-square)](#contributors-)

<!-- ALL-CONTRIBUTORS-BADGE:END -->

Please check [contributors guide](https://github.com/podkrepi-bg/frontend/blob/master/CONTRIBUTING.md) for:
Expand Down Expand Up @@ -226,6 +228,8 @@ Thanks goes to these wonderful people:
<td align="center" valign="top" width="10%"><a href="https://martbul.github.io/MartinKovachki/"><img src="https://avatars.githubusercontent.com/u/99181339?v=4?s=100" width="100px;" alt="Martin Kovachki"/><br /><sub><b>Martin Kovachki</b></sub></a><br /><a href="https://github.com/podkrepi-bg/frontend/commits?author=Martbul" title="Code">💻</a> <a href="https://github.com/podkrepi-bg/frontend/commits?author=Martbul" title="Tests">⚠️</a></td>
<td align="center" valign="top" width="10%"><a href="https://github.com/viiktorstefanov"><img src="https://avatars.githubusercontent.com/u/122864734?v=4?s=100" width="100px;" alt="Viktor Stefanov"/><br /><sub><b>Viktor Stefanov</b></sub></a><br /><a href="https://github.com/podkrepi-bg/frontend/commits?author=viiktorstefanov" title="Code">💻</a></td>
<td align="center" valign="top" width="10%"><a href="https://github.com/velnachev"><img src="https://avatars.githubusercontent.com/u/60844919?v=4?s=100" width="100px;" alt="velnachev"/><br /><sub><b>velnachev</b></sub></a><br /><a href="https://github.com/podkrepi-bg/frontend/commits?author=velnachev" title="Code">💻</a></td>
<td align="center" valign="top" width="10%"><a href="https://github.com/nikolay-yankov"><img src="https://avatars.githubusercontent.com/u/36303598?v=4?s=100" width="100px;" alt="Nikolay Yankov"/><br /><sub><b>Nikolay Yankov</b></sub></a><br /><a href="https://github.com/podkrepi-bg/frontend/commits?author=nikolay-yankov" title="Code">💻</a></td>
<td align="center" valign="top" width="10%"><a href="https://github.com/katina-anachkova"><img src="https://avatars.githubusercontent.com/u/82702355?v=4?s=100" width="100px;" alt="Katina Anachkova"/><br /><sub><b>Katina Anachkova</b></sub></a><br /><a href="https://github.com/podkrepi-bg/frontend/commits?author=katina-anachkova" title="Code">💻</a></td>
</tr>
</tbody>
</table>
Expand Down
21 changes: 21 additions & 0 deletions e2e/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,24 @@ Options:
```shell
yarn test:e2e --headed --debug -x -g support
```
### Tests with Authenticated user
### Writing
To auth a user we rely on the Storage where the session is stored. And the storage is filled in and accessed via a `test.extend` [fixture](https://playwright.dev/docs/auth#authenticate-with-api-request). It takes care to login and store the session and then use it in the tests. See the `e2e/utils/fixtures.ts` file
This is the process for writing tests for auth user.
- import the desired user `test` from the fixture
`import { expect, giverTest as test } from '../../../utils/fixtures'` for the `giver` user
- write your e2e tests ...
> [Examples] `e2e/tests/regression/campaign-application/campaign-application-giver.spec.ts` and `e2e/tests/regression/campaign-application/campaign-application-admin.spec.ts`
### Running
- [Locally] run the 'docker compose -d keycloak pg-db', the api (`yarn dev` in the api repo folder), the app (`yarn dev` in the frontend repo folder),
- in the `frontend/e2e` folder run `yarn e2e:tests --ui` to start the playwright visual testing tool
2 changes: 1 addition & 1 deletion e2e/pages/web-pages/donation/donation.page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export class DonationPage extends CampaignsPage {
bgLocalizationValidation['informed-agree-with'] + ' ' + bgLocalizationValidation.gdpr
private readonly enPrivacyCheckboxText =
enLocalizationValidation['informed-agree-with'] + ' ' + enLocalizationValidation.gdpr
private readonly bgStripeErrorNoBalanceText = 'Картата Ви не разполага с достатъчно средства.'
private readonly bgStripeErrorNoBalanceText = 'В картата ви няма достатъчно средства. Опитайте с друга.'

async checkPageUrlByRegExp(urlRegExpAsString?: string, timeoutParam = 10000): Promise<void> {
await this.page.waitForTimeout(1000)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
import {
CampaignApplicationResponse,
CampaignApplicationExisting,
CampaignApplicationAdminResponse,
} from '../../../../src/gql/campaign-applications'
import { Page } from 'playwright/test'
import { expect, giverTest as test } from '../../../utils/fixtures'
import { textLocalized } from '../../../utils/texts-localized'
Expand Down Expand Up @@ -169,6 +164,41 @@ test.describe('Campaign application giver', () => {
await expect(page.getByText(t.steps.application['campaign-end'].options.funds)).toBeVisible()
await expect(page.getByText('goal')).toBeVisible()
})

test('should see the edit campaign application and be able to delete a selected file ', async ({
page,
baseURL,
}) => {
// arrange
await setupMeAndCampaignTypes(page)
await setupCampaignApplicationForEdit(page)
await page.goto(`${baseURL}/campaigns/application/1234`)
const t = await textLocalized().campaign.bg()
await page.getByRole('button', { name: t.cta.next }).click()
await page.getByRole('button', { name: t.cta.next }).click()

// expect to see 2 files
await expect(page.getByText('1234.txt')).toBeVisible()
await expect(page.getByText('document.pdf')).toBeVisible()

// act
// hit the delete button ...
await page.locator('li').filter({ hasText: '1234.txt' }).getByLabel('delete').click()
const [editCamAppReq, fileDeleteReq] = await Promise.all([
// the edit request to edit the CamApp entity
page.waitForRequest((r) => r.method() === 'PATCH'),
// the delete request to remove one of the files
page.waitForRequest((r) => r.method() === 'DELETE'),
// ... and when submit
page.getByRole('button', { name: t.cta.submit }).click(),
])

await expect(editCamAppReq.postDataJSON()).toBeDefined()

const fileDelRes = await fileDeleteReq.response()

await expect(fileDelRes?.json()).resolves.toEqual({ id: 'ok' })
})
})

function defaultCampaignApplication() {
Expand Down Expand Up @@ -222,13 +252,52 @@ async function setupMeAndCampaignTypes(page: Page) {
},
{
id: '34b501f0-b3c3-43d9-9be0-7f7258eeb247',
name: 'Membership',
slug: 'membership',
description: 'Membership Campaigns',
name: 'Elderly',
slug: 'elderly',
description: 'Help elderly people',
parentId: null,
category: 'others',
},
],
}),
)
}

async function setupCampaignApplicationForEdit(
page: Page,
application: Partial<ReturnType<typeof defaultCampaignApplication>> = {},
) {
await page.route('*/**/api/v1/campaign-application/byId/*', (req) =>
req.fulfill({
json: {
...defaultCampaignApplication(),
id: 'forEdit',
documents: [
{ filename: '1234.txt', id: '1234' },
{ filename: 'document.pdf', id: 'doc-id-123123' },
],
...application,
},
}),
)

// on submit at the end of edit this patch request needs to be sent
await page.route('*/**/api/v1/campaign-application/forEdit', (req) =>
req.fulfill({
json: {
...defaultCampaignApplication(),
id: 'forEdit',
...application,
},
}),
)

// delete file successful
await page.route('*/**/api/v1/campaign-application/fileById/*', (req) =>
req.fulfill({
json: {
id: 'ok',
},
}),
)
}
4 changes: 4 additions & 0 deletions e2e/utils/fixtures.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* This is logic for authenticating and storing the session to be used in the tests. See the e2e/Readme.md - the section about Authenticated user
*/

import { test, test as base } from '@playwright/test'
import dotenv from 'dotenv'
import fs from 'fs'
Expand Down
6 changes: 3 additions & 3 deletions e2e/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -235,13 +235,13 @@ __metadata:
linkType: hard

"cross-spawn@npm:^7.0.0":
version: 7.0.3
resolution: "cross-spawn@npm:7.0.3"
version: 7.0.6
resolution: "cross-spawn@npm:7.0.6"
dependencies:
path-key: ^3.1.0
shebang-command: ^2.0.0
which: ^2.0.1
checksum: 671cc7c7288c3a8406f3c69a3ae2fc85555c04169e9d611def9a675635472614f1c0ed0ef80955d5b6d4e724f6ced67f0ad1bb006c2ea643488fcfef994d7f52
checksum: 8d306efacaf6f3f60e0224c287664093fa9185680b2d195852ba9a863f85d02dcc737094c6e512175f8ee0161f9b87c73c6826034c2422e39de7d6569cf4503b
languageName: node
linkType: hard

Expand Down
2 changes: 1 addition & 1 deletion public/locales/bg/donation-flow.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
},
"noregister": {
"label": "Продължете без регистрация ",
"description": "Продължавайки без регистрация, нямате възможност да запазите дарението в историята на профила си както и да правите месечни дарения по избрана кампания"
"description": "Продължавайки без регистрация, нямате възможност да запазите дарението в историята на профила си както и да правите месечни дарения по избрана кампания."
},
"field": {
"password": "Парола",
Expand Down
6 changes: 3 additions & 3 deletions public/locales/en/donation-flow.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
},
"card-data": {
"name-label": "Cardholder name",
"error": {
"errors": {
"email": "Please enter your email",
"name": "Please enter your name"
}
Expand Down Expand Up @@ -106,7 +106,7 @@
},
"noregister": {
"label": "Continue without registration",
"description": "You will not be able to get a donation certificate or a list of your donations. If you still want to receive a receipt, please share your email - it will not be visible in the platform"
"description": "You will not be able to get a donation certificate or a list of your donations. If you still want to receive a receipt, please share your email - it will not be visible in the platform."
},
"field": {
"password": "Password",
Expand All @@ -128,7 +128,7 @@
"donation": "Donation",
"transaction": {
"title": "Transaction",
"description": "The transaction is only to compensate the transfer and is calculated based on your method of payment. \"Podkrepi.bg\" works with 0% commission"
"description": "The transaction is only to compensate the transfer and is calculated based on your method of payment. \"Podkrepi.bg\" works with 0% commission."
},
"total": "Total",
"field": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ export const useCampaignsList = () => {
const { data, isLoading } = fetchMutation()

return {
list: data?.sort((a, b) => b?.updatedAt?.localeCompare(a?.updatedAt ?? '') ?? 0),
// the data array is strict mode (sometimes) it throws a Readonly array error on the sort so create a shallow copy
list: [...(data ?? [])].sort((a, b) => b?.updatedAt?.localeCompare(a?.updatedAt ?? '') ?? 0),
isLoading,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export default function CampaignApplicationBasic() {
/>
</Grid>
<Grid item xs={12}>
<CampaignTypeSelect name="applicationBasic.campaignType" />
<CampaignTypeSelect name="applicationBasic.campaignType" hideSystemTypes={true} />
</Grid>
<Grid item xs={12}>
<StyledFormTextField
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,6 @@ export default function CampaignApplicationDetails({ files, setFiles }: Props) {
<StyledStepHeading variant="h4">{t('steps.details.title')}</StyledStepHeading>
</Grid>
<Grid item container spacing={6} justifyContent="space-between" direction="row">
<Grid item xs={12}>
<FormTextField
type="text"
name="applicationDetails.cause"
label={t('steps.details.cause')}
multiline
rows={3}
/>
</Grid>
<Grid item xs={12}>
<FormTextField
type="text"
Expand All @@ -50,6 +41,15 @@ export default function CampaignApplicationDetails({ files, setFiles }: Props) {
rows={5}
/>
</Grid>
<Grid item xs={12}>
<FormTextField
type="text"
name="applicationDetails.cause"
label={t('steps.details.cause')}
multiline
rows={3}
/>
</Grid>
<Grid item xs={12}>
<FileUpload
buttonLabel={t('steps.details.documents')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { Button, Grid, Tooltip } from '@mui/material'
import FilePresentIcon from '@mui/icons-material/FilePresent'
import Link from 'next/link'
import { expenseFileUrl } from 'common/util/expenseFileUrls'
import { getExactDate } from 'common/util/date'
import { bg, enUS } from 'date-fns/locale'

const PREFIX = 'Grid'

Expand Down Expand Up @@ -43,12 +45,13 @@ const Root = styled(Grid)({
})

export default observer(function CampaignPublicExpensesGrid({ slug }: Props) {
const { t } = useTranslation('')
const { t, i18n } = useTranslation('')
const { data: expensesList } = useCampaignApprovedExpensesList(slug)
const [paginationModel, setPaginationModel] = useState({
pageSize: 20,
page: 0,
})
const locale = i18n?.language == 'bg' ? bg : enUS

const columns: GridColDef[] = [
{ field: 'id', headerName: 'ID' },
Expand Down Expand Up @@ -96,8 +99,7 @@ export default observer(function CampaignPublicExpensesGrid({ slug }: Props) {
if (!params.row.spentAt) {
return ''
}

return new Date(params.row.spentAt).toLocaleDateString()
return getExactDate(params.row.spentAt, locale)
},
},
{
Expand Down
16 changes: 10 additions & 6 deletions src/components/client/campaigns/CampaignTypeSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import { useCampaignTypesList } from 'common/hooks/campaigns'
import { useField } from 'formik'
import { useTranslation } from 'next-i18next'

export default function CampaignTypeSelect({ name = 'campaignTypeId' }) {
const systemTypes = ['Membership']

export default function CampaignTypeSelect({ name = 'campaignTypeId', hideSystemTypes = false }) {
const { t } = useTranslation()
const { data } = useCampaignTypesList()
const [field, meta] = useField(name)
Expand All @@ -21,11 +23,13 @@ export default function CampaignTypeSelect({ name = 'campaignTypeId' }) {
<MenuItem value="" disabled>
{t('campaigns:campaign.type')}
</MenuItem>
{data?.map((campaignType, index) => (
<MenuItem key={index} value={campaignType.id}>
{campaignType.name}
</MenuItem>
))}
{data
?.filter((campaignType) => !hideSystemTypes || !systemTypes.includes(campaignType?.name))
?.map((campaignType, index) => (
<MenuItem key={index} value={campaignType.id}>
{campaignType.name}
</MenuItem>
))}
</Select>
{helperText && <FormHelperText error>{helperText}</FormHelperText>}
</FormControl>
Expand Down
Loading

0 comments on commit 3c418af

Please sign in to comment.