Full document, spreadsheet, slideshow, and diagram tooling
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 222 lines 8.0 kB view raw
1import { describe, it, expect } from 'vitest'; 2import { 3 extractFormat, 4 applyFormat, 5 FORMAT_PROPERTIES, 6} from '../src/sheets/format-painter.js'; 7 8// ============================================================ 9// FORMAT_PROPERTIES constant 10// ============================================================ 11 12describe('FORMAT_PROPERTIES', () => { 13 it('includes all expected formatting properties', () => { 14 expect(FORMAT_PROPERTIES).toContain('bold'); 15 expect(FORMAT_PROPERTIES).toContain('italic'); 16 expect(FORMAT_PROPERTIES).toContain('align'); 17 expect(FORMAT_PROPERTIES).toContain('color'); 18 expect(FORMAT_PROPERTIES).toContain('bg'); 19 expect(FORMAT_PROPERTIES).toContain('borders'); 20 expect(FORMAT_PROPERTIES).toContain('format'); 21 expect(FORMAT_PROPERTIES).toContain('wrap'); 22 }); 23 24 it('includes new formatting properties (underline, strikethrough, verticalAlign, fontSize, fontFamily)', () => { 25 expect(FORMAT_PROPERTIES).toContain('underline'); 26 expect(FORMAT_PROPERTIES).toContain('strikethrough'); 27 expect(FORMAT_PROPERTIES).toContain('verticalAlign'); 28 expect(FORMAT_PROPERTIES).toContain('fontSize'); 29 expect(FORMAT_PROPERTIES).toContain('fontFamily'); 30 }); 31}); 32 33// ============================================================ 34// extractFormat — new properties 35// ============================================================ 36 37describe('extractFormat — new properties', () => { 38 it('extracts underline and strikethrough', () => { 39 const cellData = { v: 'x', f: '', s: { underline: true, strikethrough: true } }; 40 const result = extractFormat(cellData); 41 expect(result.underline).toBe(true); 42 expect(result.strikethrough).toBe(true); 43 }); 44 45 it('extracts fontSize and fontFamily', () => { 46 const cellData = { v: 'x', f: '', s: { fontSize: 14, fontFamily: 'serif' } }; 47 const result = extractFormat(cellData); 48 expect(result.fontSize).toBe(14); 49 expect(result.fontFamily).toBe('serif'); 50 }); 51 52 it('extracts verticalAlign', () => { 53 const cellData = { v: 'x', f: '', s: { verticalAlign: 'bottom' } }; 54 const result = extractFormat(cellData); 55 expect(result.verticalAlign).toBe('bottom'); 56 }); 57}); 58 59// ============================================================ 60// applyFormat — new properties 61// ============================================================ 62 63describe('applyFormat — new properties', () => { 64 it('applies new properties to a cell', () => { 65 const existing = { bold: true }; 66 const format = { underline: true, fontSize: 16, fontFamily: 'monospace', verticalAlign: 'middle', strikethrough: true }; 67 const result = applyFormat(existing, format); 68 expect(result.bold).toBe(true); 69 expect(result.underline).toBe(true); 70 expect(result.fontSize).toBe(16); 71 expect(result.fontFamily).toBe('monospace'); 72 expect(result.verticalAlign).toBe('middle'); 73 expect(result.strikethrough).toBe(true); 74 }); 75}); 76 77// ============================================================ 78// extractFormat — extracts formatting from cell data 79// ============================================================ 80 81describe('extractFormat', () => { 82 it('extracts all style properties from cell data', () => { 83 const cellData = { 84 v: 42, 85 f: 'A1+B1', 86 s: { 87 bold: true, 88 italic: true, 89 align: 'center', 90 color: '#ff0000', 91 bg: '#eeeeee', 92 borders: { top: '1px solid #999' }, 93 format: 'currency', 94 wrap: true, 95 }, 96 }; 97 const result = extractFormat(cellData); 98 expect(result.bold).toBe(true); 99 expect(result.italic).toBe(true); 100 expect(result.align).toBe('center'); 101 expect(result.color).toBe('#ff0000'); 102 expect(result.bg).toBe('#eeeeee'); 103 expect(result.borders).toEqual({ top: '1px solid #999' }); 104 expect(result.format).toBe('currency'); 105 expect(result.wrap).toBe(true); 106 }); 107 108 it('returns empty object for cell with no style', () => { 109 const cellData = { v: 'hello', f: '', s: {} }; 110 const result = extractFormat(cellData); 111 expect(result).toEqual({}); 112 }); 113 114 it('returns empty object for null cell data', () => { 115 const result = extractFormat(null); 116 expect(result).toEqual({}); 117 }); 118 119 it('returns empty object for undefined cell data', () => { 120 const result = extractFormat(undefined); 121 expect(result).toEqual({}); 122 }); 123 124 it('only extracts known format properties, ignores others', () => { 125 const cellData = { 126 v: 10, 127 f: '', 128 s: { 129 bold: true, 130 someRandomProp: 'test', 131 anotherProp: 123, 132 }, 133 }; 134 const result = extractFormat(cellData); 135 expect(result.bold).toBe(true); 136 expect(result).not.toHaveProperty('someRandomProp'); 137 expect(result).not.toHaveProperty('anotherProp'); 138 }); 139 140 it('extracts partial style (only some properties set)', () => { 141 const cellData = { v: '', f: '', s: { bold: true, bg: '#fff' } }; 142 const result = extractFormat(cellData); 143 expect(result.bold).toBe(true); 144 expect(result.bg).toBe('#fff'); 145 expect(result).not.toHaveProperty('italic'); 146 expect(result).not.toHaveProperty('color'); 147 }); 148}); 149 150// ============================================================ 151// applyFormat — merges format into existing cell data 152// ============================================================ 153 154describe('applyFormat', () => { 155 it('applies all format properties to cell with existing style', () => { 156 const existingStyle = { bold: false, color: '#000' }; 157 const format = { bold: true, italic: true, bg: '#eee' }; 158 const result = applyFormat(existingStyle, format); 159 expect(result.bold).toBe(true); 160 expect(result.italic).toBe(true); 161 expect(result.bg).toBe('#eee'); 162 // Original non-format properties preserved 163 expect(result.color).toBe('#000'); 164 }); 165 166 it('replaces existing format properties', () => { 167 const existingStyle = { bold: true, align: 'left', color: '#f00' }; 168 const format = { bold: false, align: 'center', color: '#00f' }; 169 const result = applyFormat(existingStyle, format); 170 expect(result.bold).toBe(false); 171 expect(result.align).toBe('center'); 172 expect(result.color).toBe('#00f'); 173 }); 174 175 it('handles null existing style', () => { 176 const format = { bold: true, bg: '#eee' }; 177 const result = applyFormat(null, format); 178 expect(result.bold).toBe(true); 179 expect(result.bg).toBe('#eee'); 180 }); 181 182 it('handles undefined existing style', () => { 183 const format = { italic: true }; 184 const result = applyFormat(undefined, format); 185 expect(result.italic).toBe(true); 186 }); 187 188 it('handles empty format (clears nothing)', () => { 189 const existingStyle = { bold: true, color: '#f00' }; 190 const format = {}; 191 const result = applyFormat(existingStyle, format); 192 expect(result.bold).toBe(true); 193 expect(result.color).toBe('#f00'); 194 }); 195 196 it('does not mutate original objects', () => { 197 const existingStyle = { bold: true }; 198 const format = { italic: true }; 199 const result = applyFormat(existingStyle, format); 200 expect(existingStyle).toEqual({ bold: true }); 201 expect(format).toEqual({ italic: true }); 202 expect(result).toEqual({ bold: true, italic: true }); 203 }); 204 205 it('handles borders object deep copy', () => { 206 const format = { borders: { top: '1px solid #000', bottom: '1px solid #000' } }; 207 const result = applyFormat({}, format); 208 expect(result.borders).toEqual(format.borders); 209 // Verify it's a copy not a reference 210 expect(result.borders).not.toBe(format.borders); 211 }); 212 213 it('clears format properties when value is undefined', () => { 214 const existingStyle = { bold: true, italic: true, bg: '#fff' }; 215 const format = { bold: undefined, italic: false }; 216 const result = applyFormat(existingStyle, format); 217 // undefined properties are removed 218 expect(result).not.toHaveProperty('bold'); 219 expect(result.italic).toBe(false); 220 expect(result.bg).toBe('#fff'); 221 }); 222});