create-elit 3.6.5 → 3.6.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -68
- package/dist/index.js +121 -8
- package/dist/templates/{elit.config.ts → auth-fullstack-example/elit.config.ts} +51 -0
- package/dist/templates/auth-fullstack-example/package.json +26 -0
- package/dist/templates/auth-fullstack-example/src/native-screen.ts +10 -0
- package/dist/templates/auth-fullstack-example/wapkignore +10 -0
- package/dist/templates/auth-fullstack-example/wapkpatch +1 -0
- package/dist/templates/basic-example/README.md +39 -0
- package/dist/templates/basic-example/elit.config.ts +114 -0
- package/dist/templates/basic-example/gitignore +7 -0
- package/dist/templates/basic-example/package.json +26 -0
- package/dist/templates/basic-example/public/favicon.svg +22 -0
- package/dist/templates/basic-example/public/index.html +14 -0
- package/dist/templates/basic-example/src/client.ts +15 -0
- package/dist/templates/basic-example/src/main.ts +89 -0
- package/dist/templates/basic-example/src/mobile.ts +35 -0
- package/dist/templates/basic-example/src/styles.ts +273 -0
- package/dist/templates/basic-example/tsconfig.json +24 -0
- package/dist/templates/basic-example/wapkignore +10 -0
- package/dist/templates/basic-example/wapkpatch +1 -0
- package/dist/templates/todo-fullstack-example/README.md +39 -0
- package/dist/templates/todo-fullstack-example/databases/todo.ts +41 -0
- package/dist/templates/todo-fullstack-example/elit.config.ts +123 -0
- package/dist/templates/todo-fullstack-example/gitignore +7 -0
- package/dist/templates/todo-fullstack-example/package.json +26 -0
- package/dist/templates/todo-fullstack-example/public/favicon.svg +22 -0
- package/dist/templates/todo-fullstack-example/public/index.html +14 -0
- package/dist/templates/todo-fullstack-example/src/client.ts +15 -0
- package/dist/templates/todo-fullstack-example/src/components/AppFooter.ts +16 -0
- package/dist/templates/todo-fullstack-example/src/components/AppHeader.ts +23 -0
- package/dist/templates/todo-fullstack-example/src/main.ts +7 -0
- package/dist/templates/todo-fullstack-example/src/mobile.ts +36 -0
- package/dist/templates/todo-fullstack-example/src/pages/TodoPage.ts +491 -0
- package/dist/templates/todo-fullstack-example/src/router.ts +16 -0
- package/dist/templates/todo-fullstack-example/src/server.ts +226 -0
- package/dist/templates/todo-fullstack-example/src/styles.ts +768 -0
- package/dist/templates/todo-fullstack-example/src/todo-types.ts +19 -0
- package/dist/templates/todo-fullstack-example/src/web.ts +16 -0
- package/dist/templates/todo-fullstack-example/tsconfig.json +24 -0
- package/dist/templates/todo-fullstack-example/wapkignore +10 -0
- package/dist/templates/todo-fullstack-example/wapkpatch +1 -0
- package/package.json +1 -1
- package/dist/templates/package.json +0 -17
- package/dist/templates/src/client.test.ts +0 -292
- package/dist/templates/src/components/Footer.test.ts +0 -226
- package/dist/templates/src/components/Header.test.ts +0 -493
- package/dist/templates/src/pages/ChatListPage.test.ts +0 -603
- package/dist/templates/src/pages/ChatPage.test.ts +0 -530
- package/dist/templates/src/pages/ForgotPasswordPage.test.ts +0 -484
- package/dist/templates/src/pages/HomePage.test.ts +0 -601
- package/dist/templates/src/pages/LoginPage.test.ts +0 -619
- package/dist/templates/src/pages/PrivateChatPage.test.ts +0 -556
- package/dist/templates/src/pages/ProfilePage.test.ts +0 -628
- package/dist/templates/src/pages/RegisterPage.test.ts +0 -661
- /package/dist/templates/{README.md → auth-fullstack-example/README.md} +0 -0
- /package/dist/templates/{databases → auth-fullstack-example/databases}/users.ts +0 -0
- /package/dist/templates/{gitignore → auth-fullstack-example/gitignore} +0 -0
- /package/dist/templates/{public → auth-fullstack-example/public}/favicon.svg +0 -0
- /package/dist/templates/{public → auth-fullstack-example/public}/index.html +0 -0
- /package/dist/templates/{src → auth-fullstack-example/src}/client.ts +0 -0
- /package/dist/templates/{src → auth-fullstack-example/src}/components/Footer.ts +0 -0
- /package/dist/templates/{src → auth-fullstack-example/src}/components/Header.ts +0 -0
- /package/dist/templates/{src → auth-fullstack-example/src}/components/index.ts +0 -0
- /package/dist/templates/{src → auth-fullstack-example/src}/main.ts +0 -0
- /package/dist/templates/{src → auth-fullstack-example/src}/pages/ChatListPage.ts +0 -0
- /package/dist/templates/{src → auth-fullstack-example/src}/pages/ChatPage.ts +0 -0
- /package/dist/templates/{src → auth-fullstack-example/src}/pages/ForgotPasswordPage.ts +0 -0
- /package/dist/templates/{src → auth-fullstack-example/src}/pages/HomePage.ts +0 -0
- /package/dist/templates/{src → auth-fullstack-example/src}/pages/LoginPage.ts +0 -0
- /package/dist/templates/{src → auth-fullstack-example/src}/pages/PrivateChatPage.ts +0 -0
- /package/dist/templates/{src → auth-fullstack-example/src}/pages/ProfilePage.ts +0 -0
- /package/dist/templates/{src → auth-fullstack-example/src}/pages/RegisterPage.ts +0 -0
- /package/dist/templates/{src → auth-fullstack-example/src}/router.ts +0 -0
- /package/dist/templates/{src → auth-fullstack-example/src}/server.ts +0 -0
- /package/dist/templates/{src → auth-fullstack-example/src}/styles.ts +0 -0
- /package/dist/templates/{tsconfig.json → auth-fullstack-example/tsconfig.json} +0 -0
|
@@ -1,484 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ForgotPasswordPage Component Unit Tests
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
// CRITICAL: Set up ALL mocks BEFORE importing ForgotPasswordPage component
|
|
6
|
-
// The component may access globals during import, so mocks must be set up first
|
|
7
|
-
|
|
8
|
-
// Simple mock function to track calls
|
|
9
|
-
function mockFn() {
|
|
10
|
-
const calls: any[] = [];
|
|
11
|
-
const fn = (...args: any[]) => {
|
|
12
|
-
calls.push(args);
|
|
13
|
-
return undefined;
|
|
14
|
-
};
|
|
15
|
-
fn.calls = calls;
|
|
16
|
-
fn.mockClear = () => {
|
|
17
|
-
calls.length = 0;
|
|
18
|
-
};
|
|
19
|
-
return fn;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Mock router
|
|
23
|
-
const mockRouter = {
|
|
24
|
-
push: mockFn() as any,
|
|
25
|
-
replace: mockFn() as any,
|
|
26
|
-
go: mockFn() as any,
|
|
27
|
-
back: mockFn() as any,
|
|
28
|
-
forward: mockFn() as any,
|
|
29
|
-
currentPath: '/',
|
|
30
|
-
currentState: null
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
// SETUP GLOBALS BEFORE IMPORT
|
|
34
|
-
// Set up global mocks
|
|
35
|
-
(global as any).window = {
|
|
36
|
-
addEventListener: mockFn(),
|
|
37
|
-
removeEventListener: mockFn(),
|
|
38
|
-
localStorage: {
|
|
39
|
-
getItem: () => null,
|
|
40
|
-
setItem: () => {},
|
|
41
|
-
removeItem: () => {},
|
|
42
|
-
clear: () => {}
|
|
43
|
-
}
|
|
44
|
-
};
|
|
45
|
-
(globalThis as any).window = (global as any).window;
|
|
46
|
-
|
|
47
|
-
// Mock setTimeout for the simulate API call
|
|
48
|
-
const originalSetTimeout = global.setTimeout;
|
|
49
|
-
const mockSetTimeout = (callback: () => void, delay: number) => {
|
|
50
|
-
return originalSetTimeout(callback, 0); // Execute immediately for tests
|
|
51
|
-
};
|
|
52
|
-
(global as any).setTimeout = mockSetTimeout;
|
|
53
|
-
(globalThis as any).setTimeout = mockSetTimeout;
|
|
54
|
-
|
|
55
|
-
// NOW import the component (after mocks are set up)
|
|
56
|
-
import { ForgotPasswordPage } from './ForgotPasswordPage';
|
|
57
|
-
import type { VNode } from 'elit/types';
|
|
58
|
-
|
|
59
|
-
// Helper function to render VNode to HTML string
|
|
60
|
-
function renderToString(vNode: VNode | string | number | undefined | null): string {
|
|
61
|
-
if (vNode == null || vNode === false) return '';
|
|
62
|
-
if (typeof vNode !== 'object') return String(vNode);
|
|
63
|
-
|
|
64
|
-
const { tagName, props, children } = vNode;
|
|
65
|
-
const attrs = props ? Object.entries(props)
|
|
66
|
-
.filter(([k, v]) => v != null && v !== false && k !== 'children' && k !== 'ref' && !k.startsWith('on'))
|
|
67
|
-
.map(([k, v]) => {
|
|
68
|
-
if (k === 'className' || k === 'class') return `class="${Array.isArray(v) ? v.join(' ') : v}"`;
|
|
69
|
-
if (k === 'style') return `style="${typeof v === 'string' ? v : Object.entries(v).map(([sk, sv]) => `${sk.replace(/([A-Z])/g, '-$1').toLowerCase()}:${sv}`).join(';')}"`;
|
|
70
|
-
if (v === true) return k;
|
|
71
|
-
return `${k}="${v}"`;
|
|
72
|
-
})
|
|
73
|
-
.join(' ') : '';
|
|
74
|
-
|
|
75
|
-
const childrenStr = children && children.length > 0
|
|
76
|
-
? children.map(c => renderToString(c as any)).join('')
|
|
77
|
-
: '';
|
|
78
|
-
|
|
79
|
-
return `<${tagName}${attrs ? ' ' + attrs : ''}>${childrenStr}</${tagName}>`;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
// Helper function to find child by tag name
|
|
83
|
-
function findChildByTagName(vNode: VNode, tagName: string): VNode | null {
|
|
84
|
-
if (vNode && typeof vNode === 'object' && 'tagName' in vNode) {
|
|
85
|
-
if (vNode.tagName === tagName) {
|
|
86
|
-
return vNode;
|
|
87
|
-
}
|
|
88
|
-
if (vNode.children) {
|
|
89
|
-
for (const child of vNode.children) {
|
|
90
|
-
if (typeof child === 'object' && child !== null) {
|
|
91
|
-
const found = findChildByTagName(child as VNode, tagName);
|
|
92
|
-
if (found) return found;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Helper function to find children by tag name
|
|
101
|
-
function findChildrenByTagName(vNode: VNode, tagName: string): VNode[] {
|
|
102
|
-
const results: VNode[] = [];
|
|
103
|
-
|
|
104
|
-
function search(node: VNode | string | number | null | undefined) {
|
|
105
|
-
if (node && typeof node === 'object' && 'tagName' in node) {
|
|
106
|
-
if (node.tagName === tagName) {
|
|
107
|
-
results.push(node);
|
|
108
|
-
}
|
|
109
|
-
if (node.children) {
|
|
110
|
-
for (const child of node.children) {
|
|
111
|
-
search(child as any);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
search(vNode);
|
|
118
|
-
return results;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
describe('ForgotPasswordPage Component', () => {
|
|
122
|
-
beforeEach(() => {
|
|
123
|
-
// Reset mock router
|
|
124
|
-
(mockRouter.push as any).mockClear();
|
|
125
|
-
(mockRouter.replace as any).mockClear();
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
describe('page structure', () => {
|
|
129
|
-
it('should render auth-page', () => {
|
|
130
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
131
|
-
|
|
132
|
-
expect(page).toBeDefined();
|
|
133
|
-
expect(page.tagName).toBe('div');
|
|
134
|
-
expect(page.props?.className).toBe('auth-page');
|
|
135
|
-
});
|
|
136
|
-
|
|
137
|
-
it('should render auth-container', () => {
|
|
138
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
139
|
-
const html = renderToString(page);
|
|
140
|
-
|
|
141
|
-
expect(html).toContain('auth-container');
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
it('should render auth-form-wrapper', () => {
|
|
145
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
146
|
-
const html = renderToString(page);
|
|
147
|
-
|
|
148
|
-
expect(html).toContain('auth-form-wrapper');
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
it('should render auth-form-card', () => {
|
|
152
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
153
|
-
const html = renderToString(page);
|
|
154
|
-
|
|
155
|
-
expect(html).toContain('auth-form-card');
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
it('should render auth-header', () => {
|
|
159
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
160
|
-
const html = renderToString(page);
|
|
161
|
-
|
|
162
|
-
expect(html).toContain('auth-header');
|
|
163
|
-
});
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
describe('page content', () => {
|
|
167
|
-
it('should render page title', () => {
|
|
168
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
169
|
-
const html = renderToString(page);
|
|
170
|
-
|
|
171
|
-
expect(html).toContain('Forgot Password?');
|
|
172
|
-
});
|
|
173
|
-
|
|
174
|
-
it('should render page subtitle', () => {
|
|
175
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
176
|
-
const html = renderToString(page);
|
|
177
|
-
|
|
178
|
-
expect(html).toContain("Enter your email address");
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
it('should render back button', () => {
|
|
182
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
183
|
-
const html = renderToString(page);
|
|
184
|
-
|
|
185
|
-
expect(html).toContain('←');
|
|
186
|
-
expect(html).toContain('back-button');
|
|
187
|
-
});
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
describe('form elements', () => {
|
|
191
|
-
it('should render form element', () => {
|
|
192
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
193
|
-
const html = renderToString(page);
|
|
194
|
-
|
|
195
|
-
expect(html).toContain('<form');
|
|
196
|
-
});
|
|
197
|
-
|
|
198
|
-
it('should render email input', () => {
|
|
199
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
200
|
-
const html = renderToString(page);
|
|
201
|
-
|
|
202
|
-
expect(html).toContain('type="email"');
|
|
203
|
-
expect(html).toContain('id="email"');
|
|
204
|
-
expect(html).toContain('form-input');
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
it('should render email label', () => {
|
|
208
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
209
|
-
const html = renderToString(page);
|
|
210
|
-
|
|
211
|
-
expect(html).toContain('Email Address');
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
it('should render submit button', () => {
|
|
215
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
216
|
-
const html = renderToString(page);
|
|
217
|
-
|
|
218
|
-
expect(html).toContain('Send Reset Link');
|
|
219
|
-
expect(html).toContain('btn-primary');
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
it('should have correct placeholder text', () => {
|
|
223
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
224
|
-
const html = renderToString(page);
|
|
225
|
-
|
|
226
|
-
expect(html).toContain('your@email.com');
|
|
227
|
-
});
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
describe('form structure', () => {
|
|
231
|
-
it('should have form-group', () => {
|
|
232
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
233
|
-
const html = renderToString(page);
|
|
234
|
-
|
|
235
|
-
expect(html).toContain('form-group');
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
it('should have input-wrapper', () => {
|
|
239
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
240
|
-
const html = renderToString(page);
|
|
241
|
-
|
|
242
|
-
expect(html).toContain('input-wrapper');
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
it('should have input-icon', () => {
|
|
246
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
247
|
-
const html = renderToString(page);
|
|
248
|
-
|
|
249
|
-
expect(html).toContain('input-icon');
|
|
250
|
-
});
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
describe('error handling', () => {
|
|
254
|
-
it('should have error state', () => {
|
|
255
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
256
|
-
expect(page).toBeDefined();
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
it('should have error state capability', () => {
|
|
260
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
261
|
-
// The component has reactive error state capability
|
|
262
|
-
expect(page).toBeDefined();
|
|
263
|
-
});
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
describe('success state', () => {
|
|
267
|
-
it('should have success state', () => {
|
|
268
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
269
|
-
expect(page).toBeDefined();
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
it('should have success state capability', () => {
|
|
273
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
274
|
-
// The component has reactive success state capability
|
|
275
|
-
expect(page).toBeDefined();
|
|
276
|
-
});
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
describe('navigation', () => {
|
|
280
|
-
it('should have back button to login', () => {
|
|
281
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
282
|
-
const html = renderToString(page);
|
|
283
|
-
|
|
284
|
-
expect(html).toContain('←');
|
|
285
|
-
expect(html).toContain('back-button');
|
|
286
|
-
});
|
|
287
|
-
|
|
288
|
-
it('should have sign in link in footer', () => {
|
|
289
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
290
|
-
const html = renderToString(page);
|
|
291
|
-
|
|
292
|
-
expect(html).toContain('Remember your password?');
|
|
293
|
-
expect(html).toContain('Sign in');
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
it('should have back to login button', () => {
|
|
297
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
298
|
-
const html = renderToString(page);
|
|
299
|
-
|
|
300
|
-
// The success message contains "Back to Login" button
|
|
301
|
-
expect(html).toBeDefined();
|
|
302
|
-
});
|
|
303
|
-
});
|
|
304
|
-
|
|
305
|
-
describe('CSS classes', () => {
|
|
306
|
-
it('should have correct CSS classes', () => {
|
|
307
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
308
|
-
const html = renderToString(page);
|
|
309
|
-
|
|
310
|
-
expect(html).toContain('auth-page');
|
|
311
|
-
expect(html).toContain('auth-container');
|
|
312
|
-
expect(html).toContain('auth-container-single');
|
|
313
|
-
expect(html).toContain('auth-form-wrapper');
|
|
314
|
-
expect(html).toContain('auth-form-wrapper-full');
|
|
315
|
-
expect(html).toContain('auth-form-card');
|
|
316
|
-
expect(html).toContain('auth-header');
|
|
317
|
-
expect(html).toContain('auth-title');
|
|
318
|
-
expect(html).toContain('auth-subtitle');
|
|
319
|
-
});
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
describe('loading state', () => {
|
|
323
|
-
it('should have loading state', () => {
|
|
324
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
325
|
-
expect(page).toBeDefined();
|
|
326
|
-
});
|
|
327
|
-
|
|
328
|
-
it('should show loading text when loading', async () => {
|
|
329
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
330
|
-
|
|
331
|
-
// The isLoading state is reactive
|
|
332
|
-
expect(page).toBeDefined();
|
|
333
|
-
});
|
|
334
|
-
});
|
|
335
|
-
|
|
336
|
-
describe('success message content', () => {
|
|
337
|
-
it('should have success message capability', () => {
|
|
338
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
339
|
-
// Success message is conditionally rendered based on reactive state
|
|
340
|
-
expect(page).toBeDefined();
|
|
341
|
-
});
|
|
342
|
-
|
|
343
|
-
it('should have success title capability', () => {
|
|
344
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
345
|
-
// Success message is conditionally rendered
|
|
346
|
-
expect(page).toBeDefined();
|
|
347
|
-
});
|
|
348
|
-
|
|
349
|
-
it('should have success text capability', () => {
|
|
350
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
351
|
-
// Success message is conditionally rendered
|
|
352
|
-
expect(page).toBeDefined();
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
it('should have success description capability', () => {
|
|
356
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
357
|
-
// Success message is conditionally rendered
|
|
358
|
-
expect(page).toBeDefined();
|
|
359
|
-
});
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
describe('component consistency', () => {
|
|
363
|
-
it('should always return the same structure', () => {
|
|
364
|
-
const page1 = ForgotPasswordPage(mockRouter as any);
|
|
365
|
-
const page2 = ForgotPasswordPage(mockRouter as any);
|
|
366
|
-
|
|
367
|
-
expect(page1.tagName).toBe(page2.tagName);
|
|
368
|
-
expect(page1.props?.className).toBe(page2.props?.className);
|
|
369
|
-
});
|
|
370
|
-
|
|
371
|
-
it('should render without errors', () => {
|
|
372
|
-
expect(() => {
|
|
373
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
374
|
-
renderToString(page);
|
|
375
|
-
}).not.toThrow();
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
it('should have h2 element', () => {
|
|
379
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
380
|
-
const h2Elements = findChildrenByTagName(page, 'h2');
|
|
381
|
-
|
|
382
|
-
expect(h2Elements.length).toBeGreaterThan(0);
|
|
383
|
-
});
|
|
384
|
-
|
|
385
|
-
it('should have h3 element in success message capability', () => {
|
|
386
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
387
|
-
// Success message is conditionally rendered
|
|
388
|
-
expect(page).toBeDefined();
|
|
389
|
-
});
|
|
390
|
-
});
|
|
391
|
-
|
|
392
|
-
describe('form validation', () => {
|
|
393
|
-
it('should validate email is required', () => {
|
|
394
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
395
|
-
const html = renderToString(page);
|
|
396
|
-
|
|
397
|
-
// Form should be rendered
|
|
398
|
-
expect(html).toContain('<form');
|
|
399
|
-
});
|
|
400
|
-
|
|
401
|
-
it('should validate email format', () => {
|
|
402
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
403
|
-
const html = renderToString(page);
|
|
404
|
-
|
|
405
|
-
// Email input should be present
|
|
406
|
-
expect(html).toContain('type="email"');
|
|
407
|
-
});
|
|
408
|
-
});
|
|
409
|
-
|
|
410
|
-
describe('input attributes', () => {
|
|
411
|
-
it('should have correct input attributes', () => {
|
|
412
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
413
|
-
const html = renderToString(page);
|
|
414
|
-
|
|
415
|
-
expect(html).toContain('placeholder=');
|
|
416
|
-
expect(html).toContain('your@email.com');
|
|
417
|
-
expect(html).toContain('type="email"');
|
|
418
|
-
});
|
|
419
|
-
|
|
420
|
-
it('should have input icon', () => {
|
|
421
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
422
|
-
const html = renderToString(page);
|
|
423
|
-
|
|
424
|
-
expect(html).toContain('input-icon');
|
|
425
|
-
expect(html).toContain('📧');
|
|
426
|
-
});
|
|
427
|
-
});
|
|
428
|
-
|
|
429
|
-
describe('footer links', () => {
|
|
430
|
-
it('should render auth-footer', () => {
|
|
431
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
432
|
-
const html = renderToString(page);
|
|
433
|
-
|
|
434
|
-
expect(html).toContain('auth-footer');
|
|
435
|
-
});
|
|
436
|
-
|
|
437
|
-
it('should render footer text', () => {
|
|
438
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
439
|
-
const html = renderToString(page);
|
|
440
|
-
|
|
441
|
-
expect(html).toContain('Remember your password?');
|
|
442
|
-
});
|
|
443
|
-
});
|
|
444
|
-
|
|
445
|
-
describe('button states', () => {
|
|
446
|
-
it('should have disabled state for submit button', () => {
|
|
447
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
448
|
-
const html = renderToString(page);
|
|
449
|
-
|
|
450
|
-
// Check if disabled attribute is handled
|
|
451
|
-
expect(html).toContain('Send Reset Link');
|
|
452
|
-
});
|
|
453
|
-
|
|
454
|
-
it('should show loading state on button', () => {
|
|
455
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
456
|
-
const html = renderToString(page);
|
|
457
|
-
|
|
458
|
-
// Button should be present
|
|
459
|
-
expect(html).toContain('btn-primary');
|
|
460
|
-
});
|
|
461
|
-
});
|
|
462
|
-
|
|
463
|
-
describe('component lifecycle', () => {
|
|
464
|
-
it('should initialize with empty email', () => {
|
|
465
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
466
|
-
expect(page).toBeDefined();
|
|
467
|
-
});
|
|
468
|
-
|
|
469
|
-
it('should initialize with no error', () => {
|
|
470
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
471
|
-
expect(page).toBeDefined();
|
|
472
|
-
});
|
|
473
|
-
|
|
474
|
-
it('should initialize with success false', () => {
|
|
475
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
476
|
-
expect(page).toBeDefined();
|
|
477
|
-
});
|
|
478
|
-
|
|
479
|
-
it('should initialize with loading false', () => {
|
|
480
|
-
const page = ForgotPasswordPage(mockRouter as any);
|
|
481
|
-
expect(page).toBeDefined();
|
|
482
|
-
});
|
|
483
|
-
});
|
|
484
|
-
});
|