Skip to content

Commit 1d4f140

Browse files
Otto WachterOtto Wachter
Otto Wachter
authored and
Otto Wachter
committed
comment
1 parent 8bffff1 commit 1d4f140

File tree

4 files changed

+200
-0
lines changed

4 files changed

+200
-0
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ report/*
88

99
# auto-gen PHP files/logs
1010
php_errors.log
11+
.aider*

js/test/toast-1.js

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
// __tests__/toast.test.js
2+
import { Toast } from '../js/modules/toast';
3+
4+
describe('Toast', () => {
5+
let toast;
6+
let mockContainer;
7+
8+
beforeEach(() => {
9+
document.body.innerHTML =
10+
'<div id="rackContent"></div><button id="toggleRackButton"></button>';
11+
mockContainer = document.createElement('div');
12+
document.body.appendChild(mockContainer);
13+
toast = new Toast({ position: 'bottom-right', maxVisible: 2 });
14+
});
15+
16+
afterEach(() => {
17+
document.body.innerHTML = '';
18+
});
19+
20+
it('should create a toast container with the correct position', () => {
21+
const container = toast.createContainer('top-left');
22+
expect(container.className).toBe(
23+
'enable-toast__container enable-toast__container--top-left',
24+
);
25+
});
26+
27+
it('should show a toast with the correct message and level', () => {
28+
toast.showToast('Test message', 'success');
29+
const toastElement = toast.container.querySelector(
30+
'.enable-toast__toast',
31+
);
32+
expect(toastElement).not.toBeNull();
33+
expect(toastElement.querySelector('span').textContent).toBe(
34+
'Test message',
35+
);
36+
expect(toastElement.style.backgroundColor).toBe('#28a745'); // success level color
37+
});
38+
39+
it('should dismiss a toast when the close button is clicked', () => {
40+
toast.showToast('Test message', 'normal');
41+
const toastElement = toast.container.querySelector(
42+
'.enable-toast__toast',
43+
);
44+
toastElement.querySelector('.enable-toast__close-button').click();
45+
expect(
46+
toastElement.classList.contains('enable-toast__toast--exit'),
47+
).toBe(true);
48+
});
49+
50+
it('should update visible toasts correctly', () => {
51+
toast.showToast('Message 1', 'normal');
52+
toast.showToast('Message 2', 'normal');
53+
toast.showToast('Message 3', 'normal');
54+
expect(toast.visibleQueue.length).toBe(2); // maxVisible is 2
55+
expect(toast.toastQueue.length).toBe(3);
56+
});
57+
58+
it('should toggle toast rack visibility', () => {
59+
const toggleRackButton = document.getElementById('toggleRackButton');
60+
const rack = document.getElementById('rackContent');
61+
rack.style.display = 'none';
62+
toggleRackButton.click();
63+
expect(rack.style.display).toBe('block');
64+
toggleRackButton.click();
65+
expect(rack.style.display).toBe('none');
66+
});
67+
});

js/test/toast.js

+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// __tests__/toast.test.js
2+
import { Toast } from '../js/modules/toast';
3+
4+
describe('Toast Module', () => {
5+
let toast;
6+
let container;
7+
8+
beforeEach(() => {
9+
document.body.innerHTML =
10+
'<div id="rackContent"></div><button id="toggleRackButton"></button>';
11+
container = document.createElement('div');
12+
container.id = 'toastContainer';
13+
document.body.appendChild(container);
14+
15+
toast = new Toast({
16+
position: 'bottom-right',
17+
maxVisible: 3,
18+
levels: {
19+
normal: { color: '#007bff' },
20+
error: { color: '#dc3545' },
21+
warning: { color: '#ffc107' },
22+
success: { color: '#28a745' },
23+
},
24+
});
25+
});
26+
27+
afterEach(() => {
28+
document.body.innerHTML = '';
29+
});
30+
31+
it('should create a container with correct position', () => {
32+
expect(
33+
toast.container.classList.contains(
34+
'enable-toast__container--bottom-right',
35+
),
36+
).toBe(true);
37+
});
38+
39+
it('should display a toast message with correct level', () => {
40+
toast.showToast('This is a normal toast', 'normal');
41+
const toastElement = toast.container.querySelector(
42+
'.enable-toast__toast',
43+
);
44+
expect(toastElement).not.toBeNull();
45+
expect(toastElement.style.backgroundColor).toBe('#007bff');
46+
expect(
47+
toastElement.textContent.includes('This is a normal toast'),
48+
).toBe(true);
49+
});
50+
51+
it('should display multiple toasts up to maxVisible limit', () => {
52+
toast.showToast('Toast 1', 'normal');
53+
toast.showToast('Toast 2', 'success');
54+
toast.showToast('Toast 3', 'warning');
55+
toast.showToast('Toast 4', 'error');
56+
57+
const visibleToasts = toast.container.querySelectorAll(
58+
'.enable-toast__toast--visible',
59+
);
60+
expect(visibleToasts.length).toBe(3);
61+
expect(visibleToasts[0].textContent.includes('Toast 2')).toBe(true);
62+
expect(visibleToasts[1].textContent.includes('Toast 3')).toBe(true);
63+
expect(visibleToasts[2].textContent.includes('Toast 4')).toBe(true);
64+
});
65+
66+
it('should remove toast from DOM when dismissed', () => {
67+
toast.showToast('Dismiss me', 'normal');
68+
const toastElement = toast.container.querySelector(
69+
'.enable-toast__toast',
70+
);
71+
const closeButton = toastElement.querySelector(
72+
'.enable-toast__close-button',
73+
);
74+
75+
closeButton.click();
76+
77+
setTimeout(() => {
78+
expect(toastElement.parentNode).toBeNull();
79+
}, 500);
80+
});
81+
82+
it('should update aria-live attribute when specified', () => {
83+
toast.ariaLive = 'assertive';
84+
toast.showToast('Assertive toast', 'normal');
85+
const toastElement = toast.container.querySelector(
86+
'.enable-toast__toast',
87+
);
88+
expect(toastElement.getAttribute('aria-live')).toBe('assertive');
89+
});
90+
91+
it('should add and remove toasts from rack correctly', () => {
92+
toast.showToast('Toast in rack', 'normal');
93+
const rackContent = document.getElementById('rackContent');
94+
const rackToasts = rackContent.querySelectorAll('.enable-toast__toast');
95+
expect(rackToasts.length).toBe(1);
96+
97+
toast.dismissToast(toast.toastQueue[0]);
98+
setTimeout(() => {
99+
expect(
100+
rackContent.querySelectorAll('.enable-toast__toast').length,
101+
).toBe(0);
102+
}, 500);
103+
});
104+
105+
it('should toggle the toast rack visibility', () => {
106+
const toggleRackButton = document.getElementById('toggleRackButton');
107+
const rack = document.getElementById('toastRack');
108+
109+
toggleRackButton.click();
110+
expect(rack.style.display).toBe('block');
111+
112+
toggleRackButton.click();
113+
expect(rack.style.display).toBe('none');
114+
});
115+
116+
it('should handle keyboard navigation for dismissing toasts', () => {
117+
toast.showToast('Keyboard dismiss', 'normal');
118+
const toastElement = toast.container.querySelector(
119+
'.enable-toast__toast',
120+
);
121+
toastElement.focus();
122+
const event = new KeyboardEvent('keydown', { key: 'Escape' });
123+
toastElement.dispatchEvent(event);
124+
125+
setTimeout(() => {
126+
expect(
127+
toastElement.classList.contains('enable-toast__toast--exit'),
128+
).toBe(true);
129+
}, 500);
130+
});
131+
});

less/toast.less

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
}
9191
}
9292

93+
// toast rack
9394
&__rack {
9495
position: fixed;
9596
top: 20px;

0 commit comments

Comments
 (0)