@VisibleForTesting
  ExportResult<MediaContainerResource> exportOneDrivePhotos(TokensAndUrlAuthData authData,
      Optional<IdOnlyContainerResource> albumData, Optional<PaginationData> paginationData,
      UUID jobId) throws IOException {
    Optional<String> albumId = Optional.empty();
    if (albumData.isPresent()) {
      albumId = Optional.of(albumData.get().getId());
    }
    Optional<String> paginationUrl = getDrivePaginationToken(paginationData);

    MicrosoftDriveItemsResponse driveItemsResponse;
    if (paginationData.isPresent() || albumData.isPresent()) {
      driveItemsResponse =
          getOrCreateMediaInterface(authData).getDriveItems(albumId, paginationUrl);
    } else {
      driveItemsResponse = getOrCreateMediaInterface(authData).getDriveItemsFromSpecialFolder(
          MicrosoftSpecialFolder.FolderType.photos);
    }

    PaginationData nextPageData = setNextPageToken(driveItemsResponse);
    ContinuationData continuationData = new ContinuationData(nextPageData);
    MediaContainerResource containerResource;
    MicrosoftDriveItem[] driveItems = driveItemsResponse.getDriveItems();
    List<MediaAlbum> albums = new ArrayList<>();
    List<PhotoModel> photos = new ArrayList<>();
    List<VideoModel> videos = new ArrayList<>();

    if (driveItems != null && driveItems.length > 0) {
      for (MicrosoftDriveItem driveItem : driveItems) {
        MediaAlbum album = tryConvertDriveItemToMediaAlbum(driveItem, jobId);
        if (album != null) {
          albums.add(album);
          continuationData.addContainerResource(new IdOnlyContainerResource(driveItem.id));
          continue;
        }

        PhotoModel photo = tryConvertDriveItemToPhotoModel(albumId, driveItem, jobId);
        if (photo != null) {
          photos.add(photo);
          continue;
        }

        VideoModel video = tryConvertDriveItemToVideoModel(albumId, driveItem, jobId);
        if (video != null) {
          videos.add(video);
          continue;
        }
      }
    }

    ExportResult.ResultType result =
        nextPageData == null ? ExportResult.ResultType.END : ExportResult.ResultType.CONTINUE;
    containerResource = new MediaContainerResource(albums, photos, videos);
    return new ExportResult<>(result, containerResource, continuationData);
  }
@Test
  public void exportAlbumAndMediaWithNextPage() throws IOException {
    // Setup
    when(driveItemsResponse.getDriveItems())
        .thenReturn(new MicrosoftDriveItem[] {
          setUpSingleAlbum(),
          setUpSinglePhoto(PHOTO_FILENAME, PHOTO_URI, PHOTO_ID)
        });
    when(driveItemsResponse.getNextPageLink()).thenReturn(DRIVE_PAGE_URL);

    // Run
    ExportResult<MediaContainerResource> result = microsoftMediaExporter.exportOneDrivePhotos(
        null, Optional.empty(), Optional.empty(), uuid);

    // Verify method calls
    verify(mediaInterface)
        .getDriveItemsFromSpecialFolder(MicrosoftSpecialFolder.FolderType.photos);
    verify(driveItemsResponse).getDriveItems();

    // Verify pagination token is set
    ContinuationData continuationData = result.getContinuationData();
    StringPaginationToken paginationToken =
        (StringPaginationToken) continuationData.getPaginationData();
    assertThat(paginationToken.getToken()).isEqualTo(DRIVE_TOKEN_PREFIX + DRIVE_PAGE_URL);

    // Verify one album is ready for import
    Collection<MediaAlbum> actualAlbums = result.getExportedData().getAlbums();
    assertThat(actualAlbums.stream().map(MediaAlbum::getId).collect(Collectors.toList()))
        .containsExactly(FOLDER_ID);

    // Verify one photo should be present (in the root Photos special folder)
    Collection<PhotoModel> actualPhotos = result.getExportedData().getPhotos();
    assertThat(actualPhotos.stream().map(PhotoModel::getFetchableUrl).collect(Collectors.toList()))
        .containsExactly(PHOTO_URI);
    assertThat(actualPhotos.stream().map(PhotoModel::getAlbumId).collect(Collectors.toList()))
        .containsExactly(null);
    assertThat(actualPhotos.stream().map(PhotoModel::getTitle).collect(Collectors.toList()))
        .containsExactly(PHOTO_FILENAME);

    // Verify there is one container ready for sub-processing
    List<ContainerResource> actualResources = continuationData.getContainerResources();
    assertThat(actualResources.stream()
                   .map(a -> ((IdOnlyContainerResource) a).getId())
                   .collect(Collectors.toList()))
        .containsExactly(FOLDER_ID);
  }