* Start scanner-mobile-checkout convoy for the cart-then-commit phone flow. Co-authored-by: Cursor <cursoragent@cursor.com> * Ship a cart-then-commit mobile scanner so phone sessions stay on the camera. Scan matches enqueue locally instead of auto-writing ownership, checkout happens in a sheet, and audit fixes cover stale commit detection, returnUrl open redirects, nested Escape, and ember detection chrome. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
118 lines
3.2 KiB
JavaScript
118 lines
3.2 KiB
JavaScript
// @vitest-environment jsdom
|
|
import { describe, expect, it, beforeEach } from 'vitest';
|
|
import {
|
|
DEFAULT_SCANNER_DESTINATION,
|
|
destinationActionKey,
|
|
mergeScannedCardEntry,
|
|
SCANNER_CART_STORAGE_KEY,
|
|
loadScannerCart,
|
|
saveScannerCart,
|
|
clearScannerCartStorage,
|
|
} from '../../lib/scanner-session.js';
|
|
|
|
describe('destinationActionKey', () => {
|
|
it('maps owned destination to owned action key', () => {
|
|
expect(destinationActionKey(DEFAULT_SCANNER_DESTINATION)).toBe('owned');
|
|
});
|
|
|
|
it('returns pending when destination is missing', () => {
|
|
expect(destinationActionKey(null)).toBe('pending');
|
|
});
|
|
});
|
|
|
|
describe('mergeScannedCardEntry', () => {
|
|
const scanDefaults = { condition: 'NM', isFoil: false };
|
|
|
|
it('creates a new queue entry with scan defaults', () => {
|
|
const { cardEntry, scannedCards, merged } = mergeScannedCardEntry([], {
|
|
name: 'Pikachu',
|
|
set: 'Base',
|
|
databaseId: 1,
|
|
}, scanDefaults);
|
|
|
|
expect(merged).toBe(false);
|
|
expect(scannedCards).toHaveLength(1);
|
|
expect(cardEntry).toMatchObject({
|
|
name: 'Pikachu',
|
|
set: 'Base',
|
|
quantity: 1,
|
|
condition: 'NM',
|
|
isFoil: false,
|
|
processed: false,
|
|
});
|
|
expect(cardEntry.id).toBeTruthy();
|
|
});
|
|
|
|
it('increments quantity for an unprocessed duplicate name+set', () => {
|
|
const existing = {
|
|
id: 99,
|
|
name: 'Bolt',
|
|
set: 'Alpha',
|
|
quantity: 2,
|
|
processed: false,
|
|
};
|
|
|
|
const { cardEntry, scannedCards, merged } = mergeScannedCardEntry(
|
|
[existing],
|
|
{ name: 'Bolt', set: 'Alpha', databaseId: 1, scanImageUrl: 'https://blob/new.jpg' },
|
|
scanDefaults
|
|
);
|
|
|
|
expect(merged).toBe(true);
|
|
expect(scannedCards).toHaveLength(1);
|
|
expect(cardEntry.quantity).toBe(3);
|
|
expect(cardEntry.scanImageUrl).toBe('https://blob/new.jpg');
|
|
});
|
|
});
|
|
|
|
describe('scanner cart sessionStorage', () => {
|
|
const sampleCards = [
|
|
{
|
|
id: 1,
|
|
name: 'Pikachu',
|
|
set: 'Base',
|
|
quantity: 1,
|
|
condition: 'NM',
|
|
isFoil: false,
|
|
processed: false,
|
|
},
|
|
];
|
|
|
|
beforeEach(() => {
|
|
sessionStorage.clear();
|
|
});
|
|
|
|
it('round-trips cart rows and selection within a tab', () => {
|
|
saveScannerCart({ scannedCards: sampleCards, selectedCardIds: [1] });
|
|
|
|
const loaded = loadScannerCart();
|
|
expect(loaded).toEqual({ scannedCards: sampleCards, selectedCardIds: [1] });
|
|
expect(sessionStorage.getItem(SCANNER_CART_STORAGE_KEY)).toBeTruthy();
|
|
});
|
|
|
|
it('omits capturedImage and ocrText from persisted cart rows', () => {
|
|
saveScannerCart({
|
|
scannedCards: [
|
|
{
|
|
...sampleCards[0],
|
|
capturedImage: 'data:image/png;base64,AAAA',
|
|
ocrText: 'raw ocr',
|
|
},
|
|
],
|
|
selectedCardIds: [1],
|
|
});
|
|
|
|
const loaded = loadScannerCart();
|
|
expect(loaded.scannedCards[0].capturedImage).toBeUndefined();
|
|
expect(loaded.scannedCards[0].ocrText).toBeUndefined();
|
|
expect(loaded.scannedCards[0].name).toBe('Pikachu');
|
|
});
|
|
|
|
it('clearScannerCartStorage removes persisted cart state', () => {
|
|
saveScannerCart({ scannedCards: sampleCards, selectedCardIds: [1] });
|
|
clearScannerCartStorage();
|
|
|
|
expect(loadScannerCart()).toBeNull();
|
|
expect(sessionStorage.getItem(SCANNER_CART_STORAGE_KEY)).toBeNull();
|
|
});
|
|
});
|