comparison design_system/test/storybook_test.js @ 253:fdf3816959cb

[ui] Add Sonner-like notification stack Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Tue, 04 Aug 2026 12:21:19 -0700
parents 7a7581f040e8
children 2b6e732087ff
comparison
equal deleted inserted replaced
252:7a7581f040e8 253:fdf3816959cb
436 assert.deepEqual(bounded, { accepted: 25, size: 23, visible: 3 }); 436 assert.deepEqual(bounded, { accepted: 25, size: 23, visible: 3 });
437 assert.equal( 437 assert.equal(
438 await notificationScope.locator('article').count(), 438 await notificationScope.locator('article').count(),
439 3, 439 3,
440 ); 440 );
441 await page.waitForFunction(() =>
442 [...document.querySelectorAll(
443 'zen-notifications article',
444 )].some(article => article.dataset.depth === '2')
445 );
446 const collapsedStack = await notificationScope.locator(
447 '[data-zen-notification-stack]',
448 ).evaluate(stack => {
449 const articles = [...stack.querySelectorAll('article')];
450 return {
451 depths: articles.map(article => article.dataset.depth),
452 height: stack.getBoundingClientRect().height,
453 positions: articles.map(article =>
454 getComputedStyle(article).position
455 ),
456 transforms: articles.map(article =>
457 getComputedStyle(article).transform
458 ),
459 };
460 });
461 assert.deepEqual(collapsedStack.depths, ['2', '1', '0']);
462 assert.deepEqual(
463 collapsedStack.positions,
464 ['absolute', 'absolute', 'absolute'],
465 );
466 await notificationScope.locator('article').last().hover();
467 await page.waitForTimeout(300);
468 const expandedStack = await notificationScope.locator(
469 '[data-zen-notification-stack]',
470 ).evaluate(stack => ({
471 height: stack.getBoundingClientRect().height,
472 rects: [...stack.querySelectorAll('article')].map(article => {
473 const bounds = article.getBoundingClientRect();
474 return {
475 bottom: bounds.bottom,
476 left: bounds.left,
477 right: bounds.right,
478 top: bounds.top,
479 };
480 }),
481 tops: [...stack.querySelectorAll('article')].map(
482 article => Math.round(article.getBoundingClientRect().top),
483 ),
484 transforms: [...stack.querySelectorAll('article')].map(
485 article => getComputedStyle(article).transform,
486 ),
487 }));
488 assert.ok(expandedStack.height > collapsedStack.height);
489 assert.equal(new Set(expandedStack.tops).size, 3);
490 const expandedGaps = [
491 expandedStack.rects[1].top - expandedStack.rects[0].bottom,
492 expandedStack.rects[2].top - expandedStack.rects[1].bottom,
493 ];
494 for (const gap of expandedGaps) {
495 assert.ok(gap >= 10 && gap <= 14, JSON.stringify(expandedGaps));
496 }
497 assert.notDeepEqual(
498 expandedStack.transforms,
499 collapsedStack.transforms,
500 );
501 const gapX =
502 (expandedStack.rects[0].left + expandedStack.rects[0].right) / 2;
503 const gapY =
504 (expandedStack.rects[0].bottom + expandedStack.rects[1].top) / 2;
505 await page.mouse.move(gapX, gapY);
506 await page.waitForTimeout(100);
507 const gapState = await notificationScope.locator(
508 '[data-zen-notification-stack]',
509 ).evaluate(stack => ({
510 height: stack.getBoundingClientRect().height,
511 hovered: stack.matches(':hover'),
512 }));
513 assert.equal(gapState.hovered, true);
514 assert.ok(gapState.height >= expandedStack.height - 1);
515 await page.mouse.move(0, 0);
441 516
442 const actionScope = await page.evaluate(() => { 517 const actionScope = await page.evaluate(() => {
443 const scope = document.createElement('zen-notifications'); 518 const scope = document.createElement('zen-notifications');
444 scope.id = 'action-scope'; 519 scope.id = 'action-scope';
445 const source = document.createElement('button'); 520 const source = document.createElement('button');
520 composed: false, 595 composed: false,
521 detail: { version: 1, id: 'action' }, 596 detail: { version: 1, id: 'action' },
522 }, 597 },
523 )); 598 ));
524 }); 599 });
525 assert.equal(await actionArticle.count(), 0); 600 await actionArticle.waitFor({ state: 'detached' });
526 601
527 await page.evaluate(() => { 602 await page.evaluate(() => {
528 const scope = document.createElement('zen-notifications'); 603 const scope = document.createElement('zen-notifications');
529 scope.id = 'announcement-scope'; 604 scope.id = 'announcement-scope';
530 const source = document.createElement('button'); 605 const source = document.createElement('button');