@sneat/auth-ui 0.1.3 → 0.1.6
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/esm2022/index.js +4 -0
- package/esm2022/index.js.map +1 -0
- package/esm2022/lib/components/auth-menu-item/auth-menu-item.component.js +82 -0
- package/esm2022/lib/components/auth-menu-item/auth-menu-item.component.js.map +1 -0
- package/esm2022/lib/components/index.js +4 -0
- package/esm2022/lib/components/index.js.map +1 -0
- package/esm2022/lib/components/user-auth-providers/user-auth-accounts.component.js +83 -0
- package/esm2022/lib/components/user-auth-providers/user-auth-accounts.component.js.map +1 -0
- package/esm2022/lib/components/user-auth-providers/user-auth-provider-status.js +118 -0
- package/esm2022/lib/components/user-auth-providers/user-auth-provider-status.js.map +1 -0
- package/esm2022/lib/components/user-required-fields/index.js +3 -0
- package/esm2022/lib/components/user-required-fields/index.js.map +1 -0
- package/esm2022/lib/components/user-required-fields/user-required-fields-modal.component.js +111 -0
- package/esm2022/lib/components/user-required-fields/user-required-fields-modal.component.js.map +1 -0
- package/esm2022/lib/components/user-required-fields/user-required-fields.service.js +29 -0
- package/esm2022/lib/components/user-required-fields/user-required-fields.service.js.map +1 -0
- package/esm2022/lib/pages/login-page/email-login-form/email-login-form.component.js +263 -0
- package/esm2022/lib/pages/login-page/email-login-form/email-login-form.component.js.map +1 -0
- package/esm2022/lib/pages/login-page/login-page.component.js +143 -0
- package/esm2022/lib/pages/login-page/login-page.component.js.map +1 -0
- package/esm2022/lib/pages/login-page/login-with-telegram.component.js +93 -0
- package/esm2022/lib/pages/login-page/login-with-telegram.component.js.map +1 -0
- package/esm2022/lib/pages/login-page/sneat-auth-with-telegram.service.js +31 -0
- package/esm2022/lib/pages/login-page/sneat-auth-with-telegram.service.js.map +1 -0
- package/esm2022/lib/pages/sign-in-from-email-link/sign-in-from-email-link-page.component.js +52 -0
- package/esm2022/lib/pages/sign-in-from-email-link/sign-in-from-email-link-page.component.js.map +1 -0
- package/esm2022/lib/pages/sneat-auth-routing.module.js +27 -0
- package/esm2022/lib/pages/sneat-auth-routing.module.js.map +1 -0
- package/esm2022/lib/pipes/person-names.pipe.js +35 -0
- package/esm2022/lib/pipes/person-names.pipe.js.map +1 -0
- package/esm2022/sneat-auth-ui.js +5 -0
- package/esm2022/sneat-auth-ui.js.map +1 -0
- package/lib/components/auth-menu-item/auth-menu-item.component.d.ts +24 -0
- package/lib/components/user-auth-providers/user-auth-accounts.component.d.ts +17 -0
- package/lib/components/user-auth-providers/user-auth-provider-status.d.ts +31 -0
- package/lib/components/user-required-fields/user-required-fields-modal.component.d.ts +31 -0
- package/lib/components/user-required-fields/user-required-fields.service.d.ts +7 -0
- package/lib/pages/login-page/email-login-form/email-login-form.component.d.ts +51 -0
- package/lib/pages/login-page/login-page.component.d.ts +30 -0
- package/lib/pages/login-page/login-with-telegram.component.d.ts +17 -0
- package/lib/pages/login-page/sneat-auth-with-telegram.service.d.ts +18 -0
- package/lib/pages/sign-in-from-email-link/sign-in-from-email-link-page.component.d.ts +13 -0
- package/lib/pages/sneat-auth-routing.module.d.ts +9 -0
- package/lib/pipes/person-names.pipe.d.ts +9 -0
- package/package.json +14 -2
- package/sneat-auth-ui.d.ts +5 -0
- package/tsconfig.lib.prod.tsbuildinfo +1 -0
- package/eslint.config.cjs +0 -7
- package/ng-package.json +0 -7
- package/project.json +0 -38
- package/src/lib/components/auth-menu-item/auth-menu-item.component.html +0 -59
- package/src/lib/components/auth-menu-item/auth-menu-item.component.spec.ts +0 -5
- package/src/lib/components/auth-menu-item/auth-menu-item.component.ts +0 -116
- package/src/lib/components/user-auth-providers/user-auth-accounts.component.html +0 -127
- package/src/lib/components/user-auth-providers/user-auth-accounts.component.spec.ts +0 -47
- package/src/lib/components/user-auth-providers/user-auth-accounts.component.ts +0 -109
- package/src/lib/components/user-auth-providers/user-auth-provider-status.html +0 -42
- package/src/lib/components/user-auth-providers/user-auth-provider-status.ts +0 -172
- package/src/lib/components/user-required-fields/user-required-fields-modal.component.html +0 -64
- package/src/lib/components/user-required-fields/user-required-fields-modal.component.spec.ts +0 -45
- package/src/lib/components/user-required-fields/user-required-fields-modal.component.ts +0 -141
- package/src/lib/components/user-required-fields/user-required-fields.service.spec.ts +0 -335
- package/src/lib/components/user-required-fields/user-required-fields.service.ts +0 -23
- package/src/lib/pages/login-page/email-login-form/email-login-form.component.html +0 -165
- package/src/lib/pages/login-page/email-login-form/email-login-form.component.spec.ts +0 -59
- package/src/lib/pages/login-page/email-login-form/email-login-form.component.ts +0 -356
- package/src/lib/pages/login-page/index.ts +0 -3
- package/src/lib/pages/login-page/login-page.component.html +0 -146
- package/src/lib/pages/login-page/login-page.component.spec.ts +0 -5
- package/src/lib/pages/login-page/login-page.component.ts +0 -209
- package/src/lib/pages/login-page/login-with-telegram.component.spec.ts +0 -42
- package/src/lib/pages/login-page/login-with-telegram.component.ts +0 -82
- package/src/lib/pages/login-page/sneat-auth-with-telegram.service.spec.ts +0 -31
- package/src/lib/pages/login-page/sneat-auth-with-telegram.service.ts +0 -56
- package/src/lib/pages/sign-in-from-email-link/sign-in-from-email-link-page.component.html +0 -35
- package/src/lib/pages/sign-in-from-email-link/sign-in-from-email-link-page.component.spec.ts +0 -43
- package/src/lib/pages/sign-in-from-email-link/sign-in-from-email-link-page.component.ts +0 -70
- package/src/lib/pages/sneat-auth-routing.module.ts +0 -25
- package/src/lib/pipes/person-names.pipe.spec.ts +0 -317
- package/src/lib/pipes/person-names.pipe.ts +0 -31
- package/src/test-setup.ts +0 -3
- package/tsconfig.json +0 -13
- package/tsconfig.lib.json +0 -19
- package/tsconfig.lib.prod.json +0 -7
- package/tsconfig.spec.json +0 -31
- package/vite.config.mts +0 -10
- /package/{src/index.ts → index.d.ts} +0 -0
- /package/{src/lib/components/index.ts → lib/components/index.d.ts} +0 -0
- /package/{src/lib/components/user-required-fields/index.ts → lib/components/user-required-fields/index.d.ts} +0 -0
|
@@ -1,335 +0,0 @@
|
|
|
1
|
-
import { TestBed } from '@angular/core/testing';
|
|
2
|
-
import { ModalController } from '@ionic/angular/standalone';
|
|
3
|
-
import { UserRequiredFieldsService } from './user-required-fields.service';
|
|
4
|
-
import { UserRequiredFieldsModalComponent } from './user-required-fields-modal.component';
|
|
5
|
-
|
|
6
|
-
describe('UserRequiredFieldsService', () => {
|
|
7
|
-
let service: UserRequiredFieldsService;
|
|
8
|
-
let modalController: ModalController;
|
|
9
|
-
let mockModal: {
|
|
10
|
-
present: ReturnType<typeof vi.fn>;
|
|
11
|
-
onDidDismiss: ReturnType<typeof vi.fn>;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
// Create a mock modal object
|
|
16
|
-
mockModal = {
|
|
17
|
-
present: vi.fn().mockResolvedValue(undefined),
|
|
18
|
-
onDidDismiss: vi.fn(),
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
TestBed.configureTestingModule({
|
|
22
|
-
providers: [
|
|
23
|
-
UserRequiredFieldsService,
|
|
24
|
-
{
|
|
25
|
-
provide: ModalController,
|
|
26
|
-
useValue: {
|
|
27
|
-
create: vi.fn().mockResolvedValue(mockModal),
|
|
28
|
-
},
|
|
29
|
-
},
|
|
30
|
-
],
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
service = TestBed.inject(UserRequiredFieldsService);
|
|
34
|
-
modalController = TestBed.inject(ModalController);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('should be created', () => {
|
|
38
|
-
expect(service).toBeTruthy();
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
describe('open', () => {
|
|
42
|
-
it('should create a modal with UserRequiredFieldsModalComponent', async () => {
|
|
43
|
-
// Arrange
|
|
44
|
-
mockModal.onDidDismiss.mockResolvedValue({ data: true });
|
|
45
|
-
|
|
46
|
-
// Act
|
|
47
|
-
const resultPromise = service.open();
|
|
48
|
-
|
|
49
|
-
// Assert
|
|
50
|
-
expect(modalController.create).toHaveBeenCalledWith({
|
|
51
|
-
component: UserRequiredFieldsModalComponent,
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
await resultPromise;
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
it('should present the modal after creation', async () => {
|
|
58
|
-
// Arrange
|
|
59
|
-
mockModal.onDidDismiss.mockResolvedValue({ data: true });
|
|
60
|
-
|
|
61
|
-
// Act
|
|
62
|
-
await service.open();
|
|
63
|
-
|
|
64
|
-
// Assert
|
|
65
|
-
expect(mockModal.present).toHaveBeenCalledTimes(1);
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
it('should return a Promise that resolves when modal is dismissed', async () => {
|
|
69
|
-
// Arrange
|
|
70
|
-
mockModal.onDidDismiss.mockResolvedValue({ data: true });
|
|
71
|
-
|
|
72
|
-
// Act
|
|
73
|
-
const resultPromise = service.open();
|
|
74
|
-
|
|
75
|
-
// Assert - Just verify we can await it and it returns the expected value
|
|
76
|
-
const result = await resultPromise;
|
|
77
|
-
expect(result).toBe(true);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('should resolve to true when dismissal value is truthy', async () => {
|
|
81
|
-
// Arrange
|
|
82
|
-
mockModal.onDidDismiss.mockResolvedValue({ data: 'some value' });
|
|
83
|
-
|
|
84
|
-
// Act
|
|
85
|
-
const result = await service.open();
|
|
86
|
-
|
|
87
|
-
// Assert
|
|
88
|
-
expect(result).toBe(true);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it('should resolve to true when dismissal value.data is an object', async () => {
|
|
92
|
-
// Arrange
|
|
93
|
-
mockModal.onDidDismiss.mockResolvedValue({ data: { key: 'value' } });
|
|
94
|
-
|
|
95
|
-
// Act
|
|
96
|
-
const result = await service.open();
|
|
97
|
-
|
|
98
|
-
// Assert
|
|
99
|
-
expect(result).toBe(true);
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('should resolve to true when dismissal value.data is a non-empty string', async () => {
|
|
103
|
-
// Arrange
|
|
104
|
-
mockModal.onDidDismiss.mockResolvedValue({ data: 'success' });
|
|
105
|
-
|
|
106
|
-
// Act
|
|
107
|
-
const result = await service.open();
|
|
108
|
-
|
|
109
|
-
// Assert
|
|
110
|
-
expect(result).toBe(true);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it('should resolve to true when dismissal value.data is a number', async () => {
|
|
114
|
-
// Arrange
|
|
115
|
-
mockModal.onDidDismiss.mockResolvedValue({ data: 1 });
|
|
116
|
-
|
|
117
|
-
// Act
|
|
118
|
-
const result = await service.open();
|
|
119
|
-
|
|
120
|
-
// Assert
|
|
121
|
-
expect(result).toBe(true);
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
it('should resolve to false when dismissal value is undefined', async () => {
|
|
125
|
-
// Arrange
|
|
126
|
-
mockModal.onDidDismiss.mockResolvedValue(undefined);
|
|
127
|
-
|
|
128
|
-
// Act
|
|
129
|
-
const result = await service.open();
|
|
130
|
-
|
|
131
|
-
// Assert
|
|
132
|
-
expect(result).toBe(false);
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
it('should resolve to false when dismissal value.data is null (object is still truthy)', async () => {
|
|
136
|
-
// Arrange
|
|
137
|
-
mockModal.onDidDismiss.mockResolvedValue({ data: null });
|
|
138
|
-
|
|
139
|
-
// Act
|
|
140
|
-
const result = await service.open();
|
|
141
|
-
|
|
142
|
-
// Assert - Object with data:null is still a truthy object
|
|
143
|
-
expect(result).toBe(true);
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
it('should resolve to false when dismissal value.data is false (object is still truthy)', async () => {
|
|
147
|
-
// Arrange
|
|
148
|
-
mockModal.onDidDismiss.mockResolvedValue({ data: false });
|
|
149
|
-
|
|
150
|
-
// Act
|
|
151
|
-
const result = await service.open();
|
|
152
|
-
|
|
153
|
-
// Assert - Object with data:false is still a truthy object
|
|
154
|
-
expect(result).toBe(true);
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
it('should resolve to false when dismissal value.data is an empty string (object is still truthy)', async () => {
|
|
158
|
-
// Arrange
|
|
159
|
-
mockModal.onDidDismiss.mockResolvedValue({ data: '' });
|
|
160
|
-
|
|
161
|
-
// Act
|
|
162
|
-
const result = await service.open();
|
|
163
|
-
|
|
164
|
-
// Assert - Object with data:'' is still a truthy object
|
|
165
|
-
expect(result).toBe(true);
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
it('should resolve to false when dismissal value.data is zero (object is still truthy)', async () => {
|
|
169
|
-
// Arrange
|
|
170
|
-
mockModal.onDidDismiss.mockResolvedValue({ data: 0 });
|
|
171
|
-
|
|
172
|
-
// Act
|
|
173
|
-
const result = await service.open();
|
|
174
|
-
|
|
175
|
-
// Assert - Object with data:0 is still a truthy object
|
|
176
|
-
expect(result).toBe(true);
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
it('should reject the Promise when modal dismissal fails', async () => {
|
|
180
|
-
// Arrange
|
|
181
|
-
const dismissError = new Error('Modal dismissal failed');
|
|
182
|
-
mockModal.onDidDismiss.mockRejectedValue(dismissError);
|
|
183
|
-
|
|
184
|
-
// Act & Assert
|
|
185
|
-
await expect(service.open()).rejects.toThrow('Modal dismissal failed');
|
|
186
|
-
});
|
|
187
|
-
|
|
188
|
-
it('should reject the Promise when onDidDismiss throws an error', async () => {
|
|
189
|
-
// Arrange
|
|
190
|
-
const error = new Error('Unexpected error');
|
|
191
|
-
mockModal.onDidDismiss.mockRejectedValue(error);
|
|
192
|
-
|
|
193
|
-
// Act & Assert
|
|
194
|
-
await expect(service.open()).rejects.toThrow(error);
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
it('should resolve when modal is dismissed', async () => {
|
|
198
|
-
// Arrange
|
|
199
|
-
const dismissalValue = { data: 'test-value' };
|
|
200
|
-
mockModal.onDidDismiss.mockResolvedValue(dismissalValue);
|
|
201
|
-
|
|
202
|
-
// Act
|
|
203
|
-
const result = await service.open();
|
|
204
|
-
|
|
205
|
-
// Assert
|
|
206
|
-
expect(result).toBe(true);
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
it('should handle multiple sequential open calls independently', async () => {
|
|
210
|
-
// Arrange
|
|
211
|
-
const mockModal1 = {
|
|
212
|
-
present: vi.fn().mockResolvedValue(undefined),
|
|
213
|
-
onDidDismiss: vi.fn().mockResolvedValue({ data: true }),
|
|
214
|
-
};
|
|
215
|
-
const mockModal2 = {
|
|
216
|
-
present: vi.fn().mockResolvedValue(undefined),
|
|
217
|
-
onDidDismiss: vi.fn().mockResolvedValue(null), // null is falsy
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
(modalController.create as ReturnType<typeof vi.fn>)
|
|
221
|
-
.mockResolvedValueOnce(mockModal1)
|
|
222
|
-
.mockResolvedValueOnce(mockModal2);
|
|
223
|
-
|
|
224
|
-
// Act
|
|
225
|
-
const result1 = await service.open();
|
|
226
|
-
const result2 = await service.open();
|
|
227
|
-
|
|
228
|
-
// Assert
|
|
229
|
-
expect(result1).toBe(true); // { data: true } is truthy
|
|
230
|
-
expect(result2).toBe(false); // null is falsy
|
|
231
|
-
expect(modalController.create).toHaveBeenCalledTimes(2);
|
|
232
|
-
expect(mockModal1.present).toHaveBeenCalledTimes(1);
|
|
233
|
-
expect(mockModal2.present).toHaveBeenCalledTimes(1);
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
it('should call onDidDismiss after present completes', async () => {
|
|
237
|
-
// Arrange
|
|
238
|
-
const callOrder: string[] = [];
|
|
239
|
-
mockModal.present.mockImplementation(() => {
|
|
240
|
-
callOrder.push('present');
|
|
241
|
-
return Promise.resolve();
|
|
242
|
-
});
|
|
243
|
-
mockModal.onDidDismiss.mockImplementation(() => {
|
|
244
|
-
callOrder.push('onDidDismiss');
|
|
245
|
-
return Promise.resolve({ data: true });
|
|
246
|
-
});
|
|
247
|
-
|
|
248
|
-
// Act
|
|
249
|
-
await service.open();
|
|
250
|
-
|
|
251
|
-
// Assert
|
|
252
|
-
expect(callOrder).toEqual(['present', 'onDidDismiss']);
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
it('should handle dismissal with role property', async () => {
|
|
256
|
-
// Arrange
|
|
257
|
-
mockModal.onDidDismiss.mockResolvedValue({
|
|
258
|
-
data: { success: true },
|
|
259
|
-
role: 'confirm',
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
// Act
|
|
263
|
-
const result = await service.open();
|
|
264
|
-
|
|
265
|
-
// Assert
|
|
266
|
-
expect(result).toBe(true);
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
it('should handle empty object as dismissal value', async () => {
|
|
270
|
-
// Arrange
|
|
271
|
-
mockModal.onDidDismiss.mockResolvedValue({});
|
|
272
|
-
|
|
273
|
-
// Act
|
|
274
|
-
const result = await service.open();
|
|
275
|
-
|
|
276
|
-
// Assert
|
|
277
|
-
expect(result).toBe(true); // Empty object is truthy
|
|
278
|
-
});
|
|
279
|
-
|
|
280
|
-
describe('edge cases', () => {
|
|
281
|
-
it('should handle modal creation failure', async () => {
|
|
282
|
-
// Arrange
|
|
283
|
-
const createError = new Error('Failed to create modal');
|
|
284
|
-
(modalController.create as ReturnType<typeof vi.fn>).mockRejectedValue(
|
|
285
|
-
createError,
|
|
286
|
-
);
|
|
287
|
-
|
|
288
|
-
// Act & Assert
|
|
289
|
-
await expect(service.open()).rejects.toThrow('Failed to create modal');
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
it('should handle modal present failure', async () => {
|
|
293
|
-
// Arrange
|
|
294
|
-
const presentError = new Error('Failed to present modal');
|
|
295
|
-
mockModal.present.mockRejectedValue(presentError);
|
|
296
|
-
|
|
297
|
-
// Act & Assert
|
|
298
|
-
await expect(service.open()).rejects.toThrow('Failed to present modal');
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
it('should handle dismissal value with data property as array', async () => {
|
|
302
|
-
// Arrange
|
|
303
|
-
mockModal.onDidDismiss.mockResolvedValue({ data: [1, 2, 3] });
|
|
304
|
-
|
|
305
|
-
// Act
|
|
306
|
-
const result = await service.open();
|
|
307
|
-
|
|
308
|
-
// Assert
|
|
309
|
-
expect(result).toBe(true);
|
|
310
|
-
});
|
|
311
|
-
|
|
312
|
-
it('should handle dismissal value with data property as empty array', async () => {
|
|
313
|
-
// Arrange
|
|
314
|
-
mockModal.onDidDismiss.mockResolvedValue({ data: [] });
|
|
315
|
-
|
|
316
|
-
// Act
|
|
317
|
-
const result = await service.open();
|
|
318
|
-
|
|
319
|
-
// Assert
|
|
320
|
-
expect(result).toBe(true); // Empty array is truthy
|
|
321
|
-
});
|
|
322
|
-
|
|
323
|
-
it('should handle NaN as dismissal value', async () => {
|
|
324
|
-
// Arrange
|
|
325
|
-
mockModal.onDidDismiss.mockResolvedValue({ data: NaN });
|
|
326
|
-
|
|
327
|
-
// Act
|
|
328
|
-
const result = await service.open();
|
|
329
|
-
|
|
330
|
-
// Assert - Object with data:NaN is still a truthy object (even though NaN itself is falsy)
|
|
331
|
-
expect(result).toBe(true);
|
|
332
|
-
});
|
|
333
|
-
});
|
|
334
|
-
});
|
|
335
|
-
});
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { Injectable, inject } from '@angular/core';
|
|
2
|
-
import { ModalController } from '@ionic/angular/standalone';
|
|
3
|
-
import { UserRequiredFieldsModalComponent } from './user-required-fields-modal.component';
|
|
4
|
-
|
|
5
|
-
@Injectable()
|
|
6
|
-
export class UserRequiredFieldsService {
|
|
7
|
-
private readonly modalController = inject(ModalController);
|
|
8
|
-
|
|
9
|
-
public async open(): Promise<boolean> {
|
|
10
|
-
const modal = await this.modalController.create({
|
|
11
|
-
component: UserRequiredFieldsModalComponent,
|
|
12
|
-
});
|
|
13
|
-
await modal.present();
|
|
14
|
-
return new Promise((resolve, reject) => {
|
|
15
|
-
modal
|
|
16
|
-
.onDidDismiss()
|
|
17
|
-
.then((value) => {
|
|
18
|
-
resolve(!!value);
|
|
19
|
-
})
|
|
20
|
-
.catch(reject);
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
}
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
<div class="ion-padding-horizontal"></div>
|
|
2
|
-
<ion-card>
|
|
3
|
-
<ion-item-divider color="light" class="ion-no-padding">
|
|
4
|
-
<ion-segment [(ngModel)]="sign" (ionChange)="signChanged()">
|
|
5
|
-
<ion-segment-button value="up">
|
|
6
|
-
<ion-icon name="person-add" class="ion-margin-end"></ion-icon>
|
|
7
|
-
<ion-label>Sign up</ion-label>
|
|
8
|
-
</ion-segment-button>
|
|
9
|
-
<ion-segment-button value="in">
|
|
10
|
-
<ion-icon name="enter-outline" />
|
|
11
|
-
<ion-label>Sign in</ion-label>
|
|
12
|
-
</ion-segment-button>
|
|
13
|
-
</ion-segment>
|
|
14
|
-
</ion-item-divider>
|
|
15
|
-
<!-- <ion-item-divider color="light">-->
|
|
16
|
-
<!-- <ion-label color="medium" style="text-align: center; width: 100%">-->
|
|
17
|
-
<!-- Or login with email-->
|
|
18
|
-
<!-- </ion-label>-->
|
|
19
|
-
<!-- </ion-item-divider>-->
|
|
20
|
-
<ion-card-content class="ion-no-padding">
|
|
21
|
-
<ion-item>
|
|
22
|
-
<ion-label class="ion-margin-end">
|
|
23
|
-
<ion-icon name="mail-outline" />
|
|
24
|
-
</ion-label>
|
|
25
|
-
<ion-input
|
|
26
|
-
[disabled]="!!signingWith"
|
|
27
|
-
[(ngModel)]="email"
|
|
28
|
-
email
|
|
29
|
-
type="email"
|
|
30
|
-
name="email"
|
|
31
|
-
id="email"
|
|
32
|
-
required
|
|
33
|
-
placeholder="my@work-or-personal.email"
|
|
34
|
-
(keyup.enter)="keyupEnter()"
|
|
35
|
-
/>
|
|
36
|
-
</ion-item>
|
|
37
|
-
@switch (sign) {
|
|
38
|
-
@case ("up") {
|
|
39
|
-
<ion-item>
|
|
40
|
-
<ion-label class="ion-margin-end">
|
|
41
|
-
<ion-icon name="person-add-outline" />
|
|
42
|
-
</ion-label>
|
|
43
|
-
<ion-input
|
|
44
|
-
name="first_name"
|
|
45
|
-
placeholder="First name"
|
|
46
|
-
[(ngModel)]="firstName"
|
|
47
|
-
type="text"
|
|
48
|
-
required
|
|
49
|
-
(keyup.enter)="keyupEnter()"
|
|
50
|
-
[disabled]="!!signingWith"
|
|
51
|
-
/>
|
|
52
|
-
<ion-input
|
|
53
|
-
name="last_name"
|
|
54
|
-
placeholder="Last name"
|
|
55
|
-
[(ngModel)]="lastName"
|
|
56
|
-
type="text"
|
|
57
|
-
required
|
|
58
|
-
(keyup.enter)="keyupEnter()"
|
|
59
|
-
[disabled]="!!signingWith"
|
|
60
|
-
/>
|
|
61
|
-
</ion-item>
|
|
62
|
-
@if (appInfo.requiredSpaceType === "company") {
|
|
63
|
-
<ion-item>
|
|
64
|
-
<ion-label position="stacked">Company name</ion-label>
|
|
65
|
-
<ion-input
|
|
66
|
-
#teamTitleInput
|
|
67
|
-
placeholder="required"
|
|
68
|
-
required
|
|
69
|
-
[(ngModel)]="spaceTitle"
|
|
70
|
-
/>
|
|
71
|
-
</ion-item>
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
@case ("in") {
|
|
75
|
-
<ion-item>
|
|
76
|
-
<ion-label class="ion-margin-end">
|
|
77
|
-
<ion-icon name="key-outline" />
|
|
78
|
-
</ion-label>
|
|
79
|
-
<ion-input
|
|
80
|
-
[(ngModel)]="password"
|
|
81
|
-
placeholder="Password"
|
|
82
|
-
type="password"
|
|
83
|
-
required
|
|
84
|
-
(keyup.enter)="keyupEnter()"
|
|
85
|
-
[disabled]="!!signingWith"
|
|
86
|
-
/>
|
|
87
|
-
<ion-buttons slot="end">
|
|
88
|
-
<ion-button
|
|
89
|
-
color="danger"
|
|
90
|
-
[disabled]="!validEmail"
|
|
91
|
-
(click)="resetPassword()"
|
|
92
|
-
title="Send email with a link to reset password "
|
|
93
|
-
>
|
|
94
|
-
<ion-label>Forgot? Reset!</ion-label>
|
|
95
|
-
</ion-button>
|
|
96
|
-
</ion-buttons>
|
|
97
|
-
</ion-item>
|
|
98
|
-
@if (wrongPassword) {
|
|
99
|
-
<ion-item>
|
|
100
|
-
<ion-label color="danger">Wrong password</ion-label>
|
|
101
|
-
</ion-item>
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
</ion-card-content>
|
|
106
|
-
<ion-card-content>
|
|
107
|
-
@switch (sign) {
|
|
108
|
-
@case ("up") {
|
|
109
|
-
<ion-button
|
|
110
|
-
[disabled]="!!signingWith || !validEmail || (!firstName && !lastName)"
|
|
111
|
-
(click)="signUp()"
|
|
112
|
-
>
|
|
113
|
-
<ion-icon name="enter-outline" slot="start" />
|
|
114
|
-
@if (signingWith === "email") {
|
|
115
|
-
<ion-label>Signing up...</ion-label>
|
|
116
|
-
<ion-spinner
|
|
117
|
-
class="ion-margin-start"
|
|
118
|
-
slot="end"
|
|
119
|
-
name="lines-small"
|
|
120
|
-
/>
|
|
121
|
-
} @else {
|
|
122
|
-
<ion-label>Sign up</ion-label>
|
|
123
|
-
}
|
|
124
|
-
</ion-button>
|
|
125
|
-
}
|
|
126
|
-
@case ("in") {
|
|
127
|
-
<ion-button
|
|
128
|
-
[disabled]="!!signingWith || !validEmail || !password"
|
|
129
|
-
(click)="signIn()"
|
|
130
|
-
>
|
|
131
|
-
<ion-icon name="enter-outline" slot="start" />
|
|
132
|
-
@if (signingWith === "email") {
|
|
133
|
-
<ion-label>Signing in...</ion-label>
|
|
134
|
-
<ion-spinner
|
|
135
|
-
class="ion-margin-start"
|
|
136
|
-
slot="end"
|
|
137
|
-
name="lines-small"
|
|
138
|
-
/>
|
|
139
|
-
} @else {
|
|
140
|
-
<ion-label>
|
|
141
|
-
<b>Sign in</b> <ion-text
|
|
142
|
-
color="light"
|
|
143
|
-
style="text-transform: none"
|
|
144
|
-
>with password
|
|
145
|
-
</ion-text>
|
|
146
|
-
</ion-label>
|
|
147
|
-
}
|
|
148
|
-
</ion-button>
|
|
149
|
-
<ion-button disabled="disabled" fill="clear" color="medium">
|
|
150
|
-
or
|
|
151
|
-
</ion-button>
|
|
152
|
-
<ion-button
|
|
153
|
-
size="small"
|
|
154
|
-
[disabled]="!validEmail || signingWith"
|
|
155
|
-
(click)="sendSignInLink()"
|
|
156
|
-
fill="outline"
|
|
157
|
-
color="tertiary"
|
|
158
|
-
>
|
|
159
|
-
<ion-icon name="mail-outline" slot="start" />
|
|
160
|
-
<ion-label>Get sign-in link</ion-label>
|
|
161
|
-
</ion-button>
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
</ion-card-content>
|
|
165
|
-
</ion-card>
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
|
2
|
-
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
|
3
|
-
import { Auth } from '@angular/fire/auth';
|
|
4
|
-
import { ToastController } from '@ionic/angular/standalone';
|
|
5
|
-
import { SneatApiService } from '@sneat/api';
|
|
6
|
-
import { UserRecordService } from '@sneat/auth-core';
|
|
7
|
-
import { AnalyticsService, APP_INFO, ErrorLogger } from '@sneat/core';
|
|
8
|
-
import { RandomIdService } from '@sneat/random';
|
|
9
|
-
import { EmailLoginFormComponent } from './email-login-form.component';
|
|
10
|
-
|
|
11
|
-
describe('EmailLoginFormComponent', () => {
|
|
12
|
-
let component: EmailLoginFormComponent;
|
|
13
|
-
let fixture: ComponentFixture<EmailLoginFormComponent>;
|
|
14
|
-
|
|
15
|
-
beforeEach(waitForAsync(async () => {
|
|
16
|
-
await TestBed.configureTestingModule({
|
|
17
|
-
imports: [EmailLoginFormComponent],
|
|
18
|
-
providers: [
|
|
19
|
-
{
|
|
20
|
-
provide: APP_INFO,
|
|
21
|
-
useValue: { appId: 'test', appTitle: 'Test' },
|
|
22
|
-
},
|
|
23
|
-
{
|
|
24
|
-
provide: AnalyticsService,
|
|
25
|
-
useValue: { logEvent: vi.fn() },
|
|
26
|
-
},
|
|
27
|
-
{
|
|
28
|
-
provide: ErrorLogger,
|
|
29
|
-
useValue: { logError: vi.fn(), logErrorHandler: () => vi.fn() },
|
|
30
|
-
},
|
|
31
|
-
{ provide: ToastController, useValue: { create: vi.fn() } },
|
|
32
|
-
{ provide: Auth, useValue: {} },
|
|
33
|
-
{
|
|
34
|
-
provide: RandomIdService,
|
|
35
|
-
useValue: { newRandomId: () => 'test-id' },
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
provide: SneatApiService,
|
|
39
|
-
useValue: { post: vi.fn(), setApiAuthToken: vi.fn() },
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
provide: UserRecordService,
|
|
43
|
-
useValue: { initUserRecord: vi.fn() },
|
|
44
|
-
},
|
|
45
|
-
],
|
|
46
|
-
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
|
47
|
-
})
|
|
48
|
-
.overrideComponent(EmailLoginFormComponent, {
|
|
49
|
-
set: { imports: [], schemas: [CUSTOM_ELEMENTS_SCHEMA] },
|
|
50
|
-
})
|
|
51
|
-
.compileComponents();
|
|
52
|
-
fixture = TestBed.createComponent(EmailLoginFormComponent);
|
|
53
|
-
component = fixture.componentInstance;
|
|
54
|
-
}));
|
|
55
|
-
|
|
56
|
-
it('should create', () => {
|
|
57
|
-
expect(component).toBeTruthy();
|
|
58
|
-
});
|
|
59
|
-
});
|