diff --git a/css/src/main.css b/css/src/main.css index c5651a0..6c394f1 100644 --- a/css/src/main.css +++ b/css/src/main.css @@ -544,6 +544,7 @@ button > * { border-radius: 5px; border-top: 1px solid #555; box-shadow: 10px 10px 10px -8px rgba(0, 0, 0, 0.3); + z-index: 100000; } .alert.error { diff --git a/js/src/configdialogmodel.js b/js/src/configdialogmodel.js index 3f4a456..b698880 100644 --- a/js/src/configdialogmodel.js +++ b/js/src/configdialogmodel.js @@ -19,11 +19,11 @@ import { lang as $, config } from './initializer.js'; import ViewModel from './viewmodel.js'; +import uAlert from './alert.js'; import uDialog from './dialog.js'; import uLayer from './layer.js'; import uLayerCollection from './layercollection.js'; import uSelect from './select.js'; -import uUtils from './utils.js'; /** * @class ConfigDialogModel @@ -105,7 +105,7 @@ export default class ConfigDialogModel extends ViewModel { this.model.layers.setPriorityLayer(this.model.layerId); config.save(this.model) .then(() => this.dialog.destroy()) - .catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); }); + .catch((e) => { uAlert.error(`${$._('actionfailure')}\n${e.message}`, e); }); } } diff --git a/js/src/mapapi/api_gmaps.js b/js/src/mapapi/api_gmaps.js index 4cd51a4..d630131 100644 --- a/js/src/mapapi/api_gmaps.js +++ b/js/src/mapapi/api_gmaps.js @@ -19,6 +19,7 @@ import { lang as $, config } from '../initializer.js'; import MapViewModel from '../mapviewmodel.js'; +import uAlert from '../alert.js'; import uTrack from '../track.js'; import uUtils from '../utils.js'; @@ -78,7 +79,7 @@ export default class GoogleMapsApi { message += '

' + $._('gmauthfailure'); message += '

' + $._('gmapilink'); if (GoogleMapsApi.gmInitialized) { - alert(message); + uAlert.error(message); } reject(new Error(message)); }; @@ -178,7 +179,7 @@ export default class GoogleMapsApi { this.setZoom(15); } }); - setTimeout(function () { + setTimeout(() => { google.maps.event.removeListener(zListener); }, 2000); } diff --git a/js/src/mapviewmodel.js b/js/src/mapviewmodel.js index fb5affb..eff39e4 100644 --- a/js/src/mapviewmodel.js +++ b/js/src/mapviewmodel.js @@ -22,6 +22,7 @@ import GoogleMapsApi from './mapapi/api_gmaps.js'; import OpenLayersApi from './mapapi/api_openlayers.js'; import PositionDialogModel from './positiondialogmodel.js'; import ViewModel from './viewmodel.js'; +import uAlert from './alert.js'; import uDialog from './dialog.js'; import uObserve from './observe.js'; import uUtils from './utils.js'; @@ -96,7 +97,7 @@ export default class MapViewModel extends ViewModel { if (e && e.message) { txt += ` (${e.message})`; } - uUtils.error(e, txt); + uAlert.error(txt, e); config.mapApi = (apiName === 'gmaps') ? 'openlayers' : 'gmaps'; }); } diff --git a/js/src/positiondialogmodel.js b/js/src/positiondialogmodel.js index 20614ac..cfb985c 100644 --- a/js/src/positiondialogmodel.js +++ b/js/src/positiondialogmodel.js @@ -19,6 +19,7 @@ import { lang as $ } from './initializer.js'; import ViewModel from './viewmodel.js'; +import uAlert from './alert.js'; import uDialog from './dialog.js'; import uObserve from './observe.js'; import uUtils from './utils.js'; @@ -81,7 +82,7 @@ export default class PositionDialogModel extends ViewModel { track.recalculatePositions(); this.state.currentTrack = track; this.dialog.destroy(); - }).catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); }); + }).catch((e) => { uAlert.error(`${$._('actionfailure')}\n${e.message}`, e); }); } } @@ -93,7 +94,7 @@ export default class PositionDialogModel extends ViewModel { uObserve.forceUpdate(this.state, 'currentTrack'); this.dialog.destroy() }) - .catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); }); + .catch((e) => { uAlert.error(`${$._('actionfailure')}\n${e.message}`, e); }); } } diff --git a/js/src/trackdialogmodel.js b/js/src/trackdialogmodel.js index 73ecd71..b8e41dd 100644 --- a/js/src/trackdialogmodel.js +++ b/js/src/trackdialogmodel.js @@ -19,6 +19,7 @@ import { lang as $ } from '../src/initializer.js'; import ViewModel from './viewmodel.js'; +import uAlert from './alert.js'; import uDialog from './dialog.js'; import uUtils from './utils.js'; @@ -70,7 +71,7 @@ export default class TrackDialogModel extends ViewModel { this.track.delete().then(() => { this.trackVM.onTrackDeleted(); this.dialog.destroy(); - }).catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); }); + }).catch((e) => { uAlert.error(`${$._('actionfailure')}\n${e.message}`, e); }); } } @@ -79,7 +80,7 @@ export default class TrackDialogModel extends ViewModel { this.track.setName(this.model.trackname); this.track.saveMeta() .then(() => this.dialog.destroy()) - .catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); }); + .catch((e) => { uAlert.error(`${$._('actionfailure')}\n${e.message}`, e); }); } } @@ -96,7 +97,7 @@ export default class TrackDialogModel extends ViewModel { return false; } if (!this.model.trackname) { - alert($._('allrequired')); + uAlert.error($._('allrequired')); return false; } return true; diff --git a/js/src/trackviewmodel.js b/js/src/trackviewmodel.js index 8ee02a1..0f1bcc5 100644 --- a/js/src/trackviewmodel.js +++ b/js/src/trackviewmodel.js @@ -20,6 +20,7 @@ import { lang as $, auth, config } from './initializer.js'; import TrackDialogModel from './trackdialogmodel.js'; import ViewModel from './viewmodel.js'; +import uAlert from './alert.js'; import uObserve from './observe.js'; import uPositionSet from './positionset.js'; import uSelect from './select.js'; @@ -165,24 +166,24 @@ export default class TrackViewModel extends ViewModel { const form = this.importEl.parentElement; const sizeMax = form.elements['MAX_FILE_SIZE'].value; if (this.importEl.files && this.importEl.files.length === 1 && this.importEl.files[0].size > sizeMax) { - uUtils.error($._('isizefailure', sizeMax)); + uAlert.error($._('isizefailure', sizeMax)); return; } if (!auth.isAuthenticated) { - uUtils.error($._('notauthorized')); + uAlert.error($._('notauthorized')); return; } uTrack.import(form, auth.user) .then((trackList) => { if (trackList.length) { if (trackList.length > 1) { - alert($._('imultiple', trackList.length)); + uAlert.toast($._('imultiple', trackList.length)); } this.model.trackList = trackList.concat(this.model.trackList); this.model.currentTrackId = trackList[0].listValue; } }) - .catch((e) => uUtils.error(e, `${$._('actionfailure')}\n${e.message}`)) + .catch((e) => uAlert.error(`${$._('actionfailure')}\n${e.message}`, e)) .finally(() => { this.model.inputFile = ''; }); @@ -205,7 +206,7 @@ export default class TrackViewModel extends ViewModel { this.model.showLatest = false; } }) - .catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); }); + .catch((e) => { uAlert.error(`${$._('actionfailure')}\n${e.message}`, e); }); } } @@ -218,7 +219,7 @@ export default class TrackViewModel extends ViewModel { this.state.currentTrack.clear(); } this.state.currentTrack.fetchPositions() - .catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); }); + .catch((e) => { uAlert.error(`${$._('actionfailure')}\n${e.message}`, e); }); } /** @@ -235,7 +236,7 @@ export default class TrackViewModel extends ViewModel { this.model.currentTrackId = _track.listValue; } }) - .catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); }); + .catch((e) => { uAlert.error(`${$._('actionfailure')}\n${e.message}`, e); }); } /** @@ -250,7 +251,7 @@ export default class TrackViewModel extends ViewModel { this.state.currentTrack = _track; } }) - .catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); }); + .catch((e) => { uAlert.error(`${$._('actionfailure')}\n${e.message}`, e); }); } loadTrackList() { @@ -268,7 +269,7 @@ export default class TrackViewModel extends ViewModel { this.model.currentTrackId = ''; } }) - .catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); }); + .catch((e) => { uAlert.error(`${$._('actionfailure')}\n${e.message}`, e); }); } showDialog() { diff --git a/js/src/ulogger.js b/js/src/ulogger.js index 71b0428..80139cb 100644 --- a/js/src/ulogger.js +++ b/js/src/ulogger.js @@ -24,6 +24,7 @@ import MainViewModel from './mainviewmodel.js'; import MapViewModel from './mapviewmodel.js'; import TrackViewModel from './trackviewmodel.js'; import UserViewModel from './userviewmodel.js'; +import uAlert from './alert.js'; import uState from './state.js'; const domReady = uInitializer.waitForDom(); @@ -33,7 +34,7 @@ Promise.all([ domReady, initReady ]) .then(() => { start(); }) - .catch((msg) => alert(`${$._('actionfailure')}\n${msg}`)); + .catch((msg) => uAlert.error(`${$._('actionfailure')}\n${msg}`)); function start() { diff --git a/js/src/userdialogmodel.js b/js/src/userdialogmodel.js index 8145afe..47e1591 100644 --- a/js/src/userdialogmodel.js +++ b/js/src/userdialogmodel.js @@ -19,6 +19,7 @@ import { lang as $, auth, config } from './initializer.js'; import ViewModel from './viewmodel.js'; +import uAlert from './alert.js'; import uDialog from './dialog.js'; import uUser from './user.js'; import uUtils from './utils.js'; @@ -75,7 +76,7 @@ export default class UserDialogModel extends ViewModel { this.user.delete().then(() => { this.userVM.onUserDeleted(); this.dialog.destroy(); - }).catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); }); + }).catch((e) => { uAlert.error(`${$._('actionfailure')}\n${e.message}`, e); }); } } @@ -84,7 +85,7 @@ export default class UserDialogModel extends ViewModel { const password = this.model.passVisibility ? this.model.password : null; this.user.modify(this.model.admin, password) .then(() => this.dialog.destroy()) - .catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); }); + .catch((e) => { uAlert.error(`${$._('actionfailure')}\n${e.message}`, e); }); } } @@ -93,7 +94,7 @@ export default class UserDialogModel extends ViewModel { if (this.validate()) { auth.user.setPassword(this.model.password, this.model.oldPassword) .then(() => this.dialog.destroy()) - .catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); }); + .catch((e) => { uAlert.error(`${$._('actionfailure')}\n${e.message}`, e); }); } } @@ -103,7 +104,7 @@ export default class UserDialogModel extends ViewModel { uUser.add(this.model.login, this.model.password, this.model.admin).then((user) => { this.userVM.onUserAdded(user); this.dialog.destroy(); - }).catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); }); + }).catch((e) => { uAlert.error(`${$._('actionfailure')}\n${e.message}`, e); }); } } @@ -118,26 +119,26 @@ export default class UserDialogModel extends ViewModel { validate() { if (this.type === 'add') { if (!this.model.login) { - alert($._('allrequired')); + uAlert.error($._('allrequired')); return false; } } else if (this.type === 'pass') { if (!this.model.oldPassword) { - alert($._('allrequired')); + uAlert.error($._('allrequired')); return false; } } if (this.model.passVisibility) { if (!this.model.password || !this.model.password2) { - alert($._('allrequired')); + uAlert.error($._('allrequired')); return false; } if (this.model.password !== this.model.password2) { - alert($._('passnotmatch')); + uAlert.error($._('passnotmatch')); return false; } if (!config.validPassStrength(this.model.password)) { - alert($.getLocalePassRules()); + uAlert.error($.getLocalePassRules()); return false; } } diff --git a/js/src/userviewmodel.js b/js/src/userviewmodel.js index f4a7869..9c7e710 100644 --- a/js/src/userviewmodel.js +++ b/js/src/userviewmodel.js @@ -20,9 +20,9 @@ import { lang as $, auth } from './initializer.js'; import UserDialogModel from './userdialogmodel.js'; import ViewModel from './viewmodel.js'; +import uAlert from './alert.js'; import uSelect from './select.js'; import uUser from './user.js'; -import uUtils from './utils.js'; /** * @class UserViewModel @@ -80,7 +80,7 @@ export default class UserViewModel extends ViewModel { this.model.currentUserId = userId; } }) - .catch((e) => { uUtils.error(e, `${$._('actionfailure')}\n${e.message}`); }); + .catch((e) => { uAlert.error(`${$._('actionfailure')}\n${e.message}`, e); }); return this; } diff --git a/js/test/api_gmaps.test.js b/js/test/api_gmaps.test.js index 550854c..5e071f6 100644 --- a/js/test/api_gmaps.test.js +++ b/js/test/api_gmaps.test.js @@ -21,6 +21,7 @@ import * as gmStub from './helpers/googlemaps.stub.js'; import { config, lang } from '../src/initializer.js' import GoogleMapsApi from '../src/mapapi/api_gmaps.js'; import TrackFactory from './helpers/trackfactory.js'; +import uAlert from '../src/alert.js'; import uObserve from '../src/observe.js'; import uUtils from '../src/utils.js'; @@ -45,7 +46,7 @@ describe('Google Maps map API tests', () => { spyOn(google.maps, 'Marker').and.callThrough(); spyOn(google.maps, 'Polyline').and.callThrough(); spyOnProperty(GoogleMapsApi, 'loadTimeoutMs', 'get').and.returnValue(loadTimeout); - spyOn(window, 'alert'); + spyOn(uAlert, 'error'); spyOn(lang, '_').and.returnValue('{placeholder}'); gmStub.applyPrototypes(); }); @@ -155,8 +156,8 @@ describe('Google Maps map API tests', () => { window.gm_loaded(); window.gm_authFailure(); - expect(window.alert).toHaveBeenCalledTimes(1); - expect(window.alert.calls.mostRecent().args[0]).toContain('authfailure'); + expect(uAlert.error).toHaveBeenCalledTimes(1); + expect(uAlert.error.calls.mostRecent().args[0]).toContain('authfailure'); }); it('should clean up class fields', () => { diff --git a/js/test/mapviewmodel.test.js b/js/test/mapviewmodel.test.js index b96ff15..601f048 100644 --- a/js/test/mapviewmodel.test.js +++ b/js/test/mapviewmodel.test.js @@ -22,6 +22,7 @@ import Fixture from './helpers/fixture.js'; import MapViewModel from '../src/mapviewmodel.js'; import TrackFactory from './helpers/trackfactory.js'; import ViewModel from '../src/viewmodel.js'; +import uAlert from '../src/alert.js'; import uObserve from '../src/observe.js'; import uState from '../src/state.js'; import uUtils from '../src/utils.js'; @@ -111,7 +112,7 @@ describe('MapViewModel tests', () => { it('should load gmaps api and fail with error, config map api should be set to another api', (done) => { // given spyOn(vm, 'onReady'); - spyOn(uUtils, 'error'); + spyOn(uAlert, 'error'); mockApi.init.and.returnValue(Promise.reject(new Error('init failed'))); // when vm.loadMapAPI('gmaps'); @@ -120,7 +121,7 @@ describe('MapViewModel tests', () => { expect(vm.getApi).toHaveBeenCalledWith('gmaps'); expect(vm.onReady).not.toHaveBeenCalled(); expect(config.mapApi).toBe('openlayers'); - expect(uUtils.error).toHaveBeenCalledWith(jasmine.any(Error), jasmine.stringMatching('init failed')); + expect(uAlert.error).toHaveBeenCalledWith(jasmine.stringMatching('init failed'), jasmine.any(Error)); done(); }, 100); }); diff --git a/js/test/positiondialogmodel.test.js b/js/test/positiondialogmodel.test.js index 9623ded..f95c61f 100644 --- a/js/test/positiondialogmodel.test.js +++ b/js/test/positiondialogmodel.test.js @@ -44,7 +44,6 @@ describe('PositionDialogModel tests', () => { spyOn(track.positions[positionIndex], 'save').and.returnValue(Promise.resolve()); spyOn(track.positions[positionIndex], 'delete').and.returnValue(Promise.resolve()); spyOn(uObserve, 'forceUpdate'); - spyOn(window, 'alert'); }); afterEach(() => { diff --git a/js/test/trackdialogmodel.test.js b/js/test/trackdialogmodel.test.js index 51a96b8..f7deca7 100644 --- a/js/test/trackdialogmodel.test.js +++ b/js/test/trackdialogmodel.test.js @@ -20,6 +20,7 @@ import { config, lang } from '../src/initializer.js'; import TrackDialogModel from '../src/trackdialogmodel.js'; import TrackFactory from './helpers/trackfactory.js'; +import uAlert from '../src/alert.js'; import uDialog from '../src/dialog.js'; import uObserve from '../src/observe.js'; import uState from '../src/state.js'; @@ -41,7 +42,7 @@ describe('TrackDialogModel tests', () => { spyOn(dm.track, 'delete').and.returnValue(Promise.resolve()); spyOn(dm.track, 'saveMeta').and.returnValue(Promise.resolve()); spyOn(dm.track, 'setName'); - spyOn(window, 'alert'); + spyOn(uAlert, 'error'); }); afterEach(() => { @@ -153,7 +154,7 @@ describe('TrackDialogModel tests', () => { const result = dm.validate(); // then expect(result).toBe(false); - expect(window.alert).not.toHaveBeenCalled(); + expect(uAlert.error).not.toHaveBeenCalled(); }); it('should return false and raise alert if track name is empty', () => { @@ -164,7 +165,7 @@ describe('TrackDialogModel tests', () => { const result = dm.validate(); // then expect(result).toBe(false); - expect(window.alert).toHaveBeenCalledTimes(1); + expect(uAlert.error).toHaveBeenCalledTimes(1); }); it('should return true on valid track name', () => { @@ -175,6 +176,6 @@ describe('TrackDialogModel tests', () => { const result = dm.validate(); // then expect(result).toBe(true); - expect(window.alert).not.toHaveBeenCalled(); + expect(uAlert.error).not.toHaveBeenCalled(); }); }); diff --git a/js/test/trackviewmodel.test.js b/js/test/trackviewmodel.test.js index 67474b6..de4e9c3 100644 --- a/js/test/trackviewmodel.test.js +++ b/js/test/trackviewmodel.test.js @@ -22,12 +22,12 @@ import Fixture from './helpers/fixture.js'; import TrackFactory from './helpers/trackfactory.js'; import TrackViewModel from '../src/trackviewmodel.js'; import ViewModel from '../src/viewmodel.js'; +import uAlert from '../src/alert.js'; import uObserve from '../src/observe.js'; import uPositionSet from '../src/positionset.js'; import uState from '../src/state.js'; import uTrack from '../src/track.js'; import uUser from '../src/user.js'; -import uUtils from '../src/utils.js'; describe('TrackViewModel tests', () => { @@ -453,7 +453,7 @@ describe('TrackViewModel tests', () => { return Promise.resolve(imported); }); spyOn(uPositionSet, 'fetch').and.returnValue(Promise.resolve(positions)); - spyOn(window, 'alert'); + spyOn(uAlert, 'toast'); const options = ''; trackEl.insertAdjacentHTML('afterbegin', options); const optLength = trackEl.options.length; @@ -478,7 +478,7 @@ describe('TrackViewModel tests', () => { expect(state.currentTrack).toBe(imported[0]); expect(vm.model.currentTrackId).toBe(imported[0].listValue); expect(state.currentTrack.length).toBe(positions.length); - expect(window.alert).toHaveBeenCalledTimes(1); + expect(uAlert.toast).toHaveBeenCalledTimes(1); expect(trackEl.options.length).toBe(optLength + imported.length); expect(vm.model.trackList.length).toBe(optLength + imported.length); expect(vm.model.inputFile).toBe(''); @@ -495,7 +495,7 @@ describe('TrackViewModel tests', () => { ]; spyOn(uTrack, 'import').and.returnValue(Promise.resolve(imported)); spyOn(uPositionSet, 'fetch').and.returnValue(Promise.resolve(positions)); - spyOn(uUtils, 'error'); + spyOn(uAlert, 'error'); const options = ''; trackEl.insertAdjacentHTML('afterbegin', options); const optLength = trackEl.options.length; @@ -534,7 +534,7 @@ describe('TrackViewModel tests', () => { const file = new File([ 'blob' ], '/path/filepath.gpx'); spyOn(uTrack, 'import').and.returnValue(Promise.resolve(imported)); spyOn(uPositionSet, 'fetch').and.returnValue(Promise.resolve(positions)); - spyOn(uUtils, 'error'); + spyOn(uAlert, 'error'); const options = ''; trackEl.insertAdjacentHTML('afterbegin', options); const optLength = trackEl.options.length; @@ -556,7 +556,7 @@ describe('TrackViewModel tests', () => { expect(uTrack.import).not.toHaveBeenCalled(); expect(state.currentTrack).toBe(track1); expect(vm.model.currentTrackId).toBe(track1.listValue); - expect(uUtils.error).toHaveBeenCalledTimes(1); + expect(uAlert.error).toHaveBeenCalledTimes(1); expect(lang._).toHaveBeenCalledWith('notauthorized'); expect(trackEl.options.length).toBe(optLength); expect(vm.model.trackList.length).toBe(optLength); diff --git a/js/test/userdialogmodel.test.js b/js/test/userdialogmodel.test.js index 54ef1a9..f47b65e 100644 --- a/js/test/userdialogmodel.test.js +++ b/js/test/userdialogmodel.test.js @@ -19,6 +19,7 @@ import { auth, config, lang } from '../src/initializer.js'; import UserDialogModel from '../src/userdialogmodel.js'; +import uAlert from '../src/alert.js'; import uDialog from '../src/dialog.js'; import uObserve from '../src/observe.js'; import uState from '../src/state.js'; @@ -51,7 +52,7 @@ describe('UserDialogModel tests', () => { spyOn(auth.user, 'setPassword').and.returnValue(Promise.resolve()); spyOn(uUser, 'add').and.returnValue(Promise.resolve(newUser)); spyOn(config, 'validPassStrength').and.returnValue(true); - spyOn(window, 'alert'); + spyOn(uAlert, 'error'); }); afterEach(() => { @@ -277,7 +278,7 @@ describe('UserDialogModel tests', () => { const result = dm.validate(); // then expect(result).toBe(true); - expect(window.alert).not.toHaveBeenCalled(); + expect(uAlert.error).not.toHaveBeenCalled(); }); it('should return false on add user dialog empty login', () => { @@ -290,7 +291,7 @@ describe('UserDialogModel tests', () => { const result = dm.validate(); // then expect(result).toBe(false); - expect(window.alert).toHaveBeenCalledTimes(1); + expect(uAlert.error).toHaveBeenCalledTimes(1); }); it('should return false on password change dialog empty old password', () => { @@ -304,7 +305,7 @@ describe('UserDialogModel tests', () => { const result = dm.validate(); // then expect(result).toBe(false); - expect(window.alert).toHaveBeenCalledTimes(1); + expect(uAlert.error).toHaveBeenCalledTimes(1); }); it('should return false on add user dialog passwords not match', () => { @@ -317,7 +318,7 @@ describe('UserDialogModel tests', () => { const result = dm.validate(); // then expect(result).toBe(false); - expect(window.alert).toHaveBeenCalledTimes(1); + expect(uAlert.error).toHaveBeenCalledTimes(1); }); it('should return true and ignore passwords on add user dialog passwords hidden', () => { @@ -330,7 +331,7 @@ describe('UserDialogModel tests', () => { const result = dm.validate(); // then expect(result).toBe(true); - expect(window.alert).toHaveBeenCalledTimes(0); + expect(uAlert.error).toHaveBeenCalledTimes(0); }); it('should test password regex on dialog validate', () => {