|
15 | 15 | from parler.utils.context import switch_language
|
16 | 16 |
|
17 | 17 | from children.factories import ChildWithGuardianFactory
|
| 18 | +from children.models import Child |
18 | 19 | from common.tests.utils import assert_match_error_code, assert_permission_denied
|
19 | 20 | from common.utils import get_global_id
|
20 | 21 | from events.factories import (
|
|
70 | 71 | )
|
71 | 72 | from events.ticket_service import check_ticket_validity
|
72 | 73 | from kukkuu.consts import (
|
| 74 | + API_USAGE_ERROR, |
73 | 75 | CHILD_ALREADY_JOINED_EVENT_ERROR,
|
74 | 76 | DATA_VALIDATION_ERROR,
|
75 | 77 | EVENT_ALREADY_PUBLISHED_ERROR,
|
|
93 | 95 | )
|
94 | 96 | from kukkuu.exceptions import EnrolmentReferenceIdDoesNotExist
|
95 | 97 | from kukkuu.views import SentryGraphQLView
|
| 98 | +from projects.factories import ProjectFactory |
96 | 99 | from projects.models import Project
|
97 | 100 | from subscriptions.factories import FreeSpotNotificationSubscriptionFactory
|
98 | 101 | from users.factories import GuardianFactory, UserFactory
|
@@ -2284,85 +2287,308 @@ def test_import_ticket_system_passwords_invalid_permissions(guardian_api_client)
|
2284 | 2287 | assert_match_error_code(executed, PERMISSION_DENIED_ERROR)
|
2285 | 2288 |
|
2286 | 2289 |
|
2287 |
| -def test_assign_ticket_system_password(snapshot, guardian_api_client): |
2288 |
| - event = EventFactory(ticket_system=Event.TICKETMASTER, published_at=now()) |
| 2290 | +def _assign_ticket_system_password(client, event, child) -> dict: |
| 2291 | + variables = { |
| 2292 | + "input": { |
| 2293 | + "eventId": get_global_id(event), |
| 2294 | + "childId": get_global_id(child), |
| 2295 | + } |
| 2296 | + } |
| 2297 | + |
| 2298 | + return client.execute( |
| 2299 | + ASSIGN_TICKET_SYSTEM_PASSWORD_MUTATION, |
| 2300 | + variables=variables, |
| 2301 | + ) |
| 2302 | + |
| 2303 | + |
| 2304 | +def test_assign_ticket_system_password_success(guardian_api_client): |
| 2305 | + """ |
| 2306 | + Test that a free password can be assigned to a child. |
| 2307 | + """ |
| 2308 | + event = EventFactory( |
| 2309 | + name="Test event", ticket_system=Event.TICKETMASTER, published_at=now() |
| 2310 | + ) |
2289 | 2311 | child = ChildWithGuardianFactory(
|
2290 |
| - relationship__guardian__user=guardian_api_client.user.guardian.user |
| 2312 | + name="Test child", |
| 2313 | + relationship__guardian__user=guardian_api_client.user.guardian.user, |
2291 | 2314 | )
|
2292 | 2315 | someone_elses_password = TicketSystemPasswordFactory( # noqa: F841
|
2293 | 2316 | event=event, value="FATAL LEAK", assigned_at=now()
|
2294 | 2317 | )
|
2295 | 2318 | free_password = TicketSystemPasswordFactory(
|
2296 |
| - event=event, child=None, value="the correct password" |
| 2319 | + event=event, child=None, value="The correct password" |
2297 | 2320 | )
|
2298 | 2321 | another_free_password = TicketSystemPasswordFactory( # noqa: F841
|
2299 |
| - event=event, child=None, value="wrong password" |
| 2322 | + event=event, child=None, value="Wrong password" |
2300 | 2323 | )
|
2301 | 2324 |
|
2302 |
| - variables = { |
2303 |
| - "input": { |
2304 |
| - "eventId": get_global_id(event), |
2305 |
| - "childId": get_global_id(child), |
| 2325 | + executed = _assign_ticket_system_password(guardian_api_client, event, child) |
| 2326 | + |
| 2327 | + assert executed == { |
| 2328 | + "data": { |
| 2329 | + "assignTicketSystemPassword": { |
| 2330 | + "child": {"name": "Test child"}, |
| 2331 | + "event": {"name": "Test event"}, |
| 2332 | + "password": "The correct password", |
| 2333 | + } |
2306 | 2334 | }
|
2307 | 2335 | }
|
2308 | 2336 |
|
2309 |
| - executed = guardian_api_client.execute( |
2310 |
| - ASSIGN_TICKET_SYSTEM_PASSWORD_MUTATION, |
2311 |
| - variables=variables, |
2312 |
| - ) |
2313 |
| - |
2314 |
| - snapshot.assert_match(executed) |
2315 | 2337 | assert child.ticket_system_passwords.get(event=event) == free_password
|
2316 | 2338 |
|
2317 |
| - # second mutation should result in password already assigned error |
2318 |
| - executed = guardian_api_client.execute( |
2319 |
| - ASSIGN_TICKET_SYSTEM_PASSWORD_MUTATION, |
2320 |
| - variables=variables, |
| 2339 | + |
| 2340 | +def test_assign_ticket_system_password_already_assigned(guardian_api_client): |
| 2341 | + """ |
| 2342 | + Test that a password can not be assigned to a child who already has it. |
| 2343 | + """ |
| 2344 | + event = EventFactory(ticket_system=Event.TICKETMASTER, published_at=now()) |
| 2345 | + child = ChildWithGuardianFactory( |
| 2346 | + relationship__guardian__user=guardian_api_client.user.guardian.user |
2321 | 2347 | )
|
| 2348 | + used_password = TicketSystemPasswordFactory( |
| 2349 | + event=event, child=child, value="Used password" |
| 2350 | + ) |
| 2351 | + free_password = TicketSystemPasswordFactory( |
| 2352 | + event=event, child=None, value="Free password" |
| 2353 | + ) |
| 2354 | + assert set(TicketSystemPassword.objects.all()) == {used_password, free_password} |
| 2355 | + |
| 2356 | + executed = _assign_ticket_system_password(guardian_api_client, event, child) |
2322 | 2357 |
|
2323 | 2358 | assert_match_error_code(executed, TICKET_SYSTEM_PASSWORD_ALREADY_ASSIGNED_ERROR)
|
2324 | 2359 |
|
2325 | 2360 |
|
2326 | 2361 | def test_assign_ticket_system_password_no_free_passwords(
|
2327 | 2362 | guardian_api_client,
|
2328 | 2363 | ):
|
| 2364 | + """ |
| 2365 | + Test that if there are no free passwords available, then a password can not be |
| 2366 | + assigned because of this. |
| 2367 | + """ |
2329 | 2368 | event = EventFactory(ticket_system=Event.TICKETMASTER, published_at=now())
|
2330 | 2369 | child = ChildWithGuardianFactory(
|
2331 | 2370 | relationship__guardian__user=guardian_api_client.user.guardian.user
|
2332 | 2371 | )
|
2333 |
| - someone_elses_password = TicketSystemPasswordFactory( # noqa: F841 |
2334 |
| - event=event, value="FATAL LEAK", assigned_at=now() |
| 2372 | + TicketSystemPasswordFactory( |
| 2373 | + event=event, value="Someone else's password", assigned_at=now() |
2335 | 2374 | )
|
2336 | 2375 |
|
2337 |
| - variables = { |
2338 |
| - "input": {"eventId": get_global_id(event), "childId": get_global_id(child)} |
2339 |
| - } |
| 2376 | + executed = _assign_ticket_system_password(guardian_api_client, event, child) |
2340 | 2377 |
|
2341 |
| - executed = guardian_api_client.execute( |
2342 |
| - ASSIGN_TICKET_SYSTEM_PASSWORD_MUTATION, |
2343 |
| - variables=variables, |
| 2378 | + assert_match_error_code(executed, NO_FREE_TICKET_SYSTEM_PASSWORDS_ERROR) |
| 2379 | + |
| 2380 | + |
| 2381 | +def test_assign_ticket_system_password_internal_event(guardian_api_client): |
| 2382 | + """ |
| 2383 | + Test that a password can not be assigned to an internal ticket system event. |
| 2384 | + """ |
| 2385 | + event = EventFactory(ticket_system=Event.INTERNAL, published_at=now()) |
| 2386 | + child = ChildWithGuardianFactory( |
| 2387 | + relationship__guardian__user=guardian_api_client.user.guardian.user |
2344 | 2388 | )
|
2345 | 2389 |
|
2346 |
| - assert_match_error_code(executed, NO_FREE_TICKET_SYSTEM_PASSWORDS_ERROR) |
| 2390 | + executed = _assign_ticket_system_password(guardian_api_client, event, child) |
| 2391 | + |
| 2392 | + assert_match_error_code(executed, API_USAGE_ERROR) |
| 2393 | + assert executed["errors"][0]["message"] == ( |
| 2394 | + "Password can not be assigned to internal ticket system event" |
| 2395 | + ) |
| 2396 | + |
| 2397 | + |
| 2398 | +def test_assign_ticket_system_password_not_published_event(guardian_api_client): |
| 2399 | + """ |
| 2400 | + Test that event that has not been published is not visible to |
| 2401 | + AssignTicketSystemPassword mutation. |
| 2402 | + """ |
| 2403 | + event = EventFactory(ticket_system=Event.TICKETMASTER, published_at=None) |
| 2404 | + child = ChildWithGuardianFactory( |
| 2405 | + relationship__guardian__user=guardian_api_client.user.guardian.user |
| 2406 | + ) |
| 2407 | + |
| 2408 | + executed = _assign_ticket_system_password(guardian_api_client, event, child) |
| 2409 | + |
| 2410 | + assert_match_error_code(executed, OBJECT_DOES_NOT_EXIST_ERROR) |
| 2411 | + |
| 2412 | + |
| 2413 | +def _create_data_for_ticket_system_password_only_externals_enrolment_limit_tests( |
| 2414 | + client, enrolment_limit, existing_enrolment_count |
| 2415 | +) -> tuple[Event, Child, TicketSystemPassword]: |
| 2416 | + """ |
| 2417 | + Create test data for testing the AssignTicketSystemPassword mutation |
| 2418 | + with only external ticket system events & existing ticket system passwords. |
| 2419 | + """ |
| 2420 | + project = ProjectFactory(enrolment_limit=enrolment_limit) |
| 2421 | + event = EventFactory( |
| 2422 | + name="Test event", |
| 2423 | + project=project, |
| 2424 | + ticket_system=Event.TICKETMASTER, |
| 2425 | + published_at=now(), |
| 2426 | + ) |
| 2427 | + child = ChildWithGuardianFactory( |
| 2428 | + name="Test child", |
| 2429 | + project=project, |
| 2430 | + relationship__guardian__user=client.user.guardian.user, |
| 2431 | + ) |
| 2432 | + TicketSystemPasswordFactory.create_batch( |
| 2433 | + size=existing_enrolment_count, |
| 2434 | + child=child, |
| 2435 | + event__project=project, |
| 2436 | + event__published_at=now(), |
| 2437 | + ) |
| 2438 | + free_password = TicketSystemPasswordFactory( |
| 2439 | + event=event, child=None, value="Free password" |
| 2440 | + ) |
| 2441 | + return event, child, free_password |
| 2442 | + |
| 2443 | + |
| 2444 | +@pytest.mark.parametrize( |
| 2445 | + "enrolment_limit, existing_enrolment_count", |
| 2446 | + [ |
| 2447 | + (1, 0), |
| 2448 | + (2, 0), |
| 2449 | + (2, 1), |
| 2450 | + (3, 0), |
| 2451 | + (3, 1), |
| 2452 | + (3, 2), |
| 2453 | + (10, 1), |
| 2454 | + (10, 9), |
| 2455 | + (100, 99), |
| 2456 | + ], |
| 2457 | +) |
| 2458 | +def test_assign_ticket_system_password_only_externals_enrolment_limit_not_full( |
| 2459 | + guardian_api_client, enrolment_limit, existing_enrolment_count |
| 2460 | +): |
| 2461 | + """ |
| 2462 | + Test that a free password can be assigned to a child when the yearly enrolment limit |
| 2463 | + has not been reached. Tests without internal event enrolments. |
| 2464 | + """ |
| 2465 | + event, child, free_password = ( |
| 2466 | + _create_data_for_ticket_system_password_only_externals_enrolment_limit_tests( |
| 2467 | + guardian_api_client, enrolment_limit, existing_enrolment_count |
| 2468 | + ) |
| 2469 | + ) |
| 2470 | + assert child.ticket_system_passwords.count() == existing_enrolment_count |
| 2471 | + assert not Enrolment.objects.exists() |
| 2472 | + executed = _assign_ticket_system_password(guardian_api_client, event, child) |
| 2473 | + |
| 2474 | + assert "errors" not in executed |
| 2475 | + assert child.ticket_system_passwords.count() == (existing_enrolment_count + 1) |
| 2476 | + assert child.ticket_system_passwords.get(event=event) == free_password |
| 2477 | + |
| 2478 | + |
| 2479 | +@pytest.mark.parametrize( |
| 2480 | + "enrolment_limit, existing_enrolment_count", |
| 2481 | + [ |
| 2482 | + (1, 1), |
| 2483 | + (1, 2), |
| 2484 | + (2, 2), |
| 2485 | + (2, 3), |
| 2486 | + (3, 3), |
| 2487 | + (3, 4), |
| 2488 | + (10, 10), |
| 2489 | + (20, 30), |
| 2490 | + ], |
| 2491 | +) |
| 2492 | +def test_assign_ticket_system_password_only_externals_enrolment_limit_full( |
| 2493 | + guardian_api_client, |
| 2494 | + enrolment_limit, |
| 2495 | + existing_enrolment_count, |
| 2496 | +): |
| 2497 | + """ |
| 2498 | + Test that a free password can not be assigned to a child when the yearly enrolment |
| 2499 | + limit has been reached. Tests without internal event enrolments. |
| 2500 | + """ |
| 2501 | + event, child, free_password = ( |
| 2502 | + _create_data_for_ticket_system_password_only_externals_enrolment_limit_tests( |
| 2503 | + guardian_api_client, enrolment_limit, existing_enrolment_count |
| 2504 | + ) |
| 2505 | + ) |
| 2506 | + assert child.ticket_system_passwords.count() == existing_enrolment_count |
| 2507 | + assert not Enrolment.objects.exists() |
| 2508 | + executed = _assign_ticket_system_password(guardian_api_client, event, child) |
| 2509 | + |
| 2510 | + assert_match_error_code(executed, INELIGIBLE_OCCURRENCE_ENROLMENT) |
| 2511 | + assert executed["errors"][0]["message"] == "Yearly enrolment limit has been reached" |
| 2512 | + assert child.ticket_system_passwords.count() == existing_enrolment_count |
| 2513 | + assert not child.ticket_system_passwords.filter(event=event).exists() |
| 2514 | + |
| 2515 | + |
| 2516 | +def test_assign_ticket_system_password_internal_and_external_enrolment_limit( |
| 2517 | + guardian_api_client, |
| 2518 | +): |
| 2519 | + """ |
| 2520 | + Test that a free password can not be assigned to a child when the yearly enrolment |
| 2521 | + limit is reached by the sum of both internal and external events. |
| 2522 | + """ |
| 2523 | + project = ProjectFactory(enrolment_limit=3) |
| 2524 | + external_event = EventFactory( |
| 2525 | + name="Test event", |
| 2526 | + project=project, |
| 2527 | + ticket_system=Event.TICKETMASTER, |
| 2528 | + published_at=now(), |
| 2529 | + ) |
| 2530 | + another_external_event = EventFactory( |
| 2531 | + name="Second test event", |
| 2532 | + project=project, |
| 2533 | + ticket_system=Event.TICKETMASTER, |
| 2534 | + published_at=now(), |
| 2535 | + ) |
| 2536 | + child = ChildWithGuardianFactory( |
| 2537 | + name="Test child", |
| 2538 | + project=project, |
| 2539 | + relationship__guardian__user=guardian_api_client.user.guardian.user, |
| 2540 | + ) |
| 2541 | + TicketSystemPasswordFactory( |
| 2542 | + child=child, |
| 2543 | + event__project=project, |
| 2544 | + event__published_at=now(), |
| 2545 | + ) |
| 2546 | + TicketSystemPasswordFactory(event=external_event, child=None, value="Free password") |
| 2547 | + internal_event = EventFactory( |
| 2548 | + project=project, |
| 2549 | + ticket_system=Event.INTERNAL, |
| 2550 | + published_at=now(), |
| 2551 | + ) |
| 2552 | + EnrolmentFactory( |
| 2553 | + child=child, |
| 2554 | + occurrence__time=now() + timedelta(hours=1), |
| 2555 | + occurrence__event=internal_event, |
| 2556 | + ) |
| 2557 | + assert child.enrolments.count() == 1 |
| 2558 | + assert child.ticket_system_passwords.count() == 1 |
| 2559 | + assert child.get_enrolment_count(now().year) == 2 |
| 2560 | + |
| 2561 | + # Yearly limit has not been reached yet, so should be successful |
| 2562 | + executed = _assign_ticket_system_password( |
| 2563 | + guardian_api_client, external_event, child |
| 2564 | + ) |
| 2565 | + |
| 2566 | + assert "errors" not in executed |
| 2567 | + assert child.ticket_system_passwords.count() == 2 |
| 2568 | + assert child.get_enrolment_count(now().year) == 3 |
| 2569 | + |
| 2570 | + # Now the yearly limit has been reached, so this should fail |
| 2571 | + executed = _assign_ticket_system_password( |
| 2572 | + guardian_api_client, another_external_event, child |
| 2573 | + ) |
| 2574 | + |
| 2575 | + assert_match_error_code(executed, INELIGIBLE_OCCURRENCE_ENROLMENT) |
| 2576 | + assert executed["errors"][0]["message"] == "Yearly enrolment limit has been reached" |
| 2577 | + assert child.ticket_system_passwords.count() == 2 |
| 2578 | + assert child.get_enrolment_count(now().year) == 3 |
2347 | 2579 |
|
2348 | 2580 |
|
2349 | 2581 | def test_assign_ticket_system_password_not_own_child(guardian_api_client):
|
| 2582 | + """ |
| 2583 | + Test that the user does not see someone else's child using |
| 2584 | + AssignTicketSystemPassword mutation, and can not assign a password to them. |
| 2585 | + """ |
2350 | 2586 | event = EventFactory(ticket_system=Event.TICKETMASTER, published_at=now())
|
2351 | 2587 | another_child = ChildWithGuardianFactory()
|
2352 | 2588 | some_free_password = TicketSystemPasswordFactory(event=event) # noqa: F841
|
2353 | 2589 |
|
2354 |
| - variables = { |
2355 |
| - "input": { |
2356 |
| - "eventId": get_global_id(event), |
2357 |
| - "childId": get_global_id(another_child), |
2358 |
| - } |
2359 |
| - } |
2360 |
| - |
2361 | 2590 | # try to assign a password to someone else's child
|
2362 |
| - executed = guardian_api_client.execute( |
2363 |
| - ASSIGN_TICKET_SYSTEM_PASSWORD_MUTATION, |
2364 |
| - variables=variables, |
2365 |
| - ) |
| 2591 | + executed = _assign_ticket_system_password(guardian_api_client, event, another_child) |
2366 | 2592 |
|
2367 | 2593 | assert_match_error_code(executed, OBJECT_DOES_NOT_EXIST_ERROR)
|
2368 | 2594 | assert not another_child.ticket_system_passwords.filter(event=event).exists()
|
|
0 commit comments