From 44c1b6feb5593bdfc6635d4e59f7ce799fc87797 Mon Sep 17 00:00:00 2001 From: Nolan Lawson Date: Mon, 29 Jun 2020 21:16:22 -0700 Subject: [PATCH] fix: fix ajax code, add test, switch parser library --- package.json | 2 +- .../_actions/getRecentStatusesForAccount.js | 2 +- .../_actions/stream/fillStreamingGap.js | 4 +-- src/routes/_actions/timeline.js | 13 +++++---- src/routes/_api/timelines.js | 4 +-- src/routes/_utils/ajax.js | 11 ++++---- tests/spec/133-favorites.js | 27 +++++++++++++++++++ yarn.lock | 5 ++++ 8 files changed, 51 insertions(+), 17 deletions(-) create mode 100644 tests/spec/133-favorites.js diff --git a/package.json b/package.json index 03f83616..01b19722 100644 --- a/package.json +++ b/package.json @@ -79,6 +79,7 @@ "indexeddb-getall-shim": "^1.3.6", "intersection-observer": "^0.8.0", "intl": "^1.2.5", + "li": "^1.3.0", "localstorage-memory": "^1.0.3", "lodash-es": "^4.17.15", "lodash-webpack-plugin": "^0.11.5", @@ -116,7 +117,6 @@ "assert": "^2.0.0", "eslint-plugin-html": "^6.0.0", "fake-indexeddb": "^3.0.0", - "http-link-header": "^1.0.2", "mocha": "^7.1.0", "now": "^18.0.0", "standard": "^14.3.1", diff --git a/src/routes/_actions/getRecentStatusesForAccount.js b/src/routes/_actions/getRecentStatusesForAccount.js index 98456049..8c64a914 100644 --- a/src/routes/_actions/getRecentStatusesForAccount.js +++ b/src/routes/_actions/getRecentStatusesForAccount.js @@ -3,5 +3,5 @@ import { getTimeline } from '../_api/timelines' export async function getRecentStatusesForAccount (accountId) { const { currentInstance, accessToken } = store.get() - return getTimeline(currentInstance, accessToken, `account/${accountId}`, null, null, 20) + return (await getTimeline(currentInstance, accessToken, `account/${accountId}`, null, null, 20)).items } diff --git a/src/routes/_actions/stream/fillStreamingGap.js b/src/routes/_actions/stream/fillStreamingGap.js index 0d664835..a34550f6 100644 --- a/src/routes/_actions/stream/fillStreamingGap.js +++ b/src/routes/_actions/stream/fillStreamingGap.js @@ -13,8 +13,8 @@ export async function fillStreamingGap (instanceName, accessToken, timelineName, do { numRequests++ - newTimelineItems = await getTimeline(instanceName, accessToken, - timelineName, maxId, firstTimelineItemId, TIMELINE_GAP_BATCH_SIZE) + newTimelineItems = (await getTimeline(instanceName, accessToken, + timelineName, maxId, firstTimelineItemId, TIMELINE_GAP_BATCH_SIZE)).items if (newTimelineItems.length) { addStatusesOrNotifications(instanceName, timelineName, newTimelineItems) maxId = newTimelineItems[newTimelineItems.length - 1].id diff --git a/src/routes/_actions/timeline.js b/src/routes/_actions/timeline.js index b99e250f..0be5ea9e 100644 --- a/src/routes/_actions/timeline.js +++ b/src/routes/_actions/timeline.js @@ -14,7 +14,7 @@ import uniqBy from 'lodash-es/uniqBy' import { addStatusesOrNotifications } from './addStatusOrNotification' import { scheduleIdleTask } from '../_utils/scheduleIdleTask' import { sortItemSummariesForThread } from '../_utils/sortItemSummariesForThread' -import LinkHeader from 'http-link-header' +import li from 'li' const byId = _ => _.id @@ -99,7 +99,7 @@ async function addPagedTimelineItems (instanceName, timelineName, items) { console.log('addPagedTimelineItems, length:', items.length) mark('addPagedTimelineItemSummaries') const newSummaries = items.map(timelineItemToSummary) - addPagedTimelineItemSummaries(instanceName, timelineName, newSummaries) + await addPagedTimelineItemSummaries(instanceName, timelineName, newSummaries) stop('addPagedTimelineItemSummaries') } @@ -118,8 +118,9 @@ async function fetchPagedItems (instanceName, accessToken, timelineName) { console.log('saved timelineNextPageId', timelineNextPageId) const { items, headers } = await getTimeline(instanceName, accessToken, timelineName, timelineNextPageId, null, TIMELINE_BATCH_SIZE) const linkHeader = headers.get('Link') - const next = LinkHeader.parse(linkHeader).rel('next')[0] - const nextId = next && next.uri && (new URL(next.uri)).searchParams.get('max_id') + const parsedLinkHeader = li.parse(linkHeader) + const nextUrl = parsedLinkHeader && parsedLinkHeader.next + const nextId = nextUrl && (new URL(nextUrl)).searchParams.get('max_id') console.log('new timelineNextPageId', nextId) store.setForTimeline(instanceName, timelineName, { timelineNextPageId: nextId }) await storeFreshTimelineItemsInDatabase(instanceName, timelineName, items) @@ -183,10 +184,12 @@ async function fetchTimelineItemsAndPossiblyFallBack () { } = store.get() if (currentTimeline === 'favorites') { + // Always fetch favorites from the network, we currently don't have a good way of storing + // these in IndexedDB because of "internal ID" system Mastodon uses to paginate these await fetchPagedItems(currentInstance, accessToken, currentTimeline) } else { const { items, stale } = await fetchTimelineItems(currentInstance, accessToken, currentTimeline, online) - addTimelineItems(currentInstance, currentTimeline, items, stale) + await addTimelineItems(currentInstance, currentTimeline, items, stale) } stop('fetchTimelineItemsAndPossiblyFallBack') } diff --git a/src/routes/_api/timelines.js b/src/routes/_api/timelines.js index edfc0cdf..55270a96 100644 --- a/src/routes/_api/timelines.js +++ b/src/routes/_api/timelines.js @@ -69,10 +69,10 @@ export async function getTimeline (instanceName, accessToken, timeline, maxId, s url += '?' + paramsString(params) console.log('fetching url', url) - const { json: items, headers } = await getWithHeaders(url, auth(accessToken), { timeout: DEFAULT_TIMEOUT }) + let { json: items, headers } = await getWithHeaders(url, auth(accessToken), { timeout: DEFAULT_TIMEOUT }) if (timeline === 'direct') { - return items.map(item => item.last_status) + items = items.map(item => item.last_status) } return { items, headers } } diff --git a/src/routes/_utils/ajax.js b/src/routes/_utils/ajax.js index 0c6aafd6..6ecf171a 100644 --- a/src/routes/_utils/ajax.js +++ b/src/routes/_utils/ajax.js @@ -62,20 +62,19 @@ async function _putOrPostOrPatch (method, url, body, headers, options) { } export async function put (url, body, headers, options) { - return _putOrPostOrPatch('PUT', url, body, headers, options) + return (await _putOrPostOrPatch('PUT', url, body, headers, options)).json } export async function post (url, body, headers, options) { - return _putOrPostOrPatch('POST', url, body, headers, options) + return (await _putOrPostOrPatch('POST', url, body, headers, options)).json } export async function patch (url, body, headers, options) { - return _putOrPostOrPatch('PATCH', url, body, headers, options) + return (await _putOrPostOrPatch('PATCH', url, body, headers, options)).json } export async function get (url, headers, options) { - const { json } = await _fetch(url, makeFetchOptions('GET', headers, options), options) - return json + return (await _fetch(url, makeFetchOptions('GET', headers, options), options)).json } /** @returns {json, headers} */ @@ -84,7 +83,7 @@ export async function getWithHeaders (url, headers, options) { } export async function del (url, headers, options) { - return _fetch(url, makeFetchOptions('DELETE', headers, options), options) + return (await _fetch(url, makeFetchOptions('DELETE', headers, options), options)).json } export function paramsString (paramsObject) { diff --git a/tests/spec/133-favorites.js b/tests/spec/133-favorites.js new file mode 100644 index 00000000..762ee495 --- /dev/null +++ b/tests/spec/133-favorites.js @@ -0,0 +1,27 @@ +import { favoriteStatusAs, postAs } from '../serverActions' +import { loginAsFoobar } from '../roles' +import { + communityNavButton, getUrl, + sleep, validateTimeline +} from '../utils' +import { Selector as $ } from 'testcafe' + +fixture`133-favorites.js` + .page`http://localhost:4002` + +test('favorites can paginate', async t => { + const LENGTH = 25 + for (let i = 0; i < LENGTH; i++) { + const { id } = await postAs('admin', `fav me ${i}`) + await favoriteStatusAs('foobar', id) + await sleep(1000) + } + await loginAsFoobar(t) + await t + .click(communityNavButton) + .click($('a[href="/favorites"]')) + .expect(getUrl()).contains('/favorites') + + const expectedTimeline = Array(LENGTH).fill().map((_, i) => ({ content: `fav me ${LENGTH - i - 1}` })) + await validateTimeline(t, expectedTimeline) +}) diff --git a/yarn.lock b/yarn.lock index 8dbc7013..a6e83709 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5184,6 +5184,11 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +li@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/li/-/li-1.3.0.tgz#22c59bcaefaa9a8ef359cf759784e4bf106aea1b" + integrity sha1-IsWbyu+qmo7zWc91l4TkvxBq6hs= + linux-platform-info@^0.0.3: version "0.0.3" resolved "https://registry.yarnpkg.com/linux-platform-info/-/linux-platform-info-0.0.3.tgz#2dae324385e66e3d755bec83f86c7beea61ceb83"