audiobookshelf/test/server/utils/libraryBrowseCursor.test.js
2026-03-14 02:04:10 -04:00

68 lines
2.2 KiB
JavaScript

const chai = require('chai')
const expect = chai.expect
const {
encodeBrowseCursor,
decodeBrowseCursor
} = require('../../../server/utils/queries/libraryBrowseCursor')
describe('libraryBrowseCursor', () => {
it('round-trips a deterministic title cursor with id tie-breaker', () => {
const encoded = encodeBrowseCursor({
sortBy: 'media.metadata.title',
desc: false,
keys: ['titleIgnorePrefix', 'id'],
values: ['Dune', 'item_42']
})
expect(decodeBrowseCursor(encoded)).to.deep.equal({
sortBy: 'media.metadata.title',
desc: false,
keys: ['titleIgnorePrefix', 'id'],
values: ['Dune', 'item_42']
})
})
it('rejects a cursor without the full ordered key set', () => {
expect(() => decodeBrowseCursor(encodeBrowseCursor({
sortBy: 'media.metadata.title',
desc: false,
keys: ['titleIgnorePrefix', 'id'],
values: ['Dune']
}))).to.throw('full ordered key set')
})
it('rejects a cursor without the id tie-breaker', () => {
expect(() => decodeBrowseCursor(encodeBrowseCursor({
sortBy: 'media.metadata.title',
desc: false,
keys: ['titleIgnorePrefix'],
values: ['Dune']
}))).to.throw('tie-breaker')
})
it('rejects a cursor when the id tie-breaker value is null', () => {
expect(() => decodeBrowseCursor(encodeBrowseCursor({
sortBy: 'media.metadata.title',
desc: false,
keys: ['titleIgnorePrefix', 'id'],
values: ['Dune', null]
}))).to.throw('tie-breaker')
})
it('rejects a malformed cursor string with a controlled invalid-cursor error', () => {
expect(() => decodeBrowseCursor('%%%not-base64%%%')).to.throw('Invalid browse cursor')
})
it('rejects malformed cursor json with a controlled invalid-cursor error', () => {
const malformedJsonCursor = Buffer.from('{"sortBy":', 'utf8').toString('base64url')
expect(() => decodeBrowseCursor(malformedJsonCursor)).to.throw('Invalid browse cursor')
})
it('rejects decoded non-object json payloads with a controlled invalid-cursor error', () => {
const nonObjectCursor = Buffer.from('null', 'utf8').toString('base64url')
expect(() => decodeBrowseCursor(nonObjectCursor)).to.throw('Invalid browse cursor')
})
})