Files
shopdb-flask/plugins/tools/frontend/sharelink.spec.js

108 lines
3.8 KiB
JavaScript

// The share link has to survive a chat client, a recipient whose saved settings
// differ from the sender's, and a version of the page older than the link.
import { describe, it, expect } from 'vitest'
import { buildFragment, readFragment, coerce } from './sharelink'
const DEFAULTS = {
codetype: 'qr', errorcorrection: 'M', preset: 'zebra1x05',
labelwidth: 1.0, labelheight: 0.5, dpi: 203, layout: 'side',
}
function state (extra = {}) {
return { source: 'single', content: 'WJ-3204', ...DEFAULTS, ...extra }
}
describe('buildFragment', () => {
it('carries what was typed', () => {
const params = new URLSearchParams(buildFragment(state(), DEFAULTS).slice(1))
expect(params.get('c')).toBe('WJ-3204')
expect(params.get('s')).toBe('single')
})
it('leaves out layout values the sender never changed', () => {
const fragment = buildFragment(state(), DEFAULTS)
expect(fragment).not.toContain('labelwidth')
expect(fragment).not.toContain('dpi')
})
it('carries a layout value the sender did change', () => {
const fragment = buildFragment(state({ labelwidth: 2.0, dpi: 300 }), DEFAULTS)
const params = new URLSearchParams(fragment.slice(1))
expect(params.get('labelwidth')).toBe('2')
expect(params.get('dpi')).toBe('300')
})
it('says nothing about one copy, which is what everybody has', () => {
expect(buildFragment(state({ copies: 1 }), DEFAULTS)).not.toContain('n=')
expect(buildFragment(state({ copies: 4 }), DEFAULTS)).toContain('n=4')
})
it('is empty when there is nothing to share', () => {
// So the caller can disable its button rather than emit a bare '#'.
expect(buildFragment({}, DEFAULTS)).toBe('')
})
it('never carries the picture', () => {
// A data URL runs to megabytes; the link would not survive a chat box.
const fragment = buildFragment(state({ pictureUrl: 'data:image/png;base64,AAAA' }), DEFAULTS)
expect(fragment).not.toContain('data:image')
expect(fragment).not.toContain('pictureUrl')
})
})
describe('readFragment', () => {
it('reads back what buildFragment wrote', () => {
const sent = state({ content: 'Bay 310 / press 2', label: 'Press', copies: 3,
labelwidth: 2.0, layout: 'stack' })
const back = readFragment(buildFragment(sent, DEFAULTS))
expect(back.content).toBe('Bay 310 / press 2')
expect(back.label).toBe('Press')
expect(back.copies).toBe('3')
expect(back.labelwidth).toBe('2')
expect(back.layout).toBe('stack')
})
it('survives the characters people actually put in a label', () => {
const awkward = 'CNC #4 & 5 - 50% duty, "spare"'
const back = readFragment(buildFragment(state({ content: awkward }), DEFAULTS))
expect(back.content).toBe(awkward)
})
it('ignores a key it does not know', () => {
// A link made by a newer version must still open here, minus the parts
// this version cannot use.
const back = readFragment('#c=X&somethingnew=1')
expect(back.content).toBe('X')
expect(back.somethingnew).toBeUndefined()
})
it('is empty for an empty or absent fragment', () => {
expect(readFragment('')).toEqual({})
expect(readFragment('#')).toEqual({})
expect(readFragment(undefined)).toEqual({})
})
})
describe('coerce', () => {
it('keeps a number a number', () => {
// '0' + '2' is '02'; 0 + 2 is 2. The nudge fields are arithmetic.
expect(coerce('2', 0)).toBe(2)
expect(coerce('0.4286', 0.5)).toBeCloseTo(0.4286)
})
it('falls back to the current value when the link is nonsense', () => {
expect(coerce('not-a-number', 203)).toBe(203)
})
it('reads a boolean back as a boolean', () => {
expect(coerce('true', false)).toBe(true)
expect(coerce('false', true)).toBe(false)
})
it('leaves a string alone', () => {
expect(coerce('stack', 'side')).toBe('stack')
})
})