From ef2585e32b546722f2157bd6203701deb495d2e9 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Fri, 11 Jan 2019 02:40:17 +0300 Subject: Remove all explicit and implicit conversions of statusId to number, changed explicit ones so that they convert them to string --- src/services/notification_utils/notification_utils.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/services/notification_utils') diff --git a/src/services/notification_utils/notification_utils.js b/src/services/notification_utils/notification_utils.js index f5ac0d47..c6782af4 100644 --- a/src/services/notification_utils/notification_utils.js +++ b/src/services/notification_utils/notification_utils.js @@ -10,8 +10,8 @@ export const visibleTypes = store => ([ ].filter(_ => _)) export const visibleNotificationsFromStore = store => { - // Don't know why, but sortBy([seen, -action.id]) doesn't work. - let sortedNotifications = sortBy(notificationsFromStore(store), ({action}) => -action.id) + // map is just to clone the array since sort mutates it and it causes some issues + let sortedNotifications = notificationsFromStore(store).map(_ => _).sort((a, b) => a.id > b.id ? -1 : 1) sortedNotifications = sortBy(sortedNotifications, 'seen') return sortedNotifications.filter((notification) => visibleTypes(store).includes(notification.type)) } -- cgit v1.2.3-70-g09d2 From b18e27c6d4d2b3d681be8dd81dafcdfeaf20fb35 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Fri, 11 Jan 2019 03:38:23 +0300 Subject: fix tests, removed one unused function, fix real problem that tests helped to surface --- src/modules/statuses.js | 4 - .../notification_utils/notification_utils.js | 2 +- test/unit/specs/modules/statuses.spec.js | 105 +++++++++------------ test/unit/specs/modules/users.spec.js | 16 ++-- .../notification_utils/notification_utils.spec.js | 16 ++-- 5 files changed, 62 insertions(+), 81 deletions(-) (limited to 'src/services/notification_utils') diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 05626a02..a931fd97 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -100,10 +100,6 @@ export const statusType = (status) => { return 'unknown' } -export const findMaxId = (...args) => { - return (maxBy(flatten(args), 'id') || {}).id -} - const mergeOrAdd = (arr, obj, item) => { // For sequential IDs BE passes numbers as numbers, we want them as strings. item.id = String(item.id) diff --git a/src/services/notification_utils/notification_utils.js b/src/services/notification_utils/notification_utils.js index c6782af4..c3879677 100644 --- a/src/services/notification_utils/notification_utils.js +++ b/src/services/notification_utils/notification_utils.js @@ -11,7 +11,7 @@ export const visibleTypes = store => ([ export const visibleNotificationsFromStore = store => { // map is just to clone the array since sort mutates it and it causes some issues - let sortedNotifications = notificationsFromStore(store).map(_ => _).sort((a, b) => a.id > b.id ? -1 : 1) + let sortedNotifications = notificationsFromStore(store).map(_ => _).sort((a, b) => a.action.id > b.action.id ? -1 : 1) sortedNotifications = sortBy(sortedNotifications, 'seen') return sortedNotifications.filter((notification) => visibleTypes(store).includes(notification.type)) } diff --git a/test/unit/specs/modules/statuses.spec.js b/test/unit/specs/modules/statuses.spec.js index 7d403312..f4d0ddf4 100644 --- a/test/unit/specs/modules/statuses.spec.js +++ b/test/unit/specs/modules/statuses.spec.js @@ -1,11 +1,11 @@ import { cloneDeep } from 'lodash' -import { defaultState, mutations, findMaxId, prepareStatus, statusType } from '../../../../src/modules/statuses.js' +import { defaultState, mutations, prepareStatus, statusType } from '../../../../src/modules/statuses.js' // eslint-disable-next-line camelcase const makeMockStatus = ({id, text, is_post_verb = true}) => { return { id, - user: {id: 0}, + user: {id: '0'}, name: 'status', text: text || `Text number ${id}`, fave_num: 0, @@ -32,45 +32,30 @@ describe('Statuses.statusType', () => { describe('Statuses.prepareStatus', () => { it('sets nsfw for statuses with the #nsfw tag', () => { - const safe = makeMockStatus({id: 1, text: 'Hello oniichan'}) - const nsfw = makeMockStatus({id: 1, text: 'Hello oniichan #nsfw'}) + const safe = makeMockStatus({id: '1', text: 'Hello oniichan'}) + const nsfw = makeMockStatus({id: '1', text: 'Hello oniichan #nsfw'}) expect(prepareStatus(safe).nsfw).to.eq(false) expect(prepareStatus(nsfw).nsfw).to.eq(true) }) it('leaves existing nsfw settings alone', () => { - const nsfw = makeMockStatus({id: 1, text: 'Hello oniichan #nsfw'}) + const nsfw = makeMockStatus({id: '1', text: 'Hello oniichan #nsfw'}) nsfw.nsfw = false expect(prepareStatus(nsfw).nsfw).to.eq(false) }) it('sets deleted flag to false', () => { - const aStatus = makeMockStatus({id: 1, text: 'Hello oniichan'}) + const aStatus = makeMockStatus({id: '1', text: 'Hello oniichan'}) expect(prepareStatus(aStatus).deleted).to.eq(false) }) }) -describe('Statuses.findMaxId', () => { - it('returns the largest id in any of the given arrays', () => { - const statusesOne = [{ id: 100 }, { id: 2 }] - const statusesTwo = [{ id: 3 }] - - const maxId = findMaxId(statusesOne, statusesTwo) - expect(maxId).to.eq(100) - }) - - it('returns undefined for empty arrays', () => { - const maxId = findMaxId([], []) - expect(maxId).to.eq(undefined) - }) -}) - describe('The Statuses module', () => { it('adds the status to allStatuses and to the given timeline', () => { const state = cloneDeep(defaultState) - const status = makeMockStatus({id: 1}) + const status = makeMockStatus({id: '1'}) mutations.addNewStatuses(state, { statuses: [status], timeline: 'public' }) @@ -82,7 +67,7 @@ describe('The Statuses module', () => { it('counts the status as new if it has not been seen on this timeline', () => { const state = cloneDeep(defaultState) - const status = makeMockStatus({id: 1}) + const status = makeMockStatus({id: '1'}) mutations.addNewStatuses(state, { statuses: [status], timeline: 'public' }) mutations.addNewStatuses(state, { statuses: [status], timeline: 'friends' }) @@ -100,7 +85,7 @@ describe('The Statuses module', () => { it('add the statuses to allStatuses if no timeline is given', () => { const state = cloneDeep(defaultState) - const status = makeMockStatus({id: 1}) + const status = makeMockStatus({id: '1'}) mutations.addNewStatuses(state, { statuses: [status] }) @@ -112,7 +97,7 @@ describe('The Statuses module', () => { it('adds the status to allStatuses and to the given timeline, directly visible', () => { const state = cloneDeep(defaultState) - const status = makeMockStatus({id: 1}) + const status = makeMockStatus({id: '1'}) mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) @@ -124,10 +109,10 @@ describe('The Statuses module', () => { it('removes statuses by tag on deletion', () => { const state = cloneDeep(defaultState) - const status = makeMockStatus({id: 1}) - const otherStatus = makeMockStatus({id: 3}) + const status = makeMockStatus({id: '1'}) + const otherStatus = makeMockStatus({id: '3'}) status.uri = 'xxx' - const deletion = makeMockStatus({id: 2, is_post_verb: false}) + const deletion = makeMockStatus({id: '2', is_post_verb: false}) deletion.text = 'Dolus deleted notice {{tag:gs.smuglo.li,2016-11-18:noticeId=1038007:objectType=note}}.' deletion.uri = 'xxx' @@ -137,36 +122,36 @@ describe('The Statuses module', () => { expect(state.allStatuses).to.eql([otherStatus]) expect(state.timelines.public.statuses).to.eql([otherStatus]) expect(state.timelines.public.visibleStatuses).to.eql([otherStatus]) - expect(state.timelines.public.maxId).to.eql(3) + expect(state.timelines.public.maxId).to.eql('3') }) it('does not update the maxId when the noIdUpdate flag is set', () => { const state = cloneDeep(defaultState) - const status = makeMockStatus({id: 1}) - const secondStatus = makeMockStatus({id: 2}) + const status = makeMockStatus({id: '1'}) + const secondStatus = makeMockStatus({id: '2'}) mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) - expect(state.timelines.public.maxId).to.eql(1) + expect(state.timelines.public.maxId).to.eql('1') mutations.addNewStatuses(state, { statuses: [secondStatus], showImmediately: true, timeline: 'public', noIdUpdate: true }) expect(state.timelines.public.statuses).to.eql([secondStatus, status]) expect(state.timelines.public.visibleStatuses).to.eql([secondStatus, status]) - expect(state.timelines.public.maxId).to.eql(1) + expect(state.timelines.public.maxId).to.eql('1') }) it('keeps a descending by id order in timeline.visibleStatuses and timeline.statuses', () => { const state = cloneDeep(defaultState) - const nonVisibleStatus = makeMockStatus({id: 1}) - const status = makeMockStatus({id: 3}) - const statusTwo = makeMockStatus({id: 2}) - const statusThree = makeMockStatus({id: 4}) + const nonVisibleStatus = makeMockStatus({id: '1'}) + const status = makeMockStatus({id: '3'}) + const statusTwo = makeMockStatus({id: '2'}) + const statusThree = makeMockStatus({id: '4'}) mutations.addNewStatuses(state, { statuses: [nonVisibleStatus], showImmediately: false, timeline: 'public' }) mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) mutations.addNewStatuses(state, { statuses: [statusTwo], showImmediately: true, timeline: 'public' }) - expect(state.timelines.public.minVisibleId).to.equal(2) + expect(state.timelines.public.minVisibleId).to.equal('2') mutations.addNewStatuses(state, { statuses: [statusThree], showImmediately: true, timeline: 'public' }) @@ -176,9 +161,9 @@ describe('The Statuses module', () => { it('splits retweets from their status and links them', () => { const state = cloneDeep(defaultState) - const status = makeMockStatus({id: 1}) - const retweet = makeMockStatus({id: 2, is_post_verb: false}) - const modStatus = makeMockStatus({id: 1, text: 'something else'}) + const status = makeMockStatus({id: '1'}) + const retweet = makeMockStatus({id: '2', is_post_verb: false}) + const modStatus = makeMockStatus({id: '1', text: 'something else'}) retweet.retweeted_status = status @@ -187,22 +172,22 @@ describe('The Statuses module', () => { expect(state.timelines.public.visibleStatuses).to.have.length(1) expect(state.timelines.public.statuses).to.have.length(1) expect(state.allStatuses).to.have.length(2) - expect(state.allStatuses[0].id).to.equal(1) - expect(state.allStatuses[1].id).to.equal(2) + expect(state.allStatuses[0].id).to.equal('1') + expect(state.allStatuses[1].id).to.equal('2') // It refers to the modified status. mutations.addNewStatuses(state, { statuses: [modStatus], timeline: 'public' }) expect(state.allStatuses).to.have.length(2) - expect(state.allStatuses[0].id).to.equal(1) + expect(state.allStatuses[0].id).to.equal('1') expect(state.allStatuses[0].text).to.equal(modStatus.text) - expect(state.allStatuses[1].id).to.equal(2) + expect(state.allStatuses[1].id).to.equal('2') expect(retweet.retweeted_status.text).to.eql(modStatus.text) }) it('replaces existing statuses with the same id', () => { const state = cloneDeep(defaultState) - const status = makeMockStatus({id: 1}) - const modStatus = makeMockStatus({id: 1, text: 'something else'}) + const status = makeMockStatus({id: '1'}) + const modStatus = makeMockStatus({id: '1', text: 'something else'}) // Add original status mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) @@ -218,9 +203,9 @@ describe('The Statuses module', () => { it('replaces existing statuses with the same id, coming from a retweet', () => { const state = cloneDeep(defaultState) - const status = makeMockStatus({id: 1}) - const modStatus = makeMockStatus({id: 1, text: 'something else'}) - const retweet = makeMockStatus({id: 2, is_post_verb: false}) + const status = makeMockStatus({id: '1'}) + const modStatus = makeMockStatus({id: '1', text: 'something else'}) + const retweet = makeMockStatus({id: '2', is_post_verb: false}) retweet.retweeted_status = modStatus // Add original status @@ -239,15 +224,15 @@ describe('The Statuses module', () => { it('handles favorite actions', () => { const state = cloneDeep(defaultState) - const status = makeMockStatus({id: 1}) + const status = makeMockStatus({id: '1'}) const favorite = { - id: 2, + id: '2', is_post_verb: false, in_reply_to_status_id: '1', // The API uses strings here... uri: 'tag:shitposter.club,2016-08-21:fave:3895:note:773501:2016-08-21T16:52:15+00:00', text: 'a favorited something by b', - user: { id: 99 } + user: { id: '99' } } mutations.addNewStatuses(state, { statuses: [status], showImmediately: true, timeline: 'public' }) @@ -266,11 +251,11 @@ describe('The Statuses module', () => { // If something is favorited by the current user, it also sets the 'favorited' property but does not increment counter to avoid over-counting. Counter is incremented (updated, really) via response to the favorite request. const user = { - id: 1 + id: '1' } const ownFavorite = { - id: 3, + id: '3', is_post_verb: false, in_reply_to_status_id: '1', // The API uses strings here... uri: 'tag:shitposter.club,2016-08-21:fave:3895:note:773501:2016-08-21T16:52:15+00:00', @@ -287,16 +272,16 @@ describe('The Statuses module', () => { describe('notifications', () => { it('removes a notification when the notice gets removed', () => { - const user = { id: 1 } + const user = { id: '1' } const state = cloneDeep(defaultState) - const status = makeMockStatus({id: 1}) - const otherStatus = makeMockStatus({id: 3}) - const mentionedStatus = makeMockStatus({id: 2}) + const status = makeMockStatus({id: '1'}) + const otherStatus = makeMockStatus({id: '3'}) + const mentionedStatus = makeMockStatus({id: '2'}) mentionedStatus.attentions = [user] mentionedStatus.uri = 'xxx' otherStatus.attentions = [user] - const deletion = makeMockStatus({id: 4, is_post_verb: false}) + const deletion = makeMockStatus({id: '4', is_post_verb: false}) deletion.text = 'Dolus deleted notice {{tag:gs.smuglo.li,2016-11-18:noticeId=1038007:objectType=note}}.' deletion.uri = 'xxx' diff --git a/test/unit/specs/modules/users.spec.js b/test/unit/specs/modules/users.spec.js index af60c9b3..b0f3c51e 100644 --- a/test/unit/specs/modules/users.spec.js +++ b/test/unit/specs/modules/users.spec.js @@ -6,8 +6,8 @@ describe('The users module', () => { describe('mutations', () => { it('adds new users to the set, merging in new information for old users', () => { const state = cloneDeep(defaultState) - const user = { id: 1, name: 'Guy' } - const modUser = { id: 1, name: 'Dude' } + const user = { id: '1', name: 'Guy' } + const modUser = { id: '1', name: 'Dude' } mutations.addNewUsers(state, [user]) expect(state.users).to.have.length(1) @@ -21,7 +21,7 @@ describe('The users module', () => { it('sets a mute bit on users', () => { const state = cloneDeep(defaultState) - const user = { id: 1, name: 'Guy' } + const user = { id: '1', name: 'Guy' } mutations.addNewUsers(state, [user]) mutations.setMuted(state, {user, muted: true}) @@ -38,11 +38,11 @@ describe('The users module', () => { it('returns user with matching screen_name', () => { const state = { users: [ - { screen_name: 'Guy', id: 1 } + { screen_name: 'Guy', id: '1' } ] } const name = 'Guy' - const expected = { screen_name: 'Guy', id: 1 } + const expected = { screen_name: 'Guy', id: '1' } expect(getters.userByName(state)(name)).to.eql(expected) }) }) @@ -51,11 +51,11 @@ describe('The users module', () => { it('returns user with matching id', () => { const state = { users: [ - { screen_name: 'Guy', id: 1 } + { screen_name: 'Guy', id: '1' } ] } - const id = 1 - const expected = { screen_name: 'Guy', id: 1 } + const id = '1' + const expected = { screen_name: 'Guy', id: '1' } expect(getters.userById(state)(id)).to.eql(expected) }) }) diff --git a/test/unit/specs/services/notification_utils/notification_utils.spec.js b/test/unit/specs/services/notification_utils/notification_utils.spec.js index c44b8c9e..e945459e 100644 --- a/test/unit/specs/services/notification_utils/notification_utils.spec.js +++ b/test/unit/specs/services/notification_utils/notification_utils.spec.js @@ -9,15 +9,15 @@ describe('NotificationUtils', () => { notifications: { data: [ { - action: { id: 1 }, + action: { id: '1' }, type: 'like' }, { - action: { id: 2 }, + action: { id: '2' }, type: 'mention' }, { - action: { id: 3 }, + action: { id: '3' }, type: 'repeat' } ] @@ -34,11 +34,11 @@ describe('NotificationUtils', () => { } const expected = [ { - action: { id: 3 }, + action: { id: '3' }, type: 'repeat' }, { - action: { id: 1 }, + action: { id: '1' }, type: 'like' } ] @@ -54,12 +54,12 @@ describe('NotificationUtils', () => { notifications: { data: [ { - action: { id: 1 }, + action: { id: '1' }, type: 'like', seen: false }, { - action: { id: 2 }, + action: { id: '2' }, type: 'mention', seen: true } @@ -77,7 +77,7 @@ describe('NotificationUtils', () => { } const expected = [ { - action: { id: 1 }, + action: { id: '1' }, type: 'like', seen: false } -- cgit v1.2.3-70-g09d2 From 9d0d6b86c83a4fad4038077a65149f0f3677fb82 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Fri, 25 Jan 2019 00:49:37 +0300 Subject: this attempts converting id to number to sort them numerically, since "99" > "100" while 99 < 100 --- src/components/conversation/conversation.js | 18 +++++++++++++++++- src/modules/statuses.js | 18 ++++++++++++++++-- src/services/notification_utils/notification_utils.js | 18 +++++++++++++++++- 3 files changed, 50 insertions(+), 4 deletions(-) (limited to 'src/services/notification_utils') diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index 9bf5e136..07b7c692 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -1,9 +1,25 @@ import { reduce, filter, sortBy } from 'lodash' import Status from '../status/status.vue' +const sortById = (a, b) => { + const seqA = Number(a.action.id) + const seqB = Number(b.action.id) + const isSeqA = Number.isNaN(seqA) + const isSeqB = Number.isNaN(seqB) + if (isSeqA && isSeqB) { + return seqA > seqB ? -1 : 1 + } else if (isSeqA && !isSeqB) { + return 1 + } else if (!isSeqA && isSeqB) { + return -1 + } else { + return a.action.id > b.action.id ? -1 : 1 + } +} + const sortAndFilterConversation = (conversation) => { conversation = filter(conversation, (status) => status.type !== 'retweet') - return sortBy(conversation, 'id') + return sortBy(conversation, sortById) } const conversation = { diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 83cf7256..27d4e94c 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -81,7 +81,21 @@ const mergeOrAdd = (arr, obj, item) => { } } -const sortById = (a, b) => a.id > b.id ? -1 : 1 +const sortById = (a, b) => { + const seqA = Number(a.id) + const seqB = Number(b.id) + const isSeqA = Number.isNaN(seqA) + const isSeqB = Number.isNaN(seqB) + if (isSeqA && isSeqB) { + return seqA > seqB ? -1 : 1 + } else if (isSeqA && !isSeqB) { + return 1 + } else if (!isSeqA && isSeqB) { + return -1 + } else { + return a.id > b.id ? -1 : 1 + } +} const sortTimeline = (timeline) => { timeline.visibleStatuses = timeline.visibleStatuses.sort(sortById) @@ -239,7 +253,7 @@ const addNewStatuses = (state, { statuses, showImmediately = false, timeline, us processor(status) }) - // Keep the visible statuses sorted + // Keep the visible statuses sorted if (timeline) { sortTimeline(timelineObject) if ((older || timelineObject.minVisibleId <= 0) && statuses.length > 0) { diff --git a/src/services/notification_utils/notification_utils.js b/src/services/notification_utils/notification_utils.js index c3879677..4a59bef2 100644 --- a/src/services/notification_utils/notification_utils.js +++ b/src/services/notification_utils/notification_utils.js @@ -9,9 +9,25 @@ export const visibleTypes = store => ([ store.state.config.notificationVisibility.follows && 'follow' ].filter(_ => _)) +const sortById = (a, b) => { + const seqA = Number(a.action.id) + const seqB = Number(b.action.id) + const isSeqA = Number.isNaN(seqA) + const isSeqB = Number.isNaN(seqB) + if (isSeqA && isSeqB) { + return seqA > seqB ? -1 : 1 + } else if (isSeqA && !isSeqB) { + return 1 + } else if (!isSeqA && isSeqB) { + return -1 + } else { + return a.action.id > b.action.id ? -1 : 1 + } +} + export const visibleNotificationsFromStore = store => { // map is just to clone the array since sort mutates it and it causes some issues - let sortedNotifications = notificationsFromStore(store).map(_ => _).sort((a, b) => a.action.id > b.action.id ? -1 : 1) + let sortedNotifications = notificationsFromStore(store).map(_ => _).sort(sortById) sortedNotifications = sortBy(sortedNotifications, 'seen') return sortedNotifications.filter((notification) => visibleTypes(store).includes(notification.type)) } -- cgit v1.2.3-70-g09d2 From f48e3d0db8029701461250bb8f47ec33f0d68606 Mon Sep 17 00:00:00 2001 From: Henry Jameson Date: Fri, 25 Jan 2019 01:39:19 +0300 Subject: quickfix --- src/components/conversation/conversation.js | 4 ++-- src/modules/statuses.js | 4 ++-- src/services/notification_utils/notification_utils.js | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/services/notification_utils') diff --git a/src/components/conversation/conversation.js b/src/components/conversation/conversation.js index 07b7c692..ae8ab4fc 100644 --- a/src/components/conversation/conversation.js +++ b/src/components/conversation/conversation.js @@ -4,8 +4,8 @@ import Status from '../status/status.vue' const sortById = (a, b) => { const seqA = Number(a.action.id) const seqB = Number(b.action.id) - const isSeqA = Number.isNaN(seqA) - const isSeqB = Number.isNaN(seqB) + const isSeqA = !Number.isNaN(seqA) + const isSeqB = !Number.isNaN(seqB) if (isSeqA && isSeqB) { return seqA > seqB ? -1 : 1 } else if (isSeqA && !isSeqB) { diff --git a/src/modules/statuses.js b/src/modules/statuses.js index 27d4e94c..20a8d2eb 100644 --- a/src/modules/statuses.js +++ b/src/modules/statuses.js @@ -84,8 +84,8 @@ const mergeOrAdd = (arr, obj, item) => { const sortById = (a, b) => { const seqA = Number(a.id) const seqB = Number(b.id) - const isSeqA = Number.isNaN(seqA) - const isSeqB = Number.isNaN(seqB) + const isSeqA = !Number.isNaN(seqA) + const isSeqB = !Number.isNaN(seqB) if (isSeqA && isSeqB) { return seqA > seqB ? -1 : 1 } else if (isSeqA && !isSeqB) { diff --git a/src/services/notification_utils/notification_utils.js b/src/services/notification_utils/notification_utils.js index 4a59bef2..cd8f3f9e 100644 --- a/src/services/notification_utils/notification_utils.js +++ b/src/services/notification_utils/notification_utils.js @@ -12,8 +12,8 @@ export const visibleTypes = store => ([ const sortById = (a, b) => { const seqA = Number(a.action.id) const seqB = Number(b.action.id) - const isSeqA = Number.isNaN(seqA) - const isSeqB = Number.isNaN(seqB) + const isSeqA = !Number.isNaN(seqA) + const isSeqB = !Number.isNaN(seqB) if (isSeqA && isSeqB) { return seqA > seqB ? -1 : 1 } else if (isSeqA && !isSeqB) { -- cgit v1.2.3-70-g09d2