diff --git a/src/core/core.module.ts b/src/core/core.module.ts index 7caca92ca..e2e7160b0 100644 --- a/src/core/core.module.ts +++ b/src/core/core.module.ts @@ -48,6 +48,7 @@ import { CoreUpdateManagerProvider } from '@services/update-manager'; import { CoreUrlUtilsProvider } from '@services/utils/url'; import { CoreUtilsProvider } from '@services/utils/utils'; import { CoreWSProvider } from '@services/ws'; +import { CorePlatformService } from '@services/platform'; export const CORE_SERVICES: Type[] = [ CoreAppProvider, @@ -68,6 +69,7 @@ export const CORE_SERVICES: Type[] = [ CoreMimetypeUtilsProvider, CoreNavigatorService, CorePluginFileDelegateService, + CorePlatformService, CoreScreenService, CoreSitesProvider, CoreSyncProvider, diff --git a/src/core/features/emulator/services/local-notifications.ts b/src/core/features/emulator/services/local-notifications.ts index 965dc05ba..7e68a2f65 100644 --- a/src/core/features/emulator/services/local-notifications.ts +++ b/src/core/features/emulator/services/local-notifications.ts @@ -15,6 +15,8 @@ import { CoreError } from '@classes/errors/error'; import { ILocalNotification, ILocalNotificationAction, LocalNotifications } from '@awesome-cordova-plugins/local-notifications/ngx'; import { Observable, Subject } from 'rxjs'; +import { CoreUtils } from '@services/utils/utils'; +import { CorePlatform } from '@services/platform'; /** * Mock LocalNotifications service. @@ -332,7 +334,16 @@ export class LocalNotificationsMock extends LocalNotifications { */ async registerPermission(): Promise { // We need to ask the user for permission - const permission = await Notification.requestPermission(); + const permissionRequests = [Notification.requestPermission()]; + + if (CorePlatform.isAutomated()) { + // In some testing environments, Notification.requestPermission gets stuck and never returns. + // Given that we don't actually need browser notifications to work in Behat tests, we can just + // continue if the permissions haven't been granted after 1 second. + permissionRequests.push(CoreUtils.wait(1000).then(() => 'granted')); + } + + const permission = await Promise.race(permissionRequests); this.hasGranted = permission === 'granted'; diff --git a/src/core/features/grades/services/grades-helper.ts b/src/core/features/grades/services/grades-helper.ts index c85353011..279f2790c 100644 --- a/src/core/features/grades/services/grades-helper.ts +++ b/src/core/features/grades/services/grades-helper.ts @@ -41,9 +41,9 @@ import { CoreNavigator } from '@services/navigator'; import { makeSingleton, Translate } from '@singletons'; import { CoreError } from '@classes/errors/error'; import { CoreCourseHelper } from '@features/course/services/course-helper'; -import { CoreAppProvider } from '@services/app'; import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate'; import { CoreCourseAccess } from '@features/course/services/course-options-delegate'; +import { CorePlatform } from '@services/platform'; export const GRADES_PAGE_NAME = 'grades'; export const GRADES_PARTICIPANTS_PAGE_NAME = 'participant-grades'; @@ -105,7 +105,7 @@ export class CoreGradesHelperProvider { row.rowclass += itemNameColumn.class.indexOf('hidden') >= 0 ? ' hidden' : ''; row.rowclass += itemNameColumn.class.indexOf('dimmed_text') >= 0 ? ' dimmed_text' : ''; - if (!useLegacyLayout && !CoreAppProvider.isAutomated()) { + if (!useLegacyLayout && !CorePlatform.isAutomated()) { // Activity name is only included in the webservice response from the latest version when behat is not running. content = content.replace(/]+>.+?<\/span>/i, ''); } diff --git a/src/core/services/app.ts b/src/core/services/app.ts index 3951685d7..a71d7b8f7 100644 --- a/src/core/services/app.ts +++ b/src/core/services/app.ts @@ -70,10 +70,11 @@ export class CoreAppProvider { /** * Returns whether the user agent is controlled by automation. I.e. Behat testing. * + * @deprecated since 4.4. Use CorePlatform.isAutomated() instead. * @returns True if the user agent is controlled by automation, false otherwise. */ static isAutomated(): boolean { - return !!navigator.webdriver; + return CorePlatform.isAutomated(); } /** @@ -82,7 +83,7 @@ export class CoreAppProvider { * @returns Timezone. Undefined to use the user's timezone. */ static getForcedTimezone(): string | undefined { - if (CoreAppProvider.isAutomated()) { + if (CorePlatform.isAutomated()) { // Use the same timezone forced for LMS in tests. return 'Australia/Perth'; } diff --git a/src/core/services/lang.ts b/src/core/services/lang.ts index 00c7e65f2..e15062850 100644 --- a/src/core/services/lang.ts +++ b/src/core/services/lang.ts @@ -16,7 +16,6 @@ import { Injectable } from '@angular/core'; import { CoreConstants } from '@/core/constants'; import { LangChangeEvent } from '@ngx-translate/core'; -import { CoreAppProvider } from '@services/app'; import { CoreConfig } from '@services/config'; import { CoreSubscriptions } from '@singletons/subscriptions'; import { makeSingleton, Translate, Http } from '@singletons'; @@ -71,7 +70,7 @@ export class CoreLangProvider { let language: string; - if (CoreAppProvider.isAutomated()) { + if (CorePlatform.isAutomated()) { // Force current language to English when Behat is running. language = 'en'; } else { diff --git a/src/core/services/platform.ts b/src/core/services/platform.ts index 87e40fdfb..a029de0b4 100644 --- a/src/core/services/platform.ts +++ b/src/core/services/platform.ts @@ -44,6 +44,15 @@ export class CorePlatformService extends Platform { return this.isMobile() && this.is('android'); } + /** + * Returns whether the user agent is controlled by automation. I.e. Behat testing. + * + * @returns True if the user agent is controlled by automation, false otherwise. + */ + isAutomated(): boolean { + return !!navigator.webdriver; + } + /** * Checks if the app is running in an iOS mobile or tablet device. * diff --git a/src/testing/testing.module.ts b/src/testing/testing.module.ts index 3b92ac120..9c3d29688 100644 --- a/src/testing/testing.module.ts +++ b/src/testing/testing.module.ts @@ -16,6 +16,7 @@ import { APP_INITIALIZER, NgModule } from '@angular/core'; import { CoreAppProvider } from '@services/app'; import moment from 'moment-timezone'; import { TestingBehatRuntime, TestingBehatRuntimeService } from './services/behat-runtime'; +import { CorePlatform } from '@services/platform'; type AutomatedTestsWindow = Window & { behat?: TestingBehatRuntimeService; @@ -27,7 +28,7 @@ type AutomatedTestsWindow = Window & { * @param window Window. */ function initializeAutomatedTests(window: AutomatedTestsWindow) { - if (!CoreAppProvider.isAutomated()) { + if (!CorePlatform.isAutomated()) { return; } diff --git a/upgrade.txt b/upgrade.txt index f188871bc..567d51573 100644 --- a/upgrade.txt +++ b/upgrade.txt @@ -11,6 +11,7 @@ For more information about upgrading, read the official documentation: https://m - With the upgrade to Ionic 7 ion-slides is no longer supported and now you need to use swiper-container and swiper-slide. More info here: https://ionicframework.com/docs/angular/slides - With the upgrade to Ionic7 ion-datetime has changed its usage. We recommend using ion-datetime-button. More info here: https://ionicframework.com/docs/updating/6-0#datetime - CoreLoginHelper.getErrorMessages has been removed. Please create the messages object yourself. + - CoreAppProvider.isAutomated() has been deprecated, use CorePlatformService.isAutomated() instead. === 4.3.0 ===