-
Notifications
You must be signed in to change notification settings - Fork 38
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
Sign up to event #104
Sign up to event #104
Changes from 6 commits
451c9bd
6c32cd1
786eaf8
b19d8df
82da026
2a336c8
c85776c
c83f3fe
db23b2c
f75a42e
cdd458a
3dea616
7d82701
748c496
2f21830
6e5a17d
2ee9245
01a5889
0949317
8970016
3e94a79
876a5b1
79a4b05
6423f59
8f02e54
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,13 @@ | ||
{ | ||
"data": [ | ||
{ | ||
"action_id": 22, | ||
"response_date": "1111 11 11, 11:11", | ||
"person": { | ||
"name": "Dummy User", | ||
"id": 2 | ||
}, | ||
"id": 2 | ||
} | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,13 @@ | ||
import EventList from './EventList'; | ||
import { mountWithProviders } from '../utils/testing'; | ||
import { ZetkinEvent } from '../interfaces/ZetkinEvent'; | ||
import { ZetkinEventResponse } from '../types/zetkin'; | ||
import { ZetkinOrganization } from '../interfaces/ZetkinOrganization'; | ||
|
||
describe('EventList', () => { | ||
let dummyOrg : ZetkinOrganization; | ||
let dummyEvents : ZetkinEvent[]; | ||
let dummyEventResponses : ZetkinEventResponse[]; | ||
|
||
beforeEach(()=> { | ||
cy.fixture('dummyOrg.json') | ||
|
@@ -16,11 +18,22 @@ describe('EventList', () => { | |
.then((data : {data: ZetkinEvent[]}) => { | ||
dummyEvents = data.data; | ||
}); | ||
cy.fixture('dummyEventResponses.json') | ||
.then((data : {data: ZetkinEventResponse[]}) => { | ||
dummyEventResponses = data.data; | ||
}); | ||
}); | ||
|
||
it('contains data for each event', () => { | ||
const spyOnSubmit = cy.spy(); | ||
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. The naming is off, implies that there is an 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. Also, there should be no need for a spy in this test (or the subsequent ones) where the spy is not actually used for spying. |
||
|
||
mountWithProviders( | ||
<EventList events={ dummyEvents } org={ dummyOrg }/>, | ||
<EventList | ||
eventResponses={ dummyEventResponses } | ||
events={ dummyEvents } | ||
onEventResponse={ spyOnSubmit } | ||
org={ dummyOrg } | ||
/>, | ||
); | ||
|
||
cy.get('[data-test="event"]').each((item) => { | ||
|
@@ -36,8 +49,15 @@ describe('EventList', () => { | |
|
||
it('contains an activity title instead of missing event title', () => { | ||
dummyEvents[0].title = undefined; | ||
const spyOnSubmit = cy.spy(); | ||
|
||
mountWithProviders( | ||
<EventList events={ dummyEvents } org={ dummyOrg }/>, | ||
<EventList | ||
eventResponses={ dummyEventResponses } | ||
events={ dummyEvents } | ||
onEventResponse={ spyOnSubmit } | ||
org={ dummyOrg } | ||
/>, | ||
); | ||
|
||
cy.get('[data-test="event"]') | ||
|
@@ -46,33 +66,70 @@ describe('EventList', () => { | |
}); | ||
|
||
it('contains a sign-up button for each event', () => { | ||
const spyOnSubmit = cy.spy(); | ||
|
||
mountWithProviders( | ||
<EventList events={ dummyEvents } org={ dummyOrg }/>, | ||
<EventList | ||
eventResponses={ dummyEventResponses } | ||
events={ dummyEvents } | ||
onEventResponse={ spyOnSubmit } | ||
org={ dummyOrg } | ||
/>, | ||
); | ||
|
||
cy.contains('misc.eventList.signup'); | ||
//Checks for buttons on all events | ||
cy.findByText('misc.eventList.signup'); | ||
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. What is the purpose of this? 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. I see now it's unnecessary since line 81 is already doing the same thing. Will remove this! |
||
|
||
//Tests button on a single event | ||
cy.findByText('misc.eventList.signup') | ||
.eq(0) | ||
.click() | ||
.then(() => { | ||
expect(spyOnSubmit).to.be.calledOnce; | ||
richardolsson marked this conversation as resolved.
Show resolved
Hide resolved
|
||
}); | ||
}); | ||
|
||
it('contains a button for more info on each event', () => { | ||
const spyOnSubmit = cy.spy(); | ||
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. Why the spy here? 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. Seems like I missed this when removing spies, will remove. |
||
|
||
mountWithProviders( | ||
<EventList events={ dummyEvents } org={ dummyOrg }/>, | ||
<EventList | ||
eventResponses={ dummyEventResponses } | ||
events={ dummyEvents } | ||
onEventResponse={ spyOnSubmit } | ||
org={ dummyOrg } | ||
/>, | ||
); | ||
|
||
cy.contains('misc.eventList.moreInfo'); | ||
}); | ||
|
||
it('shows a placeholder when the list is empty', () => { | ||
const spyOnSubmit = cy.spy(); | ||
|
||
dummyEvents = []; | ||
mountWithProviders( | ||
<EventList events={ dummyEvents } org={ dummyOrg }/>, | ||
<EventList | ||
eventResponses={ dummyEventResponses } | ||
events={ dummyEvents } | ||
onEventResponse={ spyOnSubmit } | ||
org={ dummyOrg } | ||
/>, | ||
); | ||
|
||
cy.contains('misc.eventList.placeholder'); | ||
}); | ||
|
||
it('shows a placeholder when the list is undefined', () => { | ||
const spyOnSubmit = cy.spy(); | ||
|
||
mountWithProviders( | ||
<EventList events={ undefined } org={ dummyOrg }/>, | ||
<EventList | ||
eventResponses={ dummyEventResponses } | ||
events={ undefined } | ||
onEventResponse={ spyOnSubmit } | ||
org={ dummyOrg } | ||
/>, | ||
); | ||
|
||
cy.contains('misc.eventList.placeholder'); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import apiUrl from '../utils/apiUrl'; | ||
|
||
import { ZetkinEventSignup, ZetkinMembership } from '../types/zetkin'; | ||
|
||
export default async function deleteEventResponse({ eventId, orgId } : ZetkinEventSignup) : Promise<void> { | ||
const mUrl = apiUrl('/users/me/memberships'); | ||
const mRes = await fetch(mUrl); | ||
const mData = await mRes.json(); | ||
const orgMembership = mData.data.find((m : ZetkinMembership) => m.organization.id === orgId); | ||
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. This solution is a hack. Maybe leave it like this for now, but add a TODO comment or an issue so we remember to get back to it. It should not be necessary to retrieve the memberships every time. They should be cached. |
||
|
||
if (orgMembership) { | ||
const url = apiUrl(`/orgs/${orgId}/actions/${eventId}/responses/${orgMembership.profile.id}`); | ||
await fetch(url, { | ||
method: 'DELETE', | ||
}); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import apiUrl from '../utils/apiUrl'; | ||
|
||
import { ZetkinEventResponse } from '../types/zetkin'; | ||
|
||
export default async function getEventResponses() : Promise<ZetkinEventResponse[]> { | ||
const rUrl = apiUrl('/users/me/action_responses'); | ||
const rRes = await fetch(rUrl); | ||
const rData = await rRes.json(); | ||
return rData.data; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import apiUrl from '../utils/apiUrl'; | ||
|
||
import { ZetkinEventResponse, ZetkinEventSignup, ZetkinMembership } from '../types/zetkin'; | ||
|
||
export default async function putEventResponse({ eventId, orgId } : ZetkinEventSignup) : Promise<ZetkinEventResponse> { | ||
const mUrl = apiUrl('/users/me/memberships'); | ||
const mRes = await fetch(mUrl); | ||
const mData = await mRes.json(); | ||
const orgMembership = mData.data.find((m : ZetkinMembership ) => m.organization.id === orgId); | ||
|
||
if (orgMembership) { | ||
const eventUrl = apiUrl(`/orgs/${orgId}/actions/${eventId}/responses/${orgMembership.profile.id}`); | ||
const eventRes = await fetch(eventUrl, { | ||
method: 'PUT', | ||
}); | ||
const eventData = await eventRes.json(); | ||
return eventData.data; | ||
} | ||
|
||
throw 'no membership'; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
placeholder: Sorry, there are no planned events at the moment. | ||
moreInfo: More info | ||
signup: Sign-up | ||
signup: Sign-up | ||
undoSignup: Undo sign-up |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
placeholder: Tyvärr finns det inga planerade händelser för tillfället. | ||
moreInfo: Mer info | ||
signup: Anmälan | ||
signup: Anmälan | ||
undoSignup: Ångra anmälan |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
actions: | ||
signUp: Sign-up | ||
signUp: Sign-up |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,2 @@ | ||
actions: | ||
signUp: Anmälan | ||
signUp: Anmälan |
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.
I dislike the use of this very weird date. Why the year 1111, and not something more alike to what would occur in live data? It's also not using the correct ISO format. The API delivers dates like
2021-01-21T18:30:00+00:00
, and the dummy data should mimic that.