fix: fix ajax code, add test, switch parser library

This commit is contained in:
Nolan Lawson 2020-06-29 21:16:22 -07:00
parent 5e7c8003db
commit 44c1b6feb5
8 changed files with 51 additions and 17 deletions

View File

@ -79,6 +79,7 @@
"indexeddb-getall-shim": "^1.3.6", "indexeddb-getall-shim": "^1.3.6",
"intersection-observer": "^0.8.0", "intersection-observer": "^0.8.0",
"intl": "^1.2.5", "intl": "^1.2.5",
"li": "^1.3.0",
"localstorage-memory": "^1.0.3", "localstorage-memory": "^1.0.3",
"lodash-es": "^4.17.15", "lodash-es": "^4.17.15",
"lodash-webpack-plugin": "^0.11.5", "lodash-webpack-plugin": "^0.11.5",
@ -116,7 +117,6 @@
"assert": "^2.0.0", "assert": "^2.0.0",
"eslint-plugin-html": "^6.0.0", "eslint-plugin-html": "^6.0.0",
"fake-indexeddb": "^3.0.0", "fake-indexeddb": "^3.0.0",
"http-link-header": "^1.0.2",
"mocha": "^7.1.0", "mocha": "^7.1.0",
"now": "^18.0.0", "now": "^18.0.0",
"standard": "^14.3.1", "standard": "^14.3.1",

View File

@ -3,5 +3,5 @@ import { getTimeline } from '../_api/timelines'
export async function getRecentStatusesForAccount (accountId) { export async function getRecentStatusesForAccount (accountId) {
const { currentInstance, accessToken } = store.get() 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
} }

View File

@ -13,8 +13,8 @@ export async function fillStreamingGap (instanceName, accessToken, timelineName,
do { do {
numRequests++ numRequests++
newTimelineItems = await getTimeline(instanceName, accessToken, newTimelineItems = (await getTimeline(instanceName, accessToken,
timelineName, maxId, firstTimelineItemId, TIMELINE_GAP_BATCH_SIZE) timelineName, maxId, firstTimelineItemId, TIMELINE_GAP_BATCH_SIZE)).items
if (newTimelineItems.length) { if (newTimelineItems.length) {
addStatusesOrNotifications(instanceName, timelineName, newTimelineItems) addStatusesOrNotifications(instanceName, timelineName, newTimelineItems)
maxId = newTimelineItems[newTimelineItems.length - 1].id maxId = newTimelineItems[newTimelineItems.length - 1].id

View File

@ -14,7 +14,7 @@ import uniqBy from 'lodash-es/uniqBy'
import { addStatusesOrNotifications } from './addStatusOrNotification' import { addStatusesOrNotifications } from './addStatusOrNotification'
import { scheduleIdleTask } from '../_utils/scheduleIdleTask' import { scheduleIdleTask } from '../_utils/scheduleIdleTask'
import { sortItemSummariesForThread } from '../_utils/sortItemSummariesForThread' import { sortItemSummariesForThread } from '../_utils/sortItemSummariesForThread'
import LinkHeader from 'http-link-header' import li from 'li'
const byId = _ => _.id const byId = _ => _.id
@ -99,7 +99,7 @@ async function addPagedTimelineItems (instanceName, timelineName, items) {
console.log('addPagedTimelineItems, length:', items.length) console.log('addPagedTimelineItems, length:', items.length)
mark('addPagedTimelineItemSummaries') mark('addPagedTimelineItemSummaries')
const newSummaries = items.map(timelineItemToSummary) const newSummaries = items.map(timelineItemToSummary)
addPagedTimelineItemSummaries(instanceName, timelineName, newSummaries) await addPagedTimelineItemSummaries(instanceName, timelineName, newSummaries)
stop('addPagedTimelineItemSummaries') stop('addPagedTimelineItemSummaries')
} }
@ -118,8 +118,9 @@ async function fetchPagedItems (instanceName, accessToken, timelineName) {
console.log('saved timelineNextPageId', timelineNextPageId) console.log('saved timelineNextPageId', timelineNextPageId)
const { items, headers } = await getTimeline(instanceName, accessToken, timelineName, timelineNextPageId, null, TIMELINE_BATCH_SIZE) const { items, headers } = await getTimeline(instanceName, accessToken, timelineName, timelineNextPageId, null, TIMELINE_BATCH_SIZE)
const linkHeader = headers.get('Link') const linkHeader = headers.get('Link')
const next = LinkHeader.parse(linkHeader).rel('next')[0] const parsedLinkHeader = li.parse(linkHeader)
const nextId = next && next.uri && (new URL(next.uri)).searchParams.get('max_id') const nextUrl = parsedLinkHeader && parsedLinkHeader.next
const nextId = nextUrl && (new URL(nextUrl)).searchParams.get('max_id')
console.log('new timelineNextPageId', nextId) console.log('new timelineNextPageId', nextId)
store.setForTimeline(instanceName, timelineName, { timelineNextPageId: nextId }) store.setForTimeline(instanceName, timelineName, { timelineNextPageId: nextId })
await storeFreshTimelineItemsInDatabase(instanceName, timelineName, items) await storeFreshTimelineItemsInDatabase(instanceName, timelineName, items)
@ -183,10 +184,12 @@ async function fetchTimelineItemsAndPossiblyFallBack () {
} = store.get() } = store.get()
if (currentTimeline === 'favorites') { 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) await fetchPagedItems(currentInstance, accessToken, currentTimeline)
} else { } else {
const { items, stale } = await fetchTimelineItems(currentInstance, accessToken, currentTimeline, online) const { items, stale } = await fetchTimelineItems(currentInstance, accessToken, currentTimeline, online)
addTimelineItems(currentInstance, currentTimeline, items, stale) await addTimelineItems(currentInstance, currentTimeline, items, stale)
} }
stop('fetchTimelineItemsAndPossiblyFallBack') stop('fetchTimelineItemsAndPossiblyFallBack')
} }

View File

@ -69,10 +69,10 @@ export async function getTimeline (instanceName, accessToken, timeline, maxId, s
url += '?' + paramsString(params) url += '?' + paramsString(params)
console.log('fetching url', url) 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') { if (timeline === 'direct') {
return items.map(item => item.last_status) items = items.map(item => item.last_status)
} }
return { items, headers } return { items, headers }
} }

View File

@ -62,20 +62,19 @@ async function _putOrPostOrPatch (method, url, body, headers, options) {
} }
export async function put (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) { 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) { 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) { export async function get (url, headers, options) {
const { json } = await _fetch(url, makeFetchOptions('GET', headers, options), options) return (await _fetch(url, makeFetchOptions('GET', headers, options), options)).json
return json
} }
/** @returns {json, headers} */ /** @returns {json, headers} */
@ -84,7 +83,7 @@ export async function getWithHeaders (url, headers, options) {
} }
export async function del (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) { export function paramsString (paramsObject) {

View File

@ -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)
})

View File

@ -5184,6 +5184,11 @@ levn@^0.3.0, levn@~0.3.0:
prelude-ls "~1.1.2" prelude-ls "~1.1.2"
type-check "~0.3.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: linux-platform-info@^0.0.3:
version "0.0.3" version "0.0.3"
resolved "https://registry.yarnpkg.com/linux-platform-info/-/linux-platform-info-0.0.3.tgz#2dae324385e66e3d755bec83f86c7beea61ceb83" resolved "https://registry.yarnpkg.com/linux-platform-info/-/linux-platform-info-0.0.3.tgz#2dae324385e66e3d755bec83f86c7beea61ceb83"