|
7 | 7 |
|
8 | 8 | import { describe, test, expect, vi } from 'vitest'; |
9 | 9 | import { parse, render, createUI } from './index'; |
10 | | -import type { AST, ParseResult, OnSceneChangeCallback } from './index'; |
| 10 | +import type { AST, ParseResult, OnSceneChangeCallback, DeviceType, RenderOptions } from './index'; |
11 | 11 |
|
12 | 12 | describe('render() input validation (Issue #1)', () => { |
13 | 13 | const validWireframe = ` |
@@ -250,3 +250,112 @@ describe('onSceneChange callback (Issue #2)', () => { |
250 | 250 | } |
251 | 251 | }); |
252 | 252 | }); |
| 253 | + |
| 254 | +describe('device option override (Issue #11)', () => { |
| 255 | + const desktopWireframe = ` |
| 256 | +@scene: test |
| 257 | +@device: desktop |
| 258 | +
|
| 259 | ++---------------+ |
| 260 | +| Desktop Scene | |
| 261 | ++---------------+ |
| 262 | +`; |
| 263 | + |
| 264 | + test('DeviceType type is exported', () => { |
| 265 | + // Verify the type is exported by using it |
| 266 | + const device: DeviceType = 'mobile'; |
| 267 | + expect(typeof device).toBe('string'); |
| 268 | + }); |
| 269 | + |
| 270 | + test('RenderOptions includes device field in type definition', () => { |
| 271 | + // Verify the device option is part of RenderOptions type |
| 272 | + const options: RenderOptions = { |
| 273 | + device: 'mobile', |
| 274 | + }; |
| 275 | + expect(options.device).toBe('mobile'); |
| 276 | + }); |
| 277 | + |
| 278 | + test('RenderOptions accepts all valid device types', () => { |
| 279 | + const deviceTypes: DeviceType[] = [ |
| 280 | + 'desktop', |
| 281 | + 'laptop', |
| 282 | + 'tablet', |
| 283 | + 'tablet-landscape', |
| 284 | + 'mobile', |
| 285 | + 'mobile-landscape', |
| 286 | + ]; |
| 287 | + |
| 288 | + deviceTypes.forEach((deviceType) => { |
| 289 | + const options: RenderOptions = { device: deviceType }; |
| 290 | + expect(options.device).toBe(deviceType); |
| 291 | + }); |
| 292 | + }); |
| 293 | + |
| 294 | + // Note: DOM-dependent tests are skipped in Node.js environment |
| 295 | + test.skip('render accepts device option without throwing (requires DOM)', () => { |
| 296 | + const result = parse(desktopWireframe); |
| 297 | + expect(result.success).toBe(true); |
| 298 | + |
| 299 | + if (result.success) { |
| 300 | + // This should not throw - just verify the API accepts the option |
| 301 | + expect(() => { |
| 302 | + render(result.ast, { device: 'mobile' }); |
| 303 | + }).not.toThrow(); |
| 304 | + } |
| 305 | + }); |
| 306 | + |
| 307 | + test.skip('createUI accepts device option without throwing (requires DOM)', () => { |
| 308 | + // Verify the API accepts the option |
| 309 | + expect(() => { |
| 310 | + createUI(desktopWireframe, { device: 'tablet' }); |
| 311 | + }).not.toThrow(); |
| 312 | + }); |
| 313 | + |
| 314 | + test.skip('device option overrides scene-defined device class (requires DOM)', () => { |
| 315 | + const result = parse(desktopWireframe); |
| 316 | + expect(result.success).toBe(true); |
| 317 | + |
| 318 | + if (result.success) { |
| 319 | + // Render with mobile override |
| 320 | + const { root } = render(result.ast, { device: 'mobile' }); |
| 321 | + |
| 322 | + // Should have mobile class, not desktop |
| 323 | + expect(root.classList.contains('wf-device-mobile')).toBe(true); |
| 324 | + expect(root.classList.contains('wf-device-desktop')).toBe(false); |
| 325 | + } |
| 326 | + }); |
| 327 | + |
| 328 | + test.skip('device option applies correct class for all device types (requires DOM)', () => { |
| 329 | + const result = parse(desktopWireframe); |
| 330 | + expect(result.success).toBe(true); |
| 331 | + |
| 332 | + if (result.success) { |
| 333 | + const deviceClassMap: Record<DeviceType, string> = { |
| 334 | + desktop: 'wf-device-desktop', |
| 335 | + laptop: 'wf-device-laptop', |
| 336 | + tablet: 'wf-device-tablet', |
| 337 | + 'tablet-landscape': 'wf-device-tablet-landscape', |
| 338 | + mobile: 'wf-device-mobile', |
| 339 | + 'mobile-landscape': 'wf-device-mobile-landscape', |
| 340 | + }; |
| 341 | + |
| 342 | + Object.entries(deviceClassMap).forEach(([deviceType, expectedClass]) => { |
| 343 | + const { root } = render(result.ast, { device: deviceType as DeviceType }); |
| 344 | + expect(root.classList.contains(expectedClass)).toBe(true); |
| 345 | + }); |
| 346 | + } |
| 347 | + }); |
| 348 | + |
| 349 | + test.skip('renders with scene device when no override provided (requires DOM)', () => { |
| 350 | + const result = parse(desktopWireframe); |
| 351 | + expect(result.success).toBe(true); |
| 352 | + |
| 353 | + if (result.success) { |
| 354 | + // Render without device override |
| 355 | + const { root } = render(result.ast); |
| 356 | + |
| 357 | + // Should use the scene-defined desktop device |
| 358 | + expect(root.classList.contains('wf-device-desktop')).toBe(true); |
| 359 | + } |
| 360 | + }); |
| 361 | +}); |
0 commit comments