Class TicketsWebServiceTest

java.lang.Object
ubic.gemma.rest.TicketsWebServiceTest

@ExtendWith(org.mockito.junit.jupiter.MockitoExtension.class) public class TicketsWebServiceTest extends Object
Pure Mockito unit tests for TicketsWebService covering the read-only endpoints introduced in Phase B-2 of AUDIT_AS_WORKFLOW_RECCE.md. Does NOT stand up Jersey; the focus is the WebService → service wiring and the VO projection shape.
Author:
paul
  • Constructor Details

    • TicketsWebServiceTest

      public TicketsWebServiceTest()
  • Method Details

    • setUp

      @BeforeEach public void setUp()
    • testGetTickets_passesFiltersThrough

      @Test public void testGetTickets_passesFiltersThrough()
    • testGetTickets_defaultsAreNullFilters

      @Test public void testGetTickets_defaultsAreNullFilters()
    • getTickets_passesNewFilterArgs_through

      @Test public void getTickets_passesNewFilterArgs_through()
    • getMyQueue_returnsOpenAndRecentlyResolved_forCallingUser

      @Test public void getMyQueue_returnsOpenAndRecentlyResolved_forCallingUser()
    • getMyQueue_returns401_whenAnonymous

      @Test public void getMyQueue_returns401_whenAnonymous()
    • getMyQueueSummary_returnsCountsAndOldestOpen

      @Test public void getMyQueueSummary_returnsCountsAndOldestOpen()
    • getScratchpad_provisionsAndReturnsTheCallersOwn

      @Test public void getScratchpad_provisionsAndReturnsTheCallersOwn()
      The route provisions through the service and hands back the projection. The two VO fields asserted are what a client needs to recognize it and to know it can add to it.
    • getScratchpad_returns401_whenAnonymous

      @Test public void getScratchpad_returns401_whenAnonymous()
    • getScratchpad_requiresAuthentication

      @Test public void getScratchpad_requiresAuthentication() throws NoSuchMethodException
      Throws:
      NoSuchMethodException
    • getOpenTicketSummary_holdsScratchpadsOutOfTotalOpen_butStillReportsThem

      @Test public void getOpenTicketSummary_holdsScratchpadsOutOfTotalOpen_butStillReportsThem()
      A scratchpad is never resolved, so counting one as open work would put every curator permanently behind. It comes out of totalOpen — but it is NOT hidden: it is reported on its own field and still appears in the breakdown, so totalOpen + scratchpadOpen is the sum of byType and a caller can add it back.
    • testGetTicket_includesEvents

      @Test public void testGetTicket_includesEvents()
    • testGetTicket_notFound

      @Test public void testGetTicket_notFound()
    • testGetTicketEvents_returnsEventList

      @Test public void testGetTicketEvents_returnsEventList()
    • testGetTicketEvents_notFound

      @Test public void testGetTicketEvents_notFound()
    • testOpenTicketsForExpressionExperiment_delegatesToService

      @Test public void testOpenTicketsForExpressionExperiment_delegatesToService()
    • testOpenTicketsForArrayDesign_delegatesToService

      @Test public void testOpenTicketsForArrayDesign_delegatesToService()
    • testCreateTicket_happyPath

      @Test public void testCreateTicket_happyPath()
    • testCreateTicketFromAccession_resolvesAndOpens

      @Test public void testCreateTicketFromAccession_resolvesAndOpens()
      A caller holding a GEO accession opens a ticket in one call, and the type defaults to the category the curation store's own REVIEW maps onto.
    • testCreateTicketFromAccession_aSplitAccessionTargetsEveryPart

      @Test public void testCreateTicketFromAccession_aSplitAccessionTargetsEveryPart()
      🛑 ONE ACCESSION CAN NAME SEVERAL DATASETS, and all of them become targets.

      A GSE split during import backs one experiment per split. Taking the head of the collection would open a ticket over one arbitrary part and silently drop the rest — a review that looks complete and is not, which is worse than a 400. This is the whole reason the route resolves rather than the caller.

    • testCreateTicketFromAccession_fallsBackToShortName

      @Test public void testCreateTicketFromAccession_fallsBackToShortName()
      Nothing carries the accession as an accession, so the short name is tried before giving up.
    • testCreateTicketFromAccession_unknownAccessionOpensNothing

      @Test public void testCreateTicketFromAccession_unknownAccessionOpensNothing()
      An accession naming nothing is a 404 and opens NO ticket.

      A ticket pointing at a dataset that could not be resolved is worse than no ticket: it reads as work waiting rather than as the error it is.

    • testCreateTicket_carriesTheScreenPayload

      @Test public void testCreateTicket_carriesTheScreenPayload()
      A screening agent opens a ticket and says what its screen asked. The payload is stored verbatim and comes back on the created ticket, so the UI can render the question rather than a fixed GEO-scrape table with Include/Exclude (uib, 2026-09-03).
    • testCreateTicket_withoutAPayloadLeavesItUnset

      @Test public void testCreateTicket_withoutAPayloadLeavesItUnset()
      An ordinary ticket carries none, and creating one must not invent an empty payload.
    • testCreateTicket_missingTitle_throws400

      @Test public void testCreateTicket_missingTitle_throws400()
    • testCreateTicket_nullBody_throws400

      @Test public void testCreateTicket_nullBody_throws400()
    • testUpdateTicket_stateTransition

      @Test public void testUpdateTicket_stateTransition()
    • testUpdateTicket_addComment

      @Test public void testUpdateTicket_addComment()
    • testUpdateTicket_clearAssignee

      @Test public void testUpdateTicket_clearAssignee()
    • testUpdateTicket_notFound_throws404

      @Test public void testUpdateTicket_notFound_throws404()
    • testDeleteTicket_softCancels

      @Test public void testDeleteTicket_softCancels()
    • testDeleteTicket_alreadyCancelled_noTransition

      @Test public void testDeleteTicket_alreadyCancelled_noTransition()
    • testDeleteTicket_notFound_throws404

      @Test public void testDeleteTicket_notFound_throws404()
    • testCreateTicket_withBodyAndMode_persistsBoth

      @Test public void testCreateTicket_withBodyAndMode_persistsBoth()
    • testCreateTicket_withTargetStatus_seedsUNDERWAY

      @Test public void testCreateTicket_withTargetStatus_seedsUNDERWAY()
    • testCreateTicket_multiTargetMixedTypes_passesAllThrough

      @Test public void testCreateTicket_multiTargetMixedTypes_passesAllThrough()
    • testCreateTicket_GEO_SCRAPE_WATERMARK_target

      @Test public void testCreateTicket_GEO_SCRAPE_WATERMARK_target()
    • testUpdateTicket_setsBodyAndMode

      @Test public void testUpdateTicket_setsBodyAndMode()
    • testUpdateTicket_clearBody_explicitNull

      @Test public void testUpdateTicket_clearBody_explicitNull()
    • testUpdateTicket_bodyAbsent_doesNotClearExisting

      @Test public void testUpdateTicket_bodyAbsent_doesNotClearExisting()
    • testUpdateTicket_setsTitle

      @Test public void testUpdateTicket_setsTitle()
    • testPatchTicket_delegatesToUpdateTicket

      @Test public void testPatchTicket_delegatesToUpdateTicket()
    • testCancelToReopen_lifecycle

      @Test public void testCancelToReopen_lifecycle()
    • testUpdateTargetStatus_delegatesToService

      @Test public void testUpdateTargetStatus_delegatesToService()
    • testUpdateTargetStatus_unknownTarget_returns404

      @Test public void testUpdateTargetStatus_unknownTarget_returns404()
    • testUpdateTargetStatus_missingBody_returns400

      @Test public void testUpdateTargetStatus_missingBody_returns400()
    • testWriteEndpoints_requireAuthentication

      @Test public void testWriteEndpoints_requireAuthentication() throws NoSuchMethodException
      Annotation-level auth guard: the write-side endpoints must carry @PreAuthorize("isAuthenticated()"). At runtime Spring's method- security AOP turns the missing/anonymous principal into a 401/403; here we verify the precondition that produces that runtime behaviour without standing up the Spring container.
      Throws:
      NoSuchMethodException
    • searchTickets_returnsTheHitsInTheOrderTheServiceGaveThem

      @Test public void searchTickets_returnsTheHitsInTheOrderTheServiceGaveThem()
    • searchTickets_requiresAQuery

      @Test public void searchTickets_requiresAQuery()
    • searchTickets_refusesALimitAboveTheMaximum_ratherThanClampingIt

      @Test public void searchTickets_refusesALimitAboveTheMaximum_ratherThanClampingIt()
      A limit the endpoint will not honour is refused, not quietly reduced — a silent clamp teaches the client nothing about why it got 100 rows back when it asked for 500.
    • searchTickets_acceptsALimitAtTheMaximum

      @Test public void searchTickets_acceptsALimitAtTheMaximum()
    • searchTickets_openOnlyDefaultsToTrueOnTheWire

      @Test public void searchTickets_openOnlyDefaultsToTrueOnTheWire() throws NoSuchMethodException
      The default lives in the @DefaultValue annotation, which JAX-RS applies during parameter binding — calling the method directly never sees it, so it is asserted on the wire contract itself.
      Throws:
      NoSuchMethodException
    • searchTickets_openOnlyFalseIsPassedThrough

      @Test public void searchTickets_openOnlyFalseIsPassedThrough()
    • searchTickets_passesTheCallersContactId_forScratchpadScoping

      @Test public void searchTickets_passesTheCallersContactId_forScratchpadScoping()
      The caller's identity decides whose scratchpad is worth offering, so it has to reach the service.
    • searchTickets_anonymousCallerIsServedWithNoContactId

      @Test public void searchTickets_anonymousCallerIsServedWithNoContactId()