From 290a3ce4d2970820417ea9b2491f5ab6f162fead Mon Sep 17 00:00:00 2001 From: Daniel Brooks Date: Thu, 9 Mar 2023 17:15:03 -0800 Subject: [PATCH 1/7] fix(paginate): smart paginate our results --- .../Refresh/RefreshCoordinator.swift | 2 +- .../Sync/Operations/FetchArchive.swift | 27 ++++++------- .../Sources/Sync/Operations/FetchSaves.swift | 27 +++++++------ PocketKit/Sources/Sync/PocketSource.swift | 4 +- .../Sources/Sync/Slates/SlateService.swift | 4 +- PocketKit/Sources/Sync/Source.swift | 8 ++-- PocketKit/Sources/Sync/SyncConstants.swift | 40 +++++++++++++++++++ 7 files changed, 77 insertions(+), 35 deletions(-) create mode 100644 PocketKit/Sources/Sync/SyncConstants.swift diff --git a/PocketKit/Sources/PocketKit/Refresh/RefreshCoordinator.swift b/PocketKit/Sources/PocketKit/Refresh/RefreshCoordinator.swift index 4d9ba7c68..d6b7e1556 100644 --- a/PocketKit/Sources/PocketKit/Refresh/RefreshCoordinator.swift +++ b/PocketKit/Sources/PocketKit/Refresh/RefreshCoordinator.swift @@ -26,7 +26,7 @@ class RefreshCoordinator { } func initialize() { - _ = taskScheduler.registerHandler(forTaskWithIdentifier: Self.taskID, using: .main) { [weak self] task in + _ = taskScheduler.registerHandler(forTaskWithIdentifier: Self.taskID, using: .global(qos: .background)) { [weak self] task in self?.refresh(task) self?.submitRequest() } diff --git a/PocketKit/Sources/Sync/Operations/FetchArchive.swift b/PocketKit/Sources/Sync/Operations/FetchArchive.swift index 071c9ae39..107d7d788 100644 --- a/PocketKit/Sources/Sync/Operations/FetchArchive.swift +++ b/PocketKit/Sources/Sync/Operations/FetchArchive.swift @@ -9,7 +9,6 @@ class FetchArchive: SyncOperation { private let space: Space private let events: SyncEvents private let initialDownloadState: CurrentValueSubject - private let maxItems: Int private let lastRefresh: LastRefresh init( @@ -17,13 +16,11 @@ class FetchArchive: SyncOperation { space: Space, events: SyncEvents, initialDownloadState: CurrentValueSubject, - maxItems: Int, lastRefresh: LastRefresh ) { self.apollo = apollo self.space = space self.events = events - self.maxItems = maxItems self.lastRefresh = lastRefresh self.initialDownloadState = initialDownloadState } @@ -64,7 +61,7 @@ class FetchArchive: SyncOperation { } private func fetchArchive() async throws { - var pagination = PaginationSpec(maxItems: maxItems) + var pagination = PaginationSpec(maxItems: SyncConstants.Archive.firstLoadMaxCount, pageSize: SyncConstants.Archive.initalPageSize) repeat { let result = try await fetchPage(pagination) @@ -72,11 +69,11 @@ class FetchArchive: SyncOperation { if case .started = initialDownloadState.value, let totalCount = result.data?.user?.savedItems?.totalCount, pagination.cursor == nil { - initialDownloadState.send(.paginating(totalCount: totalCount)) + initialDownloadState.send(.paginating(totalCount: totalCount > pagination.maxItems ? pagination.maxItems : totalCount)) } try await updateLocalStorage(result: result) - pagination = pagination.nextPage(result: result) + pagination = pagination.nextPage(result: result, pageSize: SyncConstants.Archive.pageSize) } while pagination.shouldFetchNextPage initialDownloadState.send(.completed) @@ -86,7 +83,7 @@ class FetchArchive: SyncOperation { let query = FetchArchiveQuery( pagination: .some(PaginationInput( after: pagination.cursor ?? .none, - first: .some(pagination.maxItems) + first: .some(pagination.pageSize) )), filter: .none, sort: .some(SavedItemsSort(sortBy: .init(.archivedAt), sortOrder: .init(.desc))) @@ -101,7 +98,6 @@ class FetchArchive: SyncOperation { return try await apollo.fetch(query: query) } - @MainActor private func updateLocalStorage(result: GraphQLResult) throws { guard let edges = result.data?.user?.savedItems?.edges else { return @@ -134,28 +130,31 @@ class FetchArchive: SyncOperation { let cursor: String? let shouldFetchNextPage: Bool let maxItems: Int + let pageSize: Int - init(maxItems: Int) { - self.init(cursor: nil, shouldFetchNextPage: false, maxItems: maxItems) + init(maxItems: Int, pageSize: Int) { + self.init(cursor: nil, shouldFetchNextPage: false, maxItems: maxItems, pageSize: pageSize) } - private init(cursor: String?, shouldFetchNextPage: Bool, maxItems: Int) { + private init(cursor: String?, shouldFetchNextPage: Bool, maxItems: Int, pageSize: Int) { self.cursor = cursor self.shouldFetchNextPage = shouldFetchNextPage self.maxItems = maxItems + self.pageSize = pageSize } - func nextPage(result: GraphQLResult) -> PaginationSpec { + func nextPage(result: GraphQLResult, pageSize: Int) -> PaginationSpec { guard let savedItems = result.data?.user?.savedItems, let itemCount = savedItems.edges?.count, let endCursor = savedItems.pageInfo.endCursor else { - return PaginationSpec(cursor: nil, shouldFetchNextPage: false, maxItems: maxItems) + return PaginationSpec(cursor: nil, shouldFetchNextPage: false, maxItems: maxItems, pageSize: pageSize) } return PaginationSpec( cursor: endCursor, shouldFetchNextPage: savedItems.pageInfo.hasNextPage && itemCount < maxItems, - maxItems: maxItems - itemCount + maxItems: maxItems - itemCount, + pageSize: pageSize ) } } diff --git a/PocketKit/Sources/Sync/Operations/FetchSaves.swift b/PocketKit/Sources/Sync/Operations/FetchSaves.swift index 82761bfb3..18e29b731 100644 --- a/PocketKit/Sources/Sync/Operations/FetchSaves.swift +++ b/PocketKit/Sources/Sync/Operations/FetchSaves.swift @@ -33,7 +33,7 @@ class FetchSaves: SyncOperation { func execute() async -> SyncOperationResult { do { - try await fetchList() + try await fetchSaves() try await fetchTags() lastRefresh.refreshedSaves() @@ -67,8 +67,8 @@ class FetchSaves: SyncOperation { } } - private func fetchList() async throws { - var pagination = PaginationSpec(maxItems: maxItems) + private func fetchSaves() async throws { + var pagination = PaginationSpec(maxItems: SyncConstants.Saves.firstLoadMaxCount, pageSize: SyncConstants.Saves.initalPageSize) repeat { let result = try await fetchPage(pagination) @@ -79,11 +79,11 @@ class FetchSaves: SyncOperation { if case .started = initialDownloadState.value, let totalCount = result.data?.user?.savedItems?.totalCount, pagination.cursor == nil { - initialDownloadState.send(.paginating(totalCount: totalCount)) + initialDownloadState.send(.paginating(totalCount: totalCount > pagination.maxItems ? pagination.maxItems : totalCount)) } try await updateLocalStorage(result: result) - pagination = pagination.nextPage(result: result) + pagination = pagination.nextPage(result: result, pageSize: SyncConstants.Saves.pageSize) } while pagination.shouldFetchNextPage initialDownloadState.send(.completed) @@ -111,7 +111,7 @@ class FetchSaves: SyncOperation { let query = FetchSavesQuery( pagination: .some(PaginationInput( after: pagination.cursor ?? .none, - first: .some(pagination.maxItems) + first: .some(pagination.pageSize) )), savedItemsFilter: .none ) @@ -168,28 +168,31 @@ class FetchSaves: SyncOperation { let cursor: String? let shouldFetchNextPage: Bool let maxItems: Int + let pageSize: Int - init(maxItems: Int) { - self.init(cursor: nil, shouldFetchNextPage: false, maxItems: maxItems) + init(maxItems: Int, pageSize: Int) { + self.init(cursor: nil, shouldFetchNextPage: false, maxItems: maxItems, pageSize: pageSize) } - private init(cursor: String?, shouldFetchNextPage: Bool, maxItems: Int) { + private init(cursor: String?, shouldFetchNextPage: Bool, maxItems: Int, pageSize: Int) { self.cursor = cursor self.shouldFetchNextPage = shouldFetchNextPage self.maxItems = maxItems + self.pageSize = pageSize } - func nextPage(result: GraphQLResult) -> PaginationSpec { + func nextPage(result: GraphQLResult, pageSize: Int) -> PaginationSpec { guard let savedItems = result.data?.user?.savedItems, let itemCount = savedItems.edges?.count, let endCursor = savedItems.pageInfo.endCursor else { - return PaginationSpec(cursor: nil, shouldFetchNextPage: false, maxItems: maxItems) + return PaginationSpec(cursor: nil, shouldFetchNextPage: false, maxItems: maxItems, pageSize: pageSize) } return PaginationSpec( cursor: endCursor, shouldFetchNextPage: savedItems.pageInfo.hasNextPage && itemCount < maxItems, - maxItems: maxItems - itemCount + maxItems: maxItems - itemCount, + pageSize: pageSize ) } } diff --git a/PocketKit/Sources/Sync/PocketSource.swift b/PocketKit/Sources/Sync/PocketSource.swift index de9ccb9ef..5bfb8cc9f 100644 --- a/PocketKit/Sources/Sync/PocketSource.swift +++ b/PocketKit/Sources/Sync/PocketSource.swift @@ -204,7 +204,7 @@ public class PocketSource: Source { // MARK: - Saves/Archive items extension PocketSource { - public func refreshSaves(maxItems: Int = 400, completion: (() -> Void)? = nil) { + public func refreshSaves(maxItems: Int, completion: (() -> Void)? = nil) { if lastRefresh.lastRefreshSaves == nil { initialSavesDownloadState.send(.started) } @@ -222,7 +222,7 @@ extension PocketSource { enqueue(operation: operation, task: .fetchSaves(maxItems: maxItems), completion: completion) } - public func refreshArchive(maxItems: Int = 400, completion: (() -> Void)? = nil) { + public func refreshArchive(maxItems: Int, completion: (() -> Void)? = nil) { if lastRefresh.lastRefreshArchive == nil { initialArchiveDownloadState.send(.started) } diff --git a/PocketKit/Sources/Sync/Slates/SlateService.swift b/PocketKit/Sources/Sync/Slates/SlateService.swift index 4a169dd57..e5d25990d 100644 --- a/PocketKit/Sources/Sync/Slates/SlateService.swift +++ b/PocketKit/Sources/Sync/Slates/SlateService.swift @@ -21,7 +21,7 @@ class APISlateService: SlateService { } func fetchSlateLineup(_ identifier: String) async throws { - let query = GetSlateLineupQuery(lineupID: identifier, maxRecommendations: 5) + let query = GetSlateLineupQuery(lineupID: identifier, maxRecommendations: SyncConstants.Home.recomendationsPerSlateFromSlateLineup) guard let remote = try await apollo.fetch(query: query).data?.getSlateLineup else { return @@ -31,7 +31,7 @@ class APISlateService: SlateService { } func fetchSlate(_ slateID: String) async throws { - let query = GetSlateQuery(slateID: slateID, recommendationCount: 25) + let query = GetSlateQuery(slateID: slateID, recommendationCount: SyncConstants.Home.recomendationsPerSlateDetail) guard let remote = try await apollo.fetch(query: query) .data?.getSlate.fragments.slateParts else { diff --git a/PocketKit/Sources/Sync/Source.swift b/PocketKit/Sources/Sync/Source.swift index a03334d5f..fc38ed505 100644 --- a/PocketKit/Sources/Sync/Source.swift +++ b/PocketKit/Sources/Sync/Source.swift @@ -95,18 +95,18 @@ public protocol Source { public extension Source { func refreshSaves(completion: (() -> Void)?) { - self.refreshSaves(maxItems: 400, completion: completion) + self.refreshSaves(maxItems: SyncConstants.Saves.firstLoadMaxCount, completion: completion) } func refreshSaves() { - self.refreshSaves(maxItems: 400, completion: nil) + self.refreshSaves(maxItems: SyncConstants.Saves.firstLoadMaxCount, completion: nil) } func refreshArchive(completion: (() -> Void)?) { - self.refreshArchive(maxItems: 400, completion: completion) + self.refreshArchive(maxItems: SyncConstants.Archive.firstLoadMaxCount, completion: completion) } func refreshArchive() { - self.refreshArchive(maxItems: 400, completion: nil) + self.refreshArchive(maxItems: SyncConstants.Archive.firstLoadMaxCount, completion: nil) } } diff --git a/PocketKit/Sources/Sync/SyncConstants.swift b/PocketKit/Sources/Sync/SyncConstants.swift new file mode 100644 index 000000000..985ad9e8b --- /dev/null +++ b/PocketKit/Sources/Sync/SyncConstants.swift @@ -0,0 +1,40 @@ +// +// File.swift +// +// +// Created by Daniel Brooks on 3/9/23. +// + +import Foundation + +struct SyncConstants { + struct Saves { + /// How many saves we load when a user logs in. As they save and use pocket they may accumilate more, but we only download the amount of latest saves here to start. + static let firstLoadMaxCount = 500 + + /// How many saves we should load on the first login request for saves, we use a small value here so the user immediately sees content. + static let initalPageSize = 15 + + /// How many saves to load per subsequent page until we hit our load count. + static let pageSize = 30 + } + + struct Archive { + /// How many archives we load when a user logs in. As they save and use pocket they may accumilate more, but we only download the amount of latest archives here to start. + static let firstLoadMaxCount = 500 + + /// How many archives we should load on the first login request for archives, we use a small value here so the user immediately sees content. + static let initalPageSize = 15 + + /// How many archives to load per subsequent page until we hit our load count. + static let pageSize = 30 + } + + struct Home { + /// How many recomendations to pull in when we load them via getSlateLineup (ie. Home) + static let recomendationsPerSlateFromSlateLineup = 5 + + /// How many recomendations to pull in when we load them via getSlate (ie. a detail view) + static let recomendationsPerSlateDetail = 25 + } +} From 4ce5aa4aa649c22243fefd09a2f4879f1aa67630 Mon Sep 17 00:00:00 2001 From: Daniel Brooks Date: Thu, 9 Mar 2023 17:15:06 -0800 Subject: [PATCH 2/7] fix(paginate): smart paginate our results --- PocketKit/Sources/Sync/Operations/FetchArchive.swift | 2 +- PocketKit/Sources/Sync/Operations/FetchSaves.swift | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/PocketKit/Sources/Sync/Operations/FetchArchive.swift b/PocketKit/Sources/Sync/Operations/FetchArchive.swift index 107d7d788..3eca049f9 100644 --- a/PocketKit/Sources/Sync/Operations/FetchArchive.swift +++ b/PocketKit/Sources/Sync/Operations/FetchArchive.swift @@ -72,7 +72,7 @@ class FetchArchive: SyncOperation { initialDownloadState.send(.paginating(totalCount: totalCount > pagination.maxItems ? pagination.maxItems : totalCount)) } - try await updateLocalStorage(result: result) + try updateLocalStorage(result: result) pagination = pagination.nextPage(result: result, pageSize: SyncConstants.Archive.pageSize) } while pagination.shouldFetchNextPage diff --git a/PocketKit/Sources/Sync/Operations/FetchSaves.swift b/PocketKit/Sources/Sync/Operations/FetchSaves.swift index 18e29b731..63d5ac186 100644 --- a/PocketKit/Sources/Sync/Operations/FetchSaves.swift +++ b/PocketKit/Sources/Sync/Operations/FetchSaves.swift @@ -82,7 +82,7 @@ class FetchSaves: SyncOperation { initialDownloadState.send(.paginating(totalCount: totalCount > pagination.maxItems ? pagination.maxItems : totalCount)) } - try await updateLocalStorage(result: result) + try updateLocalStorage(result: result) pagination = pagination.nextPage(result: result, pageSize: SyncConstants.Saves.pageSize) } while pagination.shouldFetchNextPage @@ -96,7 +96,7 @@ class FetchSaves: SyncOperation { while shouldFetchNextPage { let query = TagsQuery(pagination: .init(pagination)) let result = try await apollo.fetch(query: query) - try await updateLocalTags(result) + try updateLocalTags(result) if let pageInfo = result.data?.user?.tags?.pageInfo { pagination.after = pageInfo.endCursor ?? .none @@ -125,7 +125,6 @@ class FetchSaves: SyncOperation { return try await apollo.fetch(query: query) } - @MainActor private func updateLocalStorage(result: GraphQLResult) throws { guard let edges = result.data?.user?.savedItems?.edges else { return @@ -153,7 +152,6 @@ class FetchSaves: SyncOperation { try space.save() } - @MainActor func updateLocalTags(_ result: GraphQLResult) throws { result.data?.user?.tags?.edges?.forEach { edge in guard let node = edge?.node else { return } From 1cc1656632cceaa1fb8f2a3e748669b2977210ec Mon Sep 17 00:00:00 2001 From: Daniel Brooks Date: Thu, 9 Mar 2023 17:31:39 -0800 Subject: [PATCH 3/7] fix(pagination): ensuring we pagintate smartly --- PocketKit/Sources/Sync/Operations/FetchArchive.swift | 3 ++- PocketKit/Sources/Sync/Operations/FetchSaves.swift | 9 ++++----- .../Sources/Sync/Operations/SyncOperationFactory.swift | 6 ------ PocketKit/Sources/Sync/PocketSource.swift | 4 ---- 4 files changed, 6 insertions(+), 16 deletions(-) diff --git a/PocketKit/Sources/Sync/Operations/FetchArchive.swift b/PocketKit/Sources/Sync/Operations/FetchArchive.swift index 3eca049f9..cfa72ae10 100644 --- a/PocketKit/Sources/Sync/Operations/FetchArchive.swift +++ b/PocketKit/Sources/Sync/Operations/FetchArchive.swift @@ -72,7 +72,7 @@ class FetchArchive: SyncOperation { initialDownloadState.send(.paginating(totalCount: totalCount > pagination.maxItems ? pagination.maxItems : totalCount)) } - try updateLocalStorage(result: result) + try await updateLocalStorage(result: result) pagination = pagination.nextPage(result: result, pageSize: SyncConstants.Archive.pageSize) } while pagination.shouldFetchNextPage @@ -98,6 +98,7 @@ class FetchArchive: SyncOperation { return try await apollo.fetch(query: query) } + @MainActor private func updateLocalStorage(result: GraphQLResult) throws { guard let edges = result.data?.user?.savedItems?.edges else { return diff --git a/PocketKit/Sources/Sync/Operations/FetchSaves.swift b/PocketKit/Sources/Sync/Operations/FetchSaves.swift index 63d5ac186..c8483567a 100644 --- a/PocketKit/Sources/Sync/Operations/FetchSaves.swift +++ b/PocketKit/Sources/Sync/Operations/FetchSaves.swift @@ -10,7 +10,6 @@ class FetchSaves: SyncOperation { private let space: Space private let events: SyncEvents private let initialDownloadState: CurrentValueSubject - private let maxItems: Int private let lastRefresh: LastRefresh init( @@ -19,14 +18,12 @@ class FetchSaves: SyncOperation { space: Space, events: SyncEvents, initialDownloadState: CurrentValueSubject, - maxItems: Int, lastRefresh: LastRefresh ) { self.user = user self.apollo = apollo self.space = space self.events = events - self.maxItems = maxItems self.lastRefresh = lastRefresh self.initialDownloadState = initialDownloadState } @@ -82,7 +79,7 @@ class FetchSaves: SyncOperation { initialDownloadState.send(.paginating(totalCount: totalCount > pagination.maxItems ? pagination.maxItems : totalCount)) } - try updateLocalStorage(result: result) + try await updateLocalStorage(result: result) pagination = pagination.nextPage(result: result, pageSize: SyncConstants.Saves.pageSize) } while pagination.shouldFetchNextPage @@ -96,7 +93,7 @@ class FetchSaves: SyncOperation { while shouldFetchNextPage { let query = TagsQuery(pagination: .init(pagination)) let result = try await apollo.fetch(query: query) - try updateLocalTags(result) + try await updateLocalTags(result) if let pageInfo = result.data?.user?.tags?.pageInfo { pagination.after = pageInfo.endCursor ?? .none @@ -125,6 +122,7 @@ class FetchSaves: SyncOperation { return try await apollo.fetch(query: query) } + @MainActor private func updateLocalStorage(result: GraphQLResult) throws { guard let edges = result.data?.user?.savedItems?.edges else { return @@ -152,6 +150,7 @@ class FetchSaves: SyncOperation { try space.save() } + @MainActor func updateLocalTags(_ result: GraphQLResult) throws { result.data?.user?.tags?.edges?.forEach { edge in guard let node = edge?.node else { return } diff --git a/PocketKit/Sources/Sync/Operations/SyncOperationFactory.swift b/PocketKit/Sources/Sync/Operations/SyncOperationFactory.swift index 98d06a323..ed7d699a6 100644 --- a/PocketKit/Sources/Sync/Operations/SyncOperationFactory.swift +++ b/PocketKit/Sources/Sync/Operations/SyncOperationFactory.swift @@ -12,7 +12,6 @@ protocol SyncOperationFactory { space: Space, events: SyncEvents, initialDownloadState: CurrentValueSubject, - maxItems: Int, lastRefresh: LastRefresh ) -> SyncOperation @@ -21,7 +20,6 @@ protocol SyncOperationFactory { space: Space, events: SyncEvents, initialDownloadState: CurrentValueSubject, - maxItems: Int, lastRefresh: LastRefresh ) -> SyncOperation @@ -53,7 +51,6 @@ class OperationFactory: SyncOperationFactory { space: Space, events: SyncEvents, initialDownloadState: CurrentValueSubject, - maxItems: Int, lastRefresh: LastRefresh ) -> SyncOperation { return FetchSaves( @@ -62,7 +59,6 @@ class OperationFactory: SyncOperationFactory { space: space, events: events, initialDownloadState: initialDownloadState, - maxItems: maxItems, lastRefresh: lastRefresh ) } @@ -72,7 +68,6 @@ class OperationFactory: SyncOperationFactory { space: Space, events: SyncEvents, initialDownloadState: CurrentValueSubject, - maxItems: Int, lastRefresh: LastRefresh ) -> SyncOperation { return FetchArchive( @@ -80,7 +75,6 @@ class OperationFactory: SyncOperationFactory { space: space, events: events, initialDownloadState: initialDownloadState, - maxItems: maxItems, lastRefresh: lastRefresh ) } diff --git a/PocketKit/Sources/Sync/PocketSource.swift b/PocketKit/Sources/Sync/PocketSource.swift index 5bfb8cc9f..fe3b90fd5 100644 --- a/PocketKit/Sources/Sync/PocketSource.swift +++ b/PocketKit/Sources/Sync/PocketSource.swift @@ -215,7 +215,6 @@ extension PocketSource { space: space, events: _events, initialDownloadState: initialSavesDownloadState, - maxItems: maxItems, lastRefresh: lastRefresh ) @@ -232,7 +231,6 @@ extension PocketSource { space: space, events: _events, initialDownloadState: initialArchiveDownloadState, - maxItems: maxItems, lastRefresh: lastRefresh ) @@ -523,7 +521,6 @@ extension PocketSource { space: space, events: _events, initialDownloadState: initialSavesDownloadState, - maxItems: maxItems, lastRefresh: lastRefresh ) enqueue(operation: operation, persistentTask: persistentTask) @@ -533,7 +530,6 @@ extension PocketSource { space: space, events: _events, initialDownloadState: initialArchiveDownloadState, - maxItems: maxItems, lastRefresh: lastRefresh ) enqueue(operation: operation, persistentTask: persistentTask) From a2a162820edb4f405493de15b6a670b1547291a4 Mon Sep 17 00:00:00 2001 From: Daniel Brooks Date: Fri, 10 Mar 2023 08:31:28 -0800 Subject: [PATCH 4/7] fix(tests): updating pagination tests --- .../SyncTests/Fixtures/large-list-1.json | 883 ++++++++- .../SyncTests/Fixtures/large-list-2.json | 1701 ++++++++++++++++- .../SyncTests/Fixtures/large-list-3.json | 1701 ++++++++++++++++- .../PocketSourceTests+networkMonitoring.swift | 4 +- ...ocketSourceTests+restoringOperations.swift | 4 +- .../Tests/SyncTests/PocketSourceTests.swift | 6 +- .../SyncTests/Support/FetchSavesTests.swift | 27 +- .../Support/MockOperationFactory.swift | 16 +- 8 files changed, 4120 insertions(+), 222 deletions(-) diff --git a/PocketKit/Tests/SyncTests/Fixtures/large-list-1.json b/PocketKit/Tests/SyncTests/Fixtures/large-list-1.json index 8fc1c1e5c..2f5cf1106 100644 --- a/PocketKit/Tests/SyncTests/Fixtures/large-list-1.json +++ b/PocketKit/Tests/SyncTests/Fixtures/large-list-1.json @@ -1,68 +1,829 @@ { - "data": { - "user": { + "data": { + "user": { + "__typename": "[type-name-here]", + "isPremium": true, + "savedItems": { + "__typename": "[type-name-here]", + "totalCount": 1001, + "pageInfo": { + "__typename": "[type-name-here]", + "hasNextPage": true, + "endCursor": "cursor-1" + }, + "edges": [ + { "__typename": "[type-name-here]", - "isPremium": true, - "savedItems": { - "__typename": "[type-name-here]", - "totalCount": 3, - "pageInfo": { + "cursor": "cursor-1", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-1", + "url": "https://example.com/item-1", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-1", + "givenUrl": "https://given.example.com/item-1", + "resolvedUrl": "https://resolved.example.com/item-1", + "title": "Item 1", + "topImageUrl": "https://example.com/item-1/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-1/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-1/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-1", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-1", + "url": "https://example.com/item-1", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-1", + "givenUrl": "https://given.example.com/item-1", + "resolvedUrl": "https://resolved.example.com/item-1", + "title": "Item 1", + "topImageUrl": "https://example.com/item-1/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-1/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-1/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-1", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-1", + "url": "https://example.com/item-1", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-1", + "givenUrl": "https://given.example.com/item-1", + "resolvedUrl": "https://resolved.example.com/item-1", + "title": "Item 1", + "topImageUrl": "https://example.com/item-1/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-1/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-1/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-1", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-1", + "url": "https://example.com/item-1", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-1", + "givenUrl": "https://given.example.com/item-1", + "resolvedUrl": "https://resolved.example.com/item-1", + "title": "Item 1", + "topImageUrl": "https://example.com/item-1/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-1/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-1/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-1", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-1", + "url": "https://example.com/item-1", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-1", + "givenUrl": "https://given.example.com/item-1", + "resolvedUrl": "https://resolved.example.com/item-1", + "title": "Item 1", + "topImageUrl": "https://example.com/item-1/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-1/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-1/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-1", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-1", + "url": "https://example.com/item-1", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-1", + "givenUrl": "https://given.example.com/item-1", + "resolvedUrl": "https://resolved.example.com/item-1", + "title": "Item 1", + "topImageUrl": "https://example.com/item-1/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-1/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-1/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-1", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-1", + "url": "https://example.com/item-1", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-1", + "givenUrl": "https://given.example.com/item-1", + "resolvedUrl": "https://resolved.example.com/item-1", + "title": "Item 1", + "topImageUrl": "https://example.com/item-1/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-1/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-1/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-1", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-1", + "url": "https://example.com/item-1", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-1", + "givenUrl": "https://given.example.com/item-1", + "resolvedUrl": "https://resolved.example.com/item-1", + "title": "Item 1", + "topImageUrl": "https://example.com/item-1/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-1/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-1/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-1", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-1", + "url": "https://example.com/item-1", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-1", + "givenUrl": "https://given.example.com/item-1", + "resolvedUrl": "https://resolved.example.com/item-1", + "title": "Item 1", + "topImageUrl": "https://example.com/item-1/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-1/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-1/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-1", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-1", + "url": "https://example.com/item-1", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-1", + "givenUrl": "https://given.example.com/item-1", + "resolvedUrl": "https://resolved.example.com/item-1", + "title": "Item 1", + "topImageUrl": "https://example.com/item-1/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-1/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-1/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-1", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-1", + "url": "https://example.com/item-1", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-1", + "givenUrl": "https://given.example.com/item-1", + "resolvedUrl": "https://resolved.example.com/item-1", + "title": "Item 1", + "topImageUrl": "https://example.com/item-1/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-1/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-1/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-1", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-1", + "url": "https://example.com/item-1", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-1", + "givenUrl": "https://given.example.com/item-1", + "resolvedUrl": "https://resolved.example.com/item-1", + "title": "Item 1", + "topImageUrl": "https://example.com/item-1/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-1/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-1/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-1", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-1", + "url": "https://example.com/item-1", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-1", + "givenUrl": "https://given.example.com/item-1", + "resolvedUrl": "https://resolved.example.com/item-1", + "title": "Item 1", + "topImageUrl": "https://example.com/item-1/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-1/domain-logo.jpg" + }, + "images": [ + { "__typename": "[type-name-here]", - "hasNextPage": true, - "endCursor": "cursor-1" + "height": 1, + "width": 2, + "src": "http://example.com/item-1/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-1", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-1", + "url": "https://example.com/item-1", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-1", + "givenUrl": "https://given.example.com/item-1", + "resolvedUrl": "https://resolved.example.com/item-1", + "title": "Item 1", + "topImageUrl": "https://example.com/item-1/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-1/domain-logo.jpg" }, - "edges": [ - { - "__typename": "[type-name-here]", - "cursor": "cursor-1", - "node": { - "__typename": "[type-name-here]", - "remoteID": "saved-item-1", - "url": "https://example.com/item-1", - "_createdAt": 0, - "_deletedAt": null, - "archivedAt": null, - "isArchived": false, - "isFavorite": false, - "tags": [], - "item": { - "__typename": "Item", - "remoteID": "item-1", - "givenUrl": "https://given.example.com/item-1", - "resolvedUrl": "https://resolved.example.com/item-1", - "title": "Item 1", - "topImageUrl": "https://example.com/item-1/top-image.jpg", - "domain": null, - "language": "en", - "timeToRead": 6, - "marticle": [], - "excerpt": "Cursus Aenean Elit", - "datePublished": "2021-01-01 12:01:01", - "authors": [], - "domainMetadata": { - "__typename": "[type-name-here]", - "name": "WIRED", - "logo": "http://example.com/item-1/domain-logo.jpg" - }, - "images": [ - { - "__typename": "[type-name-here]", - "height": 1, - "width": 2, - "src": "http://example.com/item-1/image-1.jpg", - "imageId": 1 - } - ], - "isArticle": true, - "hasImage": "HAS_IMAGES", - "hasVideo": "HAS_VIDEOS", - "syndicatedArticle": null - } - } - } - ] + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-1/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-1", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-1", + "url": "https://example.com/item-1", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-1", + "givenUrl": "https://given.example.com/item-1", + "resolvedUrl": "https://resolved.example.com/item-1", + "title": "Item 1", + "topImageUrl": "https://example.com/item-1/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-1/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-1/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } } - } + } + ] + } } + } } - diff --git a/PocketKit/Tests/SyncTests/Fixtures/large-list-2.json b/PocketKit/Tests/SyncTests/Fixtures/large-list-2.json index e7d0be768..14cfe47f5 100644 --- a/PocketKit/Tests/SyncTests/Fixtures/large-list-2.json +++ b/PocketKit/Tests/SyncTests/Fixtures/large-list-2.json @@ -1,68 +1,1639 @@ { - "data": { - "user": { - "__typename": "[type-name-here]", - "isPremium": true, - "savedItems": { - "__typename": "[type-name-here]", - "totalCount": 3, - "pageInfo": { - "__typename": "[type-name-here]", - "hasNextPage": true, - "endCursor": "cursor-2" - }, - "edges": [ - { - "__typename": "[type-name-here]", - "cursor": "cursor-2", - "node": { - "__typename": "[type-name-here]", - "remoteID": "saved-item-2", - "url": "https://example.com/item-2", - "_createdAt": 0, - "_deletedAt": null, - "archivedAt": null, - "isArchived": false, - "isFavorite": false, - "tags": [], - "item": { - "__typename": "Item", - "remoteID": "item-2", - "givenUrl": "https://given.example.com/item-2", - "resolvedUrl": "https://resolved.example.com/item-2", - "title": "Item 2", - "topImageUrl": "https://example.com/item-2/top-image.jpg", - "domain": null, - "language": "en", - "timeToRead": 6, - "marticle": [], - "excerpt": "Cursus Aenean Elit", - "datePublished": "2021-01-01 12:01:01", - "authors": [], - "domainMetadata": { - "__typename": "[type-name-here]", - "name": "WIRED", - "logo": "http://example.com/item-2/domain-logo.jpg" - }, - "images": [ - { - "__typename": "[type-name-here]", - "height": 1, - "width": 2, - "src": "http://example.com/item-2/image-1.jpg", - "imageId": 1 - } - ], - "isArticle": true, - "hasImage": "HAS_IMAGES", - "hasVideo": "HAS_VIDEOS", - "syndicatedArticle": null - } - } - } - ] - } - } + "data": { + "user": { + "__typename": "[type-name-here]", + "isPremium": true, + "savedItems": { + "__typename": "[type-name-here]", + "totalCount": 1001, + "pageInfo": { + "__typename": "[type-name-here]", + "hasNextPage": true, + "endCursor": "cursor-2" + }, + "edges": [ + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-2", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-2", + "url": "https://example.com/item-2", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-2", + "givenUrl": "https://given.example.com/item-2", + "resolvedUrl": "https://resolved.example.com/item-2", + "title": "Item 2", + "topImageUrl": "https://example.com/item-2/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-2/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-2/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + } + ] + } } + } } - diff --git a/PocketKit/Tests/SyncTests/Fixtures/large-list-3.json b/PocketKit/Tests/SyncTests/Fixtures/large-list-3.json index 2bfe39c17..df33b6719 100644 --- a/PocketKit/Tests/SyncTests/Fixtures/large-list-3.json +++ b/PocketKit/Tests/SyncTests/Fixtures/large-list-3.json @@ -1,68 +1,1639 @@ { - "data": { - "user": { - "__typename": "[type-name-here]", - "isPremium": true, - "savedItems": { - "__typename": "[type-name-here]", - "totalCount": 3, - "pageInfo": { - "__typename": "[type-name-here]", - "hasNextPage": true, - "endCursor": "cursor-3" - }, - "edges": [ - { - "__typename": "[type-name-here]", - "cursor": "cursor-3", - "node": { - "__typename": "[type-name-here]", - "remoteID": "saved-item-3", - "url": "https://example.com/item-3", - "_createdAt": 0, - "_deletedAt": null, - "archivedAt": null, - "isArchived": false, - "isFavorite": false, - "tags": [], - "item": { - "__typename": "Item", - "remoteID": "item-3", - "givenUrl": "https://given.example.com/item-3", - "resolvedUrl": "https://resolved.example.com/item-3", - "title": "Item 3", - "topImageUrl": "https://example.com/item-3/top-image.jpg", - "domain": null, - "language": "en", - "timeToRead": 6, - "marticle": [], - "excerpt": "Cursus Aenean Elit", - "datePublished": "2021-01-01 12:01:01", - "authors": [], - "domainMetadata": { - "__typename": "[type-name-here]", - "name": "WIRED", - "logo": "http://example.com/item-3/domain-logo.jpg" - }, - "images": [ - { - "__typename": "[type-name-here]", - "height": 1, - "width": 2, - "src": "http://example.com/item-3/image-1.jpg", - "imageId": 1 - } - ], - "isArticle": true, - "hasImage": "HAS_IMAGES", - "hasVideo": "HAS_VIDEOS", - "syndicatedArticle": null - } - } - } - ] - } - } + "data": { + "user": { + "__typename": "[type-name-here]", + "isPremium": true, + "savedItems": { + "__typename": "[type-name-here]", + "totalCount": 1001, + "pageInfo": { + "__typename": "[type-name-here]", + "hasNextPage": true, + "endCursor": "cursor-3" + }, + "edges": [ + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + }, + { + "__typename": "[type-name-here]", + "cursor": "cursor-3", + "node": { + "__typename": "[type-name-here]", + "remoteID": "saved-item-3", + "url": "https://example.com/item-3", + "_createdAt": 0, + "_deletedAt": null, + "archivedAt": null, + "isArchived": false, + "isFavorite": false, + "tags": [ + + ], + "item": { + "__typename": "Item", + "remoteID": "item-3", + "givenUrl": "https://given.example.com/item-3", + "resolvedUrl": "https://resolved.example.com/item-3", + "title": "Item 3", + "topImageUrl": "https://example.com/item-3/top-image.jpg", + "domain": null, + "language": "en", + "timeToRead": 6, + "marticle": [ + + ], + "excerpt": "Cursus Aenean Elit", + "datePublished": "2021-01-01 12:01:01", + "authors": [ + + ], + "domainMetadata": { + "__typename": "[type-name-here]", + "name": "WIRED", + "logo": "http://example.com/item-3/domain-logo.jpg" + }, + "images": [ + { + "__typename": "[type-name-here]", + "height": 1, + "width": 2, + "src": "http://example.com/item-3/image-1.jpg", + "imageId": 1 + } + ], + "isArticle": true, + "hasImage": "HAS_IMAGES", + "hasVideo": "HAS_VIDEOS", + "syndicatedArticle": null + } + } + } + ] + } } + } } - diff --git a/PocketKit/Tests/SyncTests/PocketSourceTests+networkMonitoring.swift b/PocketKit/Tests/SyncTests/PocketSourceTests+networkMonitoring.swift index 5a38425fc..0750dd8ad 100644 --- a/PocketKit/Tests/SyncTests/PocketSourceTests+networkMonitoring.swift +++ b/PocketKit/Tests/SyncTests/PocketSourceTests+networkMonitoring.swift @@ -10,7 +10,7 @@ extension PocketSourceTests { func test_enqueueingOperations_whenNetworkPathIsUnsatisfied_doesNotExecuteOperations() { sessionProvider.session = MockSession() - operations.stubFetchSaves { _, _, _, _, _, _ in + operations.stubFetchSaves { _, _, _, _, _ in TestSyncOperation { XCTFail("Operation should not be executed while network path is unsatisfied") } @@ -33,7 +33,7 @@ extension PocketSourceTests { } let expectFetchList = expectation(description: "execute the fetch list operation") - operations.stubFetchSaves { _, _, _, _, _, _ in + operations.stubFetchSaves { _, _, _, _, _ in TestSyncOperation { expectFetchList.fulfill() } diff --git a/PocketKit/Tests/SyncTests/PocketSourceTests+restoringOperations.swift b/PocketKit/Tests/SyncTests/PocketSourceTests+restoringOperations.swift index a1c9aa85d..9b9bf7955 100644 --- a/PocketKit/Tests/SyncTests/PocketSourceTests+restoringOperations.swift +++ b/PocketKit/Tests/SyncTests/PocketSourceTests+restoringOperations.swift @@ -8,7 +8,7 @@ extension PocketSourceTests { sessionProvider.session = MockSession() let fetchList = expectation(description: "fetchList operation executed") - operations.stubFetchSaves { _, _, _, _, _, _ in + operations.stubFetchSaves { _, _, _, _, _ in TestSyncOperation { fetchList.fulfill() } } @@ -42,7 +42,7 @@ extension PocketSourceTests { source.drain { done.fulfill() } wait(for: [done], timeout: 1) - operations.stubFetchSaves { _, _, _, _, _, _ in + operations.stubFetchSaves { _, _, _, _, _ in XCTFail("Operation should not be re-created after succeeding") return TestSyncOperation { } } diff --git a/PocketKit/Tests/SyncTests/PocketSourceTests.swift b/PocketKit/Tests/SyncTests/PocketSourceTests.swift index cae666f88..e8e01f9b0 100644 --- a/PocketKit/Tests/SyncTests/PocketSourceTests.swift +++ b/PocketKit/Tests/SyncTests/PocketSourceTests.swift @@ -80,7 +80,7 @@ class PocketSourceTests: XCTestCase { let session = MockSession() sessionProvider.session = session let expectationToRunOperation = expectation(description: "Run operation") - operations.stubFetchSaves { _, _, _, _, _, _ in + operations.stubFetchSaves { _, _, _, _, _ in TestSyncOperation { expectationToRunOperation.fulfill() } @@ -94,7 +94,7 @@ class PocketSourceTests: XCTestCase { func test_refreshWithCompletion_callsCompletionWhenFinished() { sessionProvider.session = MockSession() - operations.stubFetchSaves { _, _, _, _, _, _ in + operations.stubFetchSaves { _, _, _, _, _ in TestSyncOperation { } } @@ -110,7 +110,7 @@ class PocketSourceTests: XCTestCase { func test_refresh_whenTokenIsNil_callsCompletion() { sessionProvider.session = nil - operations.stubFetchSaves { _, _, _, _, _, _ in + operations.stubFetchSaves { _, _, _, _, _ in TestSyncOperation { } } diff --git a/PocketKit/Tests/SyncTests/Support/FetchSavesTests.swift b/PocketKit/Tests/SyncTests/Support/FetchSavesTests.swift index dee927f5d..f3a12ac6d 100644 --- a/PocketKit/Tests/SyncTests/Support/FetchSavesTests.swift +++ b/PocketKit/Tests/SyncTests/Support/FetchSavesTests.swift @@ -4,6 +4,7 @@ import CoreData import Apollo import PocketGraph import SharedPocketKit +import Foundation @testable import Sync @@ -38,7 +39,6 @@ class FetchSavesTests: XCTestCase { space: Space? = nil, events: SyncEvents? = nil, initialDownloadState: CurrentValueSubject? = nil, - maxItems: Int = 400, lastRefresh: LastRefresh? = nil ) -> FetchSaves { FetchSaves( @@ -47,7 +47,6 @@ class FetchSavesTests: XCTestCase { space: space ?? self.space, events: events ?? self.events, initialDownloadState: initialDownloadState ?? self.initialDownloadState, - maxItems: maxItems, lastRefresh: lastRefresh ?? self.lastRefresh ) } @@ -199,6 +198,9 @@ class FetchSavesTests: XCTestCase { func test_refresh_whenItemCountExceedsMax_fetchesMaxNumberOfItems() async throws { var fetches = 0 + let pages = Int(ceil(Double((SyncConstants.Saves.firstLoadMaxCount - SyncConstants.Saves.initalPageSize) / SyncConstants.Saves.pageSize))) + 2 + print(pages) + user.stubSetStatus { _ in } apollo.setupTagsResponse() apollo.stubFetch { (query: FetchSavesQuery, _, _, queue, completion) -> Apollo.Cancellable in @@ -207,17 +209,22 @@ class FetchSavesTests: XCTestCase { let result: Fixture switch fetches { case 0: - XCTAssertEqual(query.pagination.unwrapped?.first, 3) + XCTAssertEqual(query.pagination.unwrapped?.first, 15) result = Fixture.load(name: "large-list-1") case 1: XCTAssertEqual(query.pagination.unwrapped?.after.unwrapped, "cursor-1") - XCTAssertEqual(query.pagination.unwrapped?.first.unwrapped, 2) + XCTAssertEqual(query.pagination.unwrapped?.first.unwrapped, 30) result = Fixture.load(name: "large-list-2") case 2: XCTAssertEqual(query.pagination.unwrapped?.after.unwrapped, "cursor-2") - XCTAssertEqual(query.pagination.unwrapped?.first.unwrapped, 1) + XCTAssertEqual(query.pagination.unwrapped?.first.unwrapped, 30) + + result = Fixture.load(name: "large-list-3") + case 3...pages: + XCTAssertEqual(query.pagination.unwrapped?.after.unwrapped, "cursor-3") + XCTAssertEqual(query.pagination.unwrapped?.first.unwrapped, 30) result = Fixture.load(name: "large-list-3") default: @@ -225,18 +232,14 @@ class FetchSavesTests: XCTestCase { return MockCancellable() } - queue.async { - completion?(.success(result.asGraphQLResult(from: query))) - } + completion?(.success(result.asGraphQLResult(from: query))) return MockCancellable() } - let service = subject(maxItems: 3) + let service = subject() _ = await service.execute() - - let items = try space.fetchSavedItems() - XCTAssertEqual(items.count, 3) + XCTAssertEqual(fetches, pages) } func test_refresh_whenUpdatedSinceIsPresent_includesUpdatedSinceFilter() async { diff --git a/PocketKit/Tests/SyncTests/Support/MockOperationFactory.swift b/PocketKit/Tests/SyncTests/Support/MockOperationFactory.swift index 98c298911..81234209d 100644 --- a/PocketKit/Tests/SyncTests/Support/MockOperationFactory.swift +++ b/PocketKit/Tests/SyncTests/Support/MockOperationFactory.swift @@ -19,8 +19,7 @@ extension MockOperationFactory { ApolloClientProtocol, Space, SyncEvents, - CurrentValueSubject, - Int + CurrentValueSubject ) -> SyncOperation struct FetchSavesCall { @@ -29,7 +28,6 @@ extension MockOperationFactory { let space: Space let events: SyncEvents let initialDownloadState: CurrentValueSubject - let maxItems: Int let lastRefresh: LastRefresh } @@ -43,7 +41,6 @@ extension MockOperationFactory { space: Space, events: SyncEvents, initialDownloadState: CurrentValueSubject, - maxItems: Int, lastRefresh: LastRefresh ) -> SyncOperation { guard let impl = implementations["fetchSaves"] as? FetchSavesImpl else { @@ -57,12 +54,11 @@ extension MockOperationFactory { space: space, events: events, initialDownloadState: initialDownloadState, - maxItems: maxItems, lastRefresh: lastRefresh ) ] - return impl(user, apollo, space, events, initialDownloadState, maxItems) + return impl(user, apollo, space, events, initialDownloadState) } func fetchSavesCall(at index: Int) -> FetchSavesCall? { @@ -80,8 +76,7 @@ extension MockOperationFactory { ApolloClientProtocol, Space, SyncEvents, - CurrentValueSubject, - Int + CurrentValueSubject ) -> SyncOperation struct FetchArchiveCall { @@ -89,7 +84,6 @@ extension MockOperationFactory { let space: Space let events: SyncEvents let initialDownloadState: CurrentValueSubject - let maxItems: Int let lastRefresh: LastRefresh } @@ -102,7 +96,6 @@ extension MockOperationFactory { space: Space, events: SyncEvents, initialDownloadState: CurrentValueSubject, - maxItems: Int, lastRefresh: LastRefresh ) -> SyncOperation { guard let impl = implementations["fetchArchive"] as? FetchArchiveImpl else { @@ -115,12 +108,11 @@ extension MockOperationFactory { space: space, events: events, initialDownloadState: initialDownloadState, - maxItems: maxItems, lastRefresh: lastRefresh ) ] - return impl(apollo, space, events, initialDownloadState, maxItems) + return impl(apollo, space, events, initialDownloadState) } func fetchArchiveCall(at index: Int) -> FetchArchiveCall? { From 17bdfdb9ba47aed3b96eee6cb251435020b4c059 Mon Sep 17 00:00:00 2001 From: Daniel Brooks Date: Fri, 10 Mar 2023 08:38:28 -0800 Subject: [PATCH 5/7] fix(archive): load archive on login --- PocketKit/Sources/PocketKit/Root/RootViewModel.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/PocketKit/Sources/PocketKit/Root/RootViewModel.swift b/PocketKit/Sources/PocketKit/Root/RootViewModel.swift index 149f095a0..172312cc8 100644 --- a/PocketKit/Sources/PocketKit/Root/RootViewModel.swift +++ b/PocketKit/Sources/PocketKit/Root/RootViewModel.swift @@ -104,6 +104,7 @@ class RootViewModel { tracker.addPersistentEntity(UserEntity(guid: session.guid, userID: session.userIdentifier)) Log.setUserID(session.userIdentifier) source.refreshSaves() + source.refreshArchive() } private func tearDownSession() { From a4e41fbe44beff8ff0a016c3c9b6b72dff225a6f Mon Sep 17 00:00:00 2001 From: Daniel Brooks Date: Fri, 10 Mar 2023 10:11:54 -0800 Subject: [PATCH 6/7] fix(pagination): fix some calls --- .../xcshareddata/xcschemes/Pocket (iOS).xcscheme | 7 +++++++ PocketKit/Sources/Sync/Operations/FetchArchive.swift | 2 +- PocketKit/Sources/Sync/Operations/FetchSaves.swift | 2 +- PocketKit/Sources/Sync/Operations/SyncTask.swift | 4 ++-- PocketKit/Sources/Sync/PocketSource.swift | 12 ++++++------ PocketKit/Sources/Sync/Source+async.swift | 4 ++-- PocketKit/Sources/Sync/Source.swift | 12 ++++++------ PocketKit/Sources/Sync/SyncConstants.swift | 9 +++------ 8 files changed, 28 insertions(+), 24 deletions(-) diff --git a/Pocket.xcodeproj/xcshareddata/xcschemes/Pocket (iOS).xcscheme b/Pocket.xcodeproj/xcshareddata/xcschemes/Pocket (iOS).xcscheme index 6efe017f5..00604f565 100644 --- a/Pocket.xcodeproj/xcshareddata/xcschemes/Pocket (iOS).xcscheme +++ b/Pocket.xcodeproj/xcshareddata/xcschemes/Pocket (iOS).xcscheme @@ -338,6 +338,13 @@ isEnabled = "NO"> + + + + pagination.maxItems ? pagination.maxItems : totalCount)) + initialDownloadState.send(.paginating(totalCount: min(totalCount, pagination.maxItems))) } try await updateLocalStorage(result: result) diff --git a/PocketKit/Sources/Sync/Operations/FetchSaves.swift b/PocketKit/Sources/Sync/Operations/FetchSaves.swift index c8483567a..eea9a1d1f 100644 --- a/PocketKit/Sources/Sync/Operations/FetchSaves.swift +++ b/PocketKit/Sources/Sync/Operations/FetchSaves.swift @@ -76,7 +76,7 @@ class FetchSaves: SyncOperation { if case .started = initialDownloadState.value, let totalCount = result.data?.user?.savedItems?.totalCount, pagination.cursor == nil { - initialDownloadState.send(.paginating(totalCount: totalCount > pagination.maxItems ? pagination.maxItems : totalCount)) + initialDownloadState.send(.paginating(totalCount: min(totalCount, pagination.maxItems))) } try await updateLocalStorage(result: result) diff --git a/PocketKit/Sources/Sync/Operations/SyncTask.swift b/PocketKit/Sources/Sync/Operations/SyncTask.swift index a70e58067..a38a034be 100644 --- a/PocketKit/Sources/Sync/Operations/SyncTask.swift +++ b/PocketKit/Sources/Sync/Operations/SyncTask.swift @@ -1,8 +1,8 @@ import Foundation enum SyncTask: Codable { - case fetchSaves(maxItems: Int) - case fetchArchive(maxItems: Int) + case fetchSaves + case fetchArchive case favorite(remoteID: String) case unfavorite(remoteID: String) case delete(remoteID: String) diff --git a/PocketKit/Sources/Sync/PocketSource.swift b/PocketKit/Sources/Sync/PocketSource.swift index fe3b90fd5..eddcc1663 100644 --- a/PocketKit/Sources/Sync/PocketSource.swift +++ b/PocketKit/Sources/Sync/PocketSource.swift @@ -204,7 +204,7 @@ public class PocketSource: Source { // MARK: - Saves/Archive items extension PocketSource { - public func refreshSaves(maxItems: Int, completion: (() -> Void)? = nil) { + public func refreshSaves(completion: (() -> Void)? = nil) { if lastRefresh.lastRefreshSaves == nil { initialSavesDownloadState.send(.started) } @@ -218,10 +218,10 @@ extension PocketSource { lastRefresh: lastRefresh ) - enqueue(operation: operation, task: .fetchSaves(maxItems: maxItems), completion: completion) + enqueue(operation: operation, task: .fetchSaves, completion: completion) } - public func refreshArchive(maxItems: Int, completion: (() -> Void)? = nil) { + public func refreshArchive(completion: (() -> Void)? = nil) { if lastRefresh.lastRefreshArchive == nil { initialArchiveDownloadState.send(.started) } @@ -234,7 +234,7 @@ extension PocketSource { lastRefresh: lastRefresh ) - enqueue(operation: operation, task: .fetchSaves(maxItems: maxItems), completion: completion) + enqueue(operation: operation, task: .fetchSaves, completion: completion) } public func favorite(item: SavedItem) { @@ -514,7 +514,7 @@ extension PocketSource { mutation: FavoriteItemMutation(itemID: remoteID) ) enqueue(operation: operation, persistentTask: persistentTask) - case .fetchSaves(let maxItems): + case .fetchSaves: let operation = operations.fetchSaves( user: user, apollo: apollo, @@ -524,7 +524,7 @@ extension PocketSource { lastRefresh: lastRefresh ) enqueue(operation: operation, persistentTask: persistentTask) - case .fetchArchive(let maxItems): + case .fetchArchive: let operation = operations.fetchArchive( apollo: apollo, space: space, diff --git a/PocketKit/Sources/Sync/Source+async.swift b/PocketKit/Sources/Sync/Source+async.swift index 6ccb2db92..9b44ca4a1 100644 --- a/PocketKit/Sources/Sync/Source+async.swift +++ b/PocketKit/Sources/Sync/Source+async.swift @@ -1,7 +1,7 @@ extension Source { - public func refresh(maxItems: Int = 400) async { + public func refresh() async { await withCheckedContinuation { (continuation: CheckedContinuation) in - refreshSaves(maxItems: maxItems) { + refreshSaves { continuation.resume(returning: ()) } } diff --git a/PocketKit/Sources/Sync/Source.swift b/PocketKit/Sources/Sync/Source.swift index fc38ed505..7e51f987c 100644 --- a/PocketKit/Sources/Sync/Source.swift +++ b/PocketKit/Sources/Sync/Source.swift @@ -32,9 +32,9 @@ public protocol Source { func object(id: NSManagedObjectID) -> T? - func refreshSaves(maxItems: Int, completion: (() -> Void)?) + func refreshSaves(completion: (() -> Void)?) - func refreshArchive(maxItems: Int, completion: (() -> Void)?) + func refreshArchive(completion: (() -> Void)?) func retryImmediately() @@ -95,18 +95,18 @@ public protocol Source { public extension Source { func refreshSaves(completion: (() -> Void)?) { - self.refreshSaves(maxItems: SyncConstants.Saves.firstLoadMaxCount, completion: completion) + self.refreshSaves(completion: completion) } func refreshSaves() { - self.refreshSaves(maxItems: SyncConstants.Saves.firstLoadMaxCount, completion: nil) + self.refreshSaves(completion: nil) } func refreshArchive(completion: (() -> Void)?) { - self.refreshArchive(maxItems: SyncConstants.Archive.firstLoadMaxCount, completion: completion) + self.refreshArchive(completion: completion) } func refreshArchive() { - self.refreshArchive(maxItems: SyncConstants.Archive.firstLoadMaxCount, completion: nil) + self.refreshArchive(completion: nil) } } diff --git a/PocketKit/Sources/Sync/SyncConstants.swift b/PocketKit/Sources/Sync/SyncConstants.swift index 985ad9e8b..a75f756d3 100644 --- a/PocketKit/Sources/Sync/SyncConstants.swift +++ b/PocketKit/Sources/Sync/SyncConstants.swift @@ -1,9 +1,6 @@ -// -// File.swift -// -// -// Created by Daniel Brooks on 3/9/23. -// +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this +// file, You can obtain one at http://mozilla.org/MPL/2.0/. import Foundation From d44acbedf3b50e1f2e38946df430bbcc762c3ead Mon Sep 17 00:00:00 2001 From: Daniel Brooks Date: Fri, 10 Mar 2023 12:10:50 -0800 Subject: [PATCH 7/7] fix(pagination): fix tests --- PocketKit/Sources/Sync/Source.swift | 7 ------- .../Refresh/RefreshCoordinatorTests.swift | 12 ++++++------ .../SavedItemsListViewModelTests.swift | 2 +- .../PocketKitTests/Support/MockSource.swift | 18 ++++++++---------- 4 files changed, 15 insertions(+), 24 deletions(-) diff --git a/PocketKit/Sources/Sync/Source.swift b/PocketKit/Sources/Sync/Source.swift index 7e51f987c..3771bd656 100644 --- a/PocketKit/Sources/Sync/Source.swift +++ b/PocketKit/Sources/Sync/Source.swift @@ -94,18 +94,11 @@ public protocol Source { } public extension Source { - func refreshSaves(completion: (() -> Void)?) { - self.refreshSaves(completion: completion) - } func refreshSaves() { self.refreshSaves(completion: nil) } - func refreshArchive(completion: (() -> Void)?) { - self.refreshArchive(completion: completion) - } - func refreshArchive() { self.refreshArchive(completion: nil) } diff --git a/PocketKit/Tests/PocketKitTests/Refresh/RefreshCoordinatorTests.swift b/PocketKit/Tests/PocketKitTests/Refresh/RefreshCoordinatorTests.swift index 6f9985ac3..d7ea8b347 100644 --- a/PocketKit/Tests/PocketKitTests/Refresh/RefreshCoordinatorTests.swift +++ b/PocketKit/Tests/PocketKitTests/Refresh/RefreshCoordinatorTests.swift @@ -62,7 +62,7 @@ class RefreshCoordinatorTests: XCTestCase { taskScheduler.stubRegisterHandler { handler = $2; return true } taskScheduler.stubSubmit { _ in } - source.stubRefreshSaves { _, completion in + source.stubRefreshSaves { completion in completion?() } @@ -84,7 +84,7 @@ class RefreshCoordinatorTests: XCTestCase { taskScheduler.stubRegisterHandler { handler = $2; return true } taskScheduler.stubSubmit { _ in } - source.stubRefreshSaves { _, completion in + source.stubRefreshSaves { completion in // completion callback never fires } @@ -105,8 +105,8 @@ class RefreshCoordinatorTests: XCTestCase { func test_receivingAppWillEnterForegroundNotification_refreshesSource_andResolvesUnresolvedSavedItems() { taskScheduler.stubRegisterHandler { _, _, _ in true } - source.stubRefreshSaves { _, _ in } - source.stubRefreshArchive { _, _ in } + source.stubRefreshSaves { _ in } + source.stubRefreshArchive { _ in } source.stubResolveUnresolvedSavedItems { } let coordinator = subject() @@ -120,10 +120,10 @@ class RefreshCoordinatorTests: XCTestCase { } func test_coordinator_whenNoSession_doesNotRefreshSavesArchive() { - source.stubRefreshSaves { _, _ in + source.stubRefreshSaves { _ in XCTFail("Should not fetch saves") } - source.stubRefreshArchive { _, _ in + source.stubRefreshArchive { _ in XCTFail("Should not fetch archive") } source.stubResolveUnresolvedSavedItems { diff --git a/PocketKit/Tests/PocketKitTests/SavedItemsListViewModelTests.swift b/PocketKit/Tests/PocketKitTests/SavedItemsListViewModelTests.swift index eaf340e23..174404075 100644 --- a/PocketKit/Tests/PocketKitTests/SavedItemsListViewModelTests.swift +++ b/PocketKit/Tests/PocketKitTests/SavedItemsListViewModelTests.swift @@ -336,7 +336,7 @@ class SavedItemsListViewModelTests: XCTestCase { } func test_refreshSaves_callsRetryImmediatelyOnSource() { - source.stubRefreshSaves { _, _ in } + source.stubRefreshSaves { _ in } source.stubRetryImmediately { } let viewModel = subject() diff --git a/PocketKit/Tests/PocketKitTests/Support/MockSource.swift b/PocketKit/Tests/PocketKitTests/Support/MockSource.swift index dada3e220..498926ee0 100644 --- a/PocketKit/Tests/PocketKitTests/Support/MockSource.swift +++ b/PocketKit/Tests/PocketKitTests/Support/MockSource.swift @@ -57,10 +57,9 @@ extension MockSource { // MARK: - Refresh Saves extension MockSource { private static let refreshSaves = "refreshSaves" - typealias RefreshSavesImpl = (Int, (() -> Void)?) -> Void + typealias RefreshSavesImpl = ((() -> Void)?) -> Void struct RefreshSavesCall { - let maxItems: Int let completion: (() -> Void)? } @@ -68,16 +67,16 @@ extension MockSource { implementations[Self.refreshSaves] = impl } - func refreshSaves(maxItems: Int, completion: (() -> Void)?) { + func refreshSaves(completion: (() -> Void)?) { guard let impl = implementations[Self.refreshSaves] as? RefreshSavesImpl else { fatalError("\(Self.self)#\(#function) has not been stubbed") } calls[Self.refreshSaves] = (calls[Self.refreshSaves] ?? []) + [ - RefreshSavesCall(maxItems: maxItems, completion: completion) + RefreshSavesCall(completion: completion) ] - impl(maxItems, completion) + impl(completion) } func refreshSavesCall(at index: Int) -> RefreshSavesCall? { @@ -92,10 +91,9 @@ extension MockSource { // MARK: - Refresh Archive extension MockSource { private static let refreshArchive = "refreshArchive" - typealias RefreshArchiveImpl = (Int, (() -> Void)?) -> Void + typealias RefreshArchiveImpl = ((() -> Void)?) -> Void struct RefreshArchiveCall { - let maxItems: Int let completion: (() -> Void)? } @@ -103,16 +101,16 @@ extension MockSource { implementations[Self.refreshArchive] = impl } - func refreshArchive(maxItems: Int, completion: (() -> Void)?) { + func refreshArchive(completion: (() -> Void)?) { guard let impl = implementations[Self.refreshArchive] as? RefreshArchiveImpl else { fatalError("\(Self.self)#\(#function) has not been stubbed") } calls[Self.refreshArchive] = (calls[Self.refreshArchive] ?? []) + [ - RefreshArchiveCall(maxItems: maxItems, completion: completion) + RefreshArchiveCall(completion: completion) ] - impl(maxItems, completion) + impl(completion) } func refreshArchiveCall(at index: Int) -> RefreshArchiveCall? {