diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 000000000..48082f72f --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +12 diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..12ffc2065 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,5 @@ +{ + "recommendations": [ + "dbaeumer.vscode-eslint" + ] +} diff --git a/gulpfile.js b/gulpfile.js index 9f3f5f93f..31db54239 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -69,3 +69,7 @@ gulp.task('watch', () => { gulp.watch(['./tests/behat'], { interval: 500 }, gulp.parallel('behat')); } }); + +gulp.task('watch-behat', () => { + gulp.watch(['./tests/behat'], { interval: 500 }, gulp.parallel('behat')); +}); diff --git a/src/addons/badges/badges.module.ts b/src/addons/badges/badges.module.ts index de0fd76b9..ed210a21e 100644 --- a/src/addons/badges/badges.module.ts +++ b/src/addons/badges/badges.module.ts @@ -44,8 +44,7 @@ const mainMenuRoutes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreContentLinksDelegate.registerHandler(AddonBadgesMyBadgesLinkHandler.instance); CoreContentLinksDelegate.registerHandler(AddonBadgesBadgeLinkHandler.instance); CoreUserDelegate.registerHandler(AddonBadgesUserHandler.instance); diff --git a/src/addons/blog/blog.module.ts b/src/addons/blog/blog.module.ts index c0fc7aa94..f933599fb 100644 --- a/src/addons/blog/blog.module.ts +++ b/src/addons/blog/blog.module.ts @@ -51,8 +51,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => async () => { + useValue: () => { CoreContentLinksDelegate.registerHandler(AddonBlogIndexLinkHandler.instance); CoreMainMenuDelegate.registerHandler(AddonBlogMainMenuHandler.instance); CoreUserDelegate.registerHandler(AddonBlogUserHandler.instance); diff --git a/src/addons/calendar/calendar.module.ts b/src/addons/calendar/calendar.module.ts index 0017176f0..3f4020e31 100644 --- a/src/addons/calendar/calendar.module.ts +++ b/src/addons/calendar/calendar.module.ts @@ -63,8 +63,7 @@ const mainMenuChildrenRoutes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => async () => { + useValue: async () => { CoreContentLinksDelegate.registerHandler(AddonCalendarViewLinkHandler.instance); CoreMainMenuDelegate.registerHandler(AddonCalendarMainMenuHandler.instance); CoreCronDelegate.register(AddonCalendarSyncCronHandler.instance); diff --git a/src/addons/competency/competency.module.ts b/src/addons/competency/competency.module.ts index e8a96e9e8..9e08180da 100644 --- a/src/addons/competency/competency.module.ts +++ b/src/addons/competency/competency.module.ts @@ -64,8 +64,7 @@ const courseIndexRoutes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => async () => { + useValue: () => { CoreContentLinksDelegate.registerHandler(AddonCompetencyCompetencyLinkHandler.instance); CoreContentLinksDelegate.registerHandler(AddonCompetencyPlanLinkHandler.instance); CoreContentLinksDelegate.registerHandler(AddonCompetencyPlansLinkHandler.instance); diff --git a/src/addons/coursecompletion/coursecompletion.module.ts b/src/addons/coursecompletion/coursecompletion.module.ts index 024980c8b..63fea73a7 100644 --- a/src/addons/coursecompletion/coursecompletion.module.ts +++ b/src/addons/coursecompletion/coursecompletion.module.ts @@ -42,8 +42,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => async () => { + useValue: () => { CoreUserDelegate.registerHandler(AddonCourseCompletionUserHandler.instance); CoreCourseOptionsDelegate.registerHandler(AddonCourseCompletionCourseOptionHandler.instance); }, diff --git a/src/addons/filter/activitynames/activitynames.module.ts b/src/addons/filter/activitynames/activitynames.module.ts index 1aa7ac805..48c4b1e43 100644 --- a/src/addons/filter/activitynames/activitynames.module.ts +++ b/src/addons/filter/activitynames/activitynames.module.ts @@ -26,8 +26,7 @@ import { AddonFilterActivityNamesHandler } from './services/handlers/activitynam { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => CoreFilterDelegate.registerHandler(AddonFilterActivityNamesHandler.instance), + useValue: () => CoreFilterDelegate.registerHandler(AddonFilterActivityNamesHandler.instance), }, ], }) diff --git a/src/addons/filter/algebra/algebra.module.ts b/src/addons/filter/algebra/algebra.module.ts index 8fe37b21d..bf961e966 100644 --- a/src/addons/filter/algebra/algebra.module.ts +++ b/src/addons/filter/algebra/algebra.module.ts @@ -26,8 +26,7 @@ import { AddonFilterAlgebraHandler } from './services/handlers/algebra'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => CoreFilterDelegate.registerHandler(AddonFilterAlgebraHandler.instance), + useValue: () => CoreFilterDelegate.registerHandler(AddonFilterAlgebraHandler.instance), }, ], }) diff --git a/src/addons/filter/censor/censor.module.ts b/src/addons/filter/censor/censor.module.ts index bdb741ab7..05672bae4 100644 --- a/src/addons/filter/censor/censor.module.ts +++ b/src/addons/filter/censor/censor.module.ts @@ -26,8 +26,7 @@ import { AddonFilterCensorHandler } from './services/handlers/censor'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => CoreFilterDelegate.registerHandler(AddonFilterCensorHandler.instance), + useValue: () => CoreFilterDelegate.registerHandler(AddonFilterCensorHandler.instance), }, ], }) diff --git a/src/addons/filter/data/data.module.ts b/src/addons/filter/data/data.module.ts index fe88960d0..6da1a0b2c 100644 --- a/src/addons/filter/data/data.module.ts +++ b/src/addons/filter/data/data.module.ts @@ -26,8 +26,7 @@ import { AddonFilterDataHandler } from './services/handlers/data'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => CoreFilterDelegate.registerHandler(AddonFilterDataHandler.instance), + useValue: () => CoreFilterDelegate.registerHandler(AddonFilterDataHandler.instance), }, ], }) diff --git a/src/addons/filter/displayh5p/displayh5p.module.ts b/src/addons/filter/displayh5p/displayh5p.module.ts index d40923144..ab5df85c4 100644 --- a/src/addons/filter/displayh5p/displayh5p.module.ts +++ b/src/addons/filter/displayh5p/displayh5p.module.ts @@ -26,8 +26,7 @@ import { AddonFilterDisplayH5PHandler } from './services/handlers/displayh5p'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => CoreFilterDelegate.registerHandler(AddonFilterDisplayH5PHandler.instance), + useValue: () => CoreFilterDelegate.registerHandler(AddonFilterDisplayH5PHandler.instance), }, ], }) diff --git a/src/addons/filter/emailprotect/emailprotect.module.ts b/src/addons/filter/emailprotect/emailprotect.module.ts index 3793c4219..b25597acc 100644 --- a/src/addons/filter/emailprotect/emailprotect.module.ts +++ b/src/addons/filter/emailprotect/emailprotect.module.ts @@ -26,8 +26,7 @@ import { AddonFilterEmailProtectHandler } from './services/handlers/emailprotect { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => CoreFilterDelegate.registerHandler(AddonFilterEmailProtectHandler.instance), + useValue: () => CoreFilterDelegate.registerHandler(AddonFilterEmailProtectHandler.instance), }, ], }) diff --git a/src/addons/filter/emoticon/emoticon.module.ts b/src/addons/filter/emoticon/emoticon.module.ts index 1e925074e..a0d562e87 100644 --- a/src/addons/filter/emoticon/emoticon.module.ts +++ b/src/addons/filter/emoticon/emoticon.module.ts @@ -26,8 +26,7 @@ import { AddonFilterEmoticonHandler } from './services/handlers/emoticon'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => CoreFilterDelegate.registerHandler(AddonFilterEmoticonHandler.instance), + useValue: () => CoreFilterDelegate.registerHandler(AddonFilterEmoticonHandler.instance), }, ], }) diff --git a/src/addons/filter/glossary/glossary.module.ts b/src/addons/filter/glossary/glossary.module.ts index 6464e2c84..8061c73cf 100644 --- a/src/addons/filter/glossary/glossary.module.ts +++ b/src/addons/filter/glossary/glossary.module.ts @@ -26,8 +26,7 @@ import { AddonFilterGlossaryHandler } from './services/handlers/glossary'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => CoreFilterDelegate.registerHandler(AddonFilterGlossaryHandler.instance), + useValue: () => CoreFilterDelegate.registerHandler(AddonFilterGlossaryHandler.instance), }, ], }) diff --git a/src/addons/filter/mathjaxloader/mathjaxloader.module.ts b/src/addons/filter/mathjaxloader/mathjaxloader.module.ts index 0f3aa5b60..fdabf6056 100644 --- a/src/addons/filter/mathjaxloader/mathjaxloader.module.ts +++ b/src/addons/filter/mathjaxloader/mathjaxloader.module.ts @@ -26,8 +26,7 @@ import { AddonFilterMathJaxLoaderHandler } from './services/handlers/mathjaxload { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => async () => { + useValue: async () => { CoreFilterDelegate.registerHandler(AddonFilterMathJaxLoaderHandler.instance); await AddonFilterMathJaxLoaderHandler.initialize(); diff --git a/src/addons/filter/mediaplugin/mediaplugin.module.ts b/src/addons/filter/mediaplugin/mediaplugin.module.ts index a72670098..1977bd08d 100644 --- a/src/addons/filter/mediaplugin/mediaplugin.module.ts +++ b/src/addons/filter/mediaplugin/mediaplugin.module.ts @@ -26,8 +26,7 @@ import { AddonFilterMediaPluginHandler } from './services/handlers/mediaplugin'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => CoreFilterDelegate.registerHandler(AddonFilterMediaPluginHandler.instance), + useValue: () => CoreFilterDelegate.registerHandler(AddonFilterMediaPluginHandler.instance), }, ], }) diff --git a/src/addons/filter/multilang/multilang.module.ts b/src/addons/filter/multilang/multilang.module.ts index 7ffab28b7..9e4ebda2d 100644 --- a/src/addons/filter/multilang/multilang.module.ts +++ b/src/addons/filter/multilang/multilang.module.ts @@ -26,8 +26,7 @@ import { AddonFilterMultilangHandler } from './services/handlers/multilang'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => CoreFilterDelegate.registerHandler(AddonFilterMultilangHandler.instance), + useValue: () => CoreFilterDelegate.registerHandler(AddonFilterMultilangHandler.instance), }, ], }) diff --git a/src/addons/filter/tex/tex.module.ts b/src/addons/filter/tex/tex.module.ts index 414d3fdc5..94e031fc5 100644 --- a/src/addons/filter/tex/tex.module.ts +++ b/src/addons/filter/tex/tex.module.ts @@ -26,8 +26,7 @@ import { AddonFilterTexHandler } from './services/handlers/tex'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => CoreFilterDelegate.registerHandler(AddonFilterTexHandler.instance), + useValue: () => CoreFilterDelegate.registerHandler(AddonFilterTexHandler.instance), }, ], }) diff --git a/src/addons/filter/tidy/tidy.module.ts b/src/addons/filter/tidy/tidy.module.ts index cf1045f1e..3cfedb6d1 100644 --- a/src/addons/filter/tidy/tidy.module.ts +++ b/src/addons/filter/tidy/tidy.module.ts @@ -26,8 +26,7 @@ import { AddonFilterTidyHandler } from './services/handlers/tidy'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => CoreFilterDelegate.registerHandler(AddonFilterTidyHandler.instance), + useValue: () => CoreFilterDelegate.registerHandler(AddonFilterTidyHandler.instance), }, ], }) diff --git a/src/addons/filter/urltolink/urltolink.module.ts b/src/addons/filter/urltolink/urltolink.module.ts index 48230c7dd..e5ee0667b 100644 --- a/src/addons/filter/urltolink/urltolink.module.ts +++ b/src/addons/filter/urltolink/urltolink.module.ts @@ -26,8 +26,7 @@ import { AddonFilterUrlToLinkHandler } from './services/handlers/urltolink'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => CoreFilterDelegate.registerHandler(AddonFilterUrlToLinkHandler.instance), + useValue: () => CoreFilterDelegate.registerHandler(AddonFilterUrlToLinkHandler.instance), }, ], }) diff --git a/src/addons/messageoutput/airnotifier/airnotifier.module.ts b/src/addons/messageoutput/airnotifier/airnotifier.module.ts index 99c4b1849..3e3d06870 100644 --- a/src/addons/messageoutput/airnotifier/airnotifier.module.ts +++ b/src/addons/messageoutput/airnotifier/airnotifier.module.ts @@ -39,8 +39,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonMessageOutputDelegate.registerHandler(AddonMessageOutputAirnotifierHandler.instance); }, }, diff --git a/src/addons/messages/messages.module.ts b/src/addons/messages/messages.module.ts index 251b053e9..5616c65e6 100644 --- a/src/addons/messages/messages.module.ts +++ b/src/addons/messages/messages.module.ts @@ -73,8 +73,7 @@ const preferencesRoutes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { // Register handlers. CoreMainMenuDelegate.registerHandler(AddonMessagesMainMenuHandler.instance); CoreCronDelegate.register(AddonMessagesMainMenuHandler.instance); diff --git a/src/addons/mod/assign/assign.module.ts b/src/addons/mod/assign/assign.module.ts index 46bd253e9..001a5cf16 100644 --- a/src/addons/mod/assign/assign.module.ts +++ b/src/addons/mod/assign/assign.module.ts @@ -70,8 +70,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseModuleDelegate.registerHandler(AddonModAssignModuleHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModAssignIndexLinkHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModAssignListLinkHandler.instance); diff --git a/src/addons/mod/assign/feedback/comments/comments.module.ts b/src/addons/mod/assign/feedback/comments/comments.module.ts index 388efd827..d1be02007 100644 --- a/src/addons/mod/assign/feedback/comments/comments.module.ts +++ b/src/addons/mod/assign/feedback/comments/comments.module.ts @@ -31,8 +31,7 @@ import { AddonModAssignFeedbackDelegate } from '../../services/feedback-delegate { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModAssignFeedbackDelegate.registerHandler(AddonModAssignFeedbackCommentsHandler.instance); }, }, diff --git a/src/addons/mod/assign/feedback/editpdf/editpdf.module.ts b/src/addons/mod/assign/feedback/editpdf/editpdf.module.ts index d9c5dcb31..670975e8f 100644 --- a/src/addons/mod/assign/feedback/editpdf/editpdf.module.ts +++ b/src/addons/mod/assign/feedback/editpdf/editpdf.module.ts @@ -29,8 +29,7 @@ import { AddonModAssignFeedbackDelegate } from '../../services/feedback-delegate { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModAssignFeedbackDelegate.registerHandler(AddonModAssignFeedbackEditPdfHandler.instance); }, }, diff --git a/src/addons/mod/assign/feedback/file/file.module.ts b/src/addons/mod/assign/feedback/file/file.module.ts index 021ce1149..b1dca6200 100644 --- a/src/addons/mod/assign/feedback/file/file.module.ts +++ b/src/addons/mod/assign/feedback/file/file.module.ts @@ -29,8 +29,7 @@ import { AddonModAssignFeedbackDelegate } from '../../services/feedback-delegate { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModAssignFeedbackDelegate.registerHandler(AddonModAssignFeedbackFileHandler.instance); }, }, diff --git a/src/addons/mod/assign/submission/comments/comments.module.ts b/src/addons/mod/assign/submission/comments/comments.module.ts index 361d3a96e..49de6435e 100644 --- a/src/addons/mod/assign/submission/comments/comments.module.ts +++ b/src/addons/mod/assign/submission/comments/comments.module.ts @@ -31,8 +31,7 @@ import { CoreCommentsComponentsModule } from '@features/comments/components/comp { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModAssignSubmissionDelegate.registerHandler(AddonModAssignSubmissionCommentsHandler.instance); }, }, diff --git a/src/addons/mod/assign/submission/file/file.module.ts b/src/addons/mod/assign/submission/file/file.module.ts index ce4501efe..a71426556 100644 --- a/src/addons/mod/assign/submission/file/file.module.ts +++ b/src/addons/mod/assign/submission/file/file.module.ts @@ -29,8 +29,7 @@ import { AddonModAssignSubmissionDelegate } from '../../services/submission-dele { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModAssignSubmissionDelegate.registerHandler(AddonModAssignSubmissionFileHandler.instance); }, }, diff --git a/src/addons/mod/assign/submission/onlinetext/onlinetext.module.ts b/src/addons/mod/assign/submission/onlinetext/onlinetext.module.ts index a3d79b5c8..fd2fc8338 100644 --- a/src/addons/mod/assign/submission/onlinetext/onlinetext.module.ts +++ b/src/addons/mod/assign/submission/onlinetext/onlinetext.module.ts @@ -31,8 +31,7 @@ import { AddonModAssignSubmissionDelegate } from '../../services/submission-dele { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModAssignSubmissionDelegate.registerHandler(AddonModAssignSubmissionOnlineTextHandler.instance); }, }, diff --git a/src/addons/mod/book/book.module.ts b/src/addons/mod/book/book.module.ts index 3123cf6b6..3ac80f207 100644 --- a/src/addons/mod/book/book.module.ts +++ b/src/addons/mod/book/book.module.ts @@ -47,8 +47,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseModuleDelegate.registerHandler(AddonModBookModuleHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModBookIndexLinkHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModBookListLinkHandler.instance); diff --git a/src/addons/mod/chat/chat.module.ts b/src/addons/mod/chat/chat.module.ts index b62ca916c..62509fdd6 100644 --- a/src/addons/mod/chat/chat.module.ts +++ b/src/addons/mod/chat/chat.module.ts @@ -47,8 +47,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseModuleDelegate.registerHandler(AddonModChatModuleHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModChatIndexLinkHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModChatListLinkHandler.instance); diff --git a/src/addons/mod/choice/choice.module.ts b/src/addons/mod/choice/choice.module.ts index dffa84ac7..ed00d95a5 100644 --- a/src/addons/mod/choice/choice.module.ts +++ b/src/addons/mod/choice/choice.module.ts @@ -59,8 +59,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseModuleDelegate.registerHandler(AddonModChoiceModuleHandler.instance); CoreCourseModulePrefetchDelegate.registerHandler(AddonModChoicePrefetchHandler.instance); CoreCronDelegate.register(AddonModChoiceSyncCronHandler.instance); diff --git a/src/addons/mod/data/data.module.ts b/src/addons/mod/data/data.module.ts index 353592b6d..aa75d547d 100644 --- a/src/addons/mod/data/data.module.ts +++ b/src/addons/mod/data/data.module.ts @@ -71,8 +71,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseModuleDelegate.registerHandler(AddonModDataModuleHandler.instance); CoreCourseModulePrefetchDelegate.registerHandler(AddonModDataPrefetchHandler.instance); CoreCronDelegate.register(AddonModDataSyncCronHandler.instance); diff --git a/src/addons/mod/data/fields/checkbox/checkbox.module.ts b/src/addons/mod/data/fields/checkbox/checkbox.module.ts index beb2b7786..05331b4ac 100644 --- a/src/addons/mod/data/fields/checkbox/checkbox.module.ts +++ b/src/addons/mod/data/fields/checkbox/checkbox.module.ts @@ -29,8 +29,7 @@ import { AddonModDataFieldCheckboxHandler } from './services/handler'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModDataFieldsDelegate.registerHandler(AddonModDataFieldCheckboxHandler.instance); }, }, diff --git a/src/addons/mod/data/fields/date/date.module.ts b/src/addons/mod/data/fields/date/date.module.ts index 05d33a1e0..e32d886e3 100644 --- a/src/addons/mod/data/fields/date/date.module.ts +++ b/src/addons/mod/data/fields/date/date.module.ts @@ -29,8 +29,7 @@ import { AddonModDataFieldDateHandler } from './services/handler'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModDataFieldsDelegate.registerHandler(AddonModDataFieldDateHandler.instance); }, }, diff --git a/src/addons/mod/data/fields/file/file.module.ts b/src/addons/mod/data/fields/file/file.module.ts index e3ad12323..a77c3f05e 100644 --- a/src/addons/mod/data/fields/file/file.module.ts +++ b/src/addons/mod/data/fields/file/file.module.ts @@ -29,8 +29,7 @@ import { AddonModDataFieldFileHandler } from './services/handler'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModDataFieldsDelegate.registerHandler(AddonModDataFieldFileHandler.instance); }, }, diff --git a/src/addons/mod/data/fields/latlong/latlong.module.ts b/src/addons/mod/data/fields/latlong/latlong.module.ts index 1dc6aacc5..d7aca0e7e 100644 --- a/src/addons/mod/data/fields/latlong/latlong.module.ts +++ b/src/addons/mod/data/fields/latlong/latlong.module.ts @@ -29,8 +29,7 @@ import { AddonModDataFieldLatlongHandler } from './services/handler'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModDataFieldsDelegate.registerHandler(AddonModDataFieldLatlongHandler.instance); }, }, diff --git a/src/addons/mod/data/fields/menu/menu.module.ts b/src/addons/mod/data/fields/menu/menu.module.ts index 12a12d4fd..1d0537e0f 100644 --- a/src/addons/mod/data/fields/menu/menu.module.ts +++ b/src/addons/mod/data/fields/menu/menu.module.ts @@ -29,8 +29,7 @@ import { AddonModDataFieldMenuHandler } from './services/handler'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModDataFieldsDelegate.registerHandler(AddonModDataFieldMenuHandler.instance); }, }, diff --git a/src/addons/mod/data/fields/multimenu/multimenu.module.ts b/src/addons/mod/data/fields/multimenu/multimenu.module.ts index 3ceb09691..92da6d881 100644 --- a/src/addons/mod/data/fields/multimenu/multimenu.module.ts +++ b/src/addons/mod/data/fields/multimenu/multimenu.module.ts @@ -29,8 +29,7 @@ import { AddonModDataFieldMultimenuHandler } from './services/handler'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModDataFieldsDelegate.registerHandler(AddonModDataFieldMultimenuHandler.instance); }, }, diff --git a/src/addons/mod/data/fields/number/number.module.ts b/src/addons/mod/data/fields/number/number.module.ts index 5dd352b23..3ba78d2b6 100644 --- a/src/addons/mod/data/fields/number/number.module.ts +++ b/src/addons/mod/data/fields/number/number.module.ts @@ -29,8 +29,7 @@ import { AddonModDataFieldNumberHandler } from './services/handler'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModDataFieldsDelegate.registerHandler(AddonModDataFieldNumberHandler.instance); }, }, diff --git a/src/addons/mod/data/fields/picture/picture.module.ts b/src/addons/mod/data/fields/picture/picture.module.ts index 86806e2f2..31a352cce 100644 --- a/src/addons/mod/data/fields/picture/picture.module.ts +++ b/src/addons/mod/data/fields/picture/picture.module.ts @@ -29,8 +29,7 @@ import { AddonModDataFieldPictureHandler } from './services/handler'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModDataFieldsDelegate.registerHandler(AddonModDataFieldPictureHandler.instance); }, }, diff --git a/src/addons/mod/data/fields/radiobutton/radiobutton.module.ts b/src/addons/mod/data/fields/radiobutton/radiobutton.module.ts index ab535000c..e44ef5d27 100644 --- a/src/addons/mod/data/fields/radiobutton/radiobutton.module.ts +++ b/src/addons/mod/data/fields/radiobutton/radiobutton.module.ts @@ -29,8 +29,7 @@ import { AddonModDataFieldRadiobuttonHandler } from './services/handler'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModDataFieldsDelegate.registerHandler(AddonModDataFieldRadiobuttonHandler.instance); }, }, diff --git a/src/addons/mod/data/fields/text/text.module.ts b/src/addons/mod/data/fields/text/text.module.ts index 890f6b9c3..d5e4db055 100644 --- a/src/addons/mod/data/fields/text/text.module.ts +++ b/src/addons/mod/data/fields/text/text.module.ts @@ -29,8 +29,7 @@ import { AddonModDataFieldTextHandler } from './services/handler'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModDataFieldsDelegate.registerHandler(AddonModDataFieldTextHandler.instance); }, }, diff --git a/src/addons/mod/data/fields/textarea/textarea.module.ts b/src/addons/mod/data/fields/textarea/textarea.module.ts index 7ee21e9be..0b9a8e73f 100644 --- a/src/addons/mod/data/fields/textarea/textarea.module.ts +++ b/src/addons/mod/data/fields/textarea/textarea.module.ts @@ -31,8 +31,7 @@ import { AddonModDataFieldTextareaHandler } from './services/handler'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModDataFieldsDelegate.registerHandler(AddonModDataFieldTextareaHandler.instance); }, }, diff --git a/src/addons/mod/data/fields/url/url.module.ts b/src/addons/mod/data/fields/url/url.module.ts index 99d8250e5..c0e107890 100644 --- a/src/addons/mod/data/fields/url/url.module.ts +++ b/src/addons/mod/data/fields/url/url.module.ts @@ -29,8 +29,7 @@ import { AddonModDataFieldUrlHandler } from './services/handler'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModDataFieldsDelegate.registerHandler(AddonModDataFieldUrlHandler.instance); }, }, diff --git a/src/addons/mod/feedback/feedback.module.ts b/src/addons/mod/feedback/feedback.module.ts index d502a3afc..1fb74f4d0 100644 --- a/src/addons/mod/feedback/feedback.module.ts +++ b/src/addons/mod/feedback/feedback.module.ts @@ -67,8 +67,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseModuleDelegate.registerHandler(AddonModFeedbackModuleHandler.instance); CoreCourseModulePrefetchDelegate.registerHandler(AddonModFeedbackPrefetchHandler.instance); CoreCronDelegate.register(AddonModFeedbackSyncCronHandler.instance); diff --git a/src/addons/mod/folder/folder.module.ts b/src/addons/mod/folder/folder.module.ts index 77aa6c9cd..1094af764 100644 --- a/src/addons/mod/folder/folder.module.ts +++ b/src/addons/mod/folder/folder.module.ts @@ -49,8 +49,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseModuleDelegate.registerHandler(AddonModFolderModuleHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModFolderIndexLinkHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModFolderListLinkHandler.instance); diff --git a/src/addons/mod/glossary/glossary.module.ts b/src/addons/mod/glossary/glossary.module.ts index ee78aa70c..9a4b09793 100644 --- a/src/addons/mod/glossary/glossary.module.ts +++ b/src/addons/mod/glossary/glossary.module.ts @@ -104,8 +104,7 @@ const courseContentsRoutes: Routes = conditionalRoutes( { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseModuleDelegate.registerHandler(AddonModGlossaryModuleHandler.instance); CoreCourseModulePrefetchDelegate.registerHandler(AddonModGlossaryPrefetchHandler.instance); CoreCronDelegate.register(AddonModGlossarySyncCronHandler.instance); diff --git a/src/addons/mod/h5pactivity/h5pactivity.module.ts b/src/addons/mod/h5pactivity/h5pactivity.module.ts index 516b54977..91b81b124 100644 --- a/src/addons/mod/h5pactivity/h5pactivity.module.ts +++ b/src/addons/mod/h5pactivity/h5pactivity.module.ts @@ -50,8 +50,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseModuleDelegate.registerHandler(AddonModH5PActivityModuleHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModH5PActivityIndexLinkHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModH5PActivityReportLinkHandler.instance); diff --git a/src/addons/mod/imscp/imscp.module.ts b/src/addons/mod/imscp/imscp.module.ts index 8684244f8..b94674269 100644 --- a/src/addons/mod/imscp/imscp.module.ts +++ b/src/addons/mod/imscp/imscp.module.ts @@ -47,8 +47,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseModuleDelegate.registerHandler(AddonModImscpModuleHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModImscpIndexLinkHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModImscpListLinkHandler.instance); diff --git a/src/addons/mod/label/label.module.ts b/src/addons/mod/label/label.module.ts index 6c480d851..60e38b5b0 100644 --- a/src/addons/mod/label/label.module.ts +++ b/src/addons/mod/label/label.module.ts @@ -25,8 +25,7 @@ import { AddonModLabelPrefetchHandler } from './services/handlers/prefetch'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseModuleDelegate.registerHandler(AddonModLabelModuleHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModLabelIndexLinkHandler.instance); CoreCourseModulePrefetchDelegate.registerHandler(AddonModLabelPrefetchHandler.instance); diff --git a/src/addons/mod/lesson/lesson.module.ts b/src/addons/mod/lesson/lesson.module.ts index 6ec9fd6e7..6957ca55f 100644 --- a/src/addons/mod/lesson/lesson.module.ts +++ b/src/addons/mod/lesson/lesson.module.ts @@ -65,8 +65,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseModuleDelegate.registerHandler(AddonModLessonModuleHandler.instance); CoreCourseModulePrefetchDelegate.registerHandler(AddonModLessonPrefetchHandler.instance); CoreCronDelegate.register(AddonModLessonSyncCronHandler.instance); diff --git a/src/addons/mod/lti/lti.module.ts b/src/addons/mod/lti/lti.module.ts index 6c6b08390..fef43da2b 100644 --- a/src/addons/mod/lti/lti.module.ts +++ b/src/addons/mod/lti/lti.module.ts @@ -24,7 +24,7 @@ import { AddonModLtiListLinkHandler } from './services/handlers/list-link'; import { AddonModLtiModuleHandler, AddonModLtiModuleHandlerService } from './services/handlers/module'; import { AddonModLtiPrefetchHandler } from './services/handlers/prefetch'; import { AddonModLtiProvider } from './services/lti'; -import { AddonModLtiHelperProvider } from './services/lti-helper'; +import { AddonModLtiHelper, AddonModLtiHelperProvider } from './services/lti-helper'; export const ADDON_MOD_LTI_SERVICES: Type[] = [ AddonModLtiProvider, @@ -47,12 +47,13 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseModuleDelegate.registerHandler(AddonModLtiModuleHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModLtiIndexLinkHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModLtiListLinkHandler.instance); CoreCourseModulePrefetchDelegate.registerHandler(AddonModLtiPrefetchHandler.instance); + + AddonModLtiHelper.watchPendingCompletions(); }, }, ], diff --git a/src/addons/mod/lti/services/lti-helper.ts b/src/addons/mod/lti/services/lti-helper.ts index 905252c24..ae3d56fda 100644 --- a/src/addons/mod/lti/services/lti-helper.ts +++ b/src/addons/mod/lti/services/lti-helper.ts @@ -31,6 +31,13 @@ export class AddonModLtiHelperProvider { protected pendingCheckCompletion: {[moduleId: string]: {courseId: number; module: CoreCourseModule}} = {}; constructor() { + // Clear pending completion on logout. + CoreEvents.on(CoreEvents.LOGOUT, () => { + this.pendingCheckCompletion = {}; + }); + } + + watchPendingCompletions(): void { Platform.resume.subscribe(() => { // User went back to the app, check pending completions. for (const moduleId in this.pendingCheckCompletion) { @@ -39,11 +46,6 @@ export class AddonModLtiHelperProvider { CoreCourse.checkModuleCompletion(data.courseId, data.module.completiondata); } }); - - // Clear pending completion on logout. - CoreEvents.on(CoreEvents.LOGOUT, () => { - this.pendingCheckCompletion = {}; - }); } /** diff --git a/src/addons/mod/page/page.module.ts b/src/addons/mod/page/page.module.ts index 10bf39c71..0eac77a47 100644 --- a/src/addons/mod/page/page.module.ts +++ b/src/addons/mod/page/page.module.ts @@ -49,8 +49,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseModuleDelegate.registerHandler(AddonModPageModuleHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModPageIndexLinkHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModPageListLinkHandler.instance); diff --git a/src/addons/mod/quiz/accessrules/delaybetweenattempts/delaybetweenattempts.module.ts b/src/addons/mod/quiz/accessrules/delaybetweenattempts/delaybetweenattempts.module.ts index 6f2b96191..537ce6c92 100644 --- a/src/addons/mod/quiz/accessrules/delaybetweenattempts/delaybetweenattempts.module.ts +++ b/src/addons/mod/quiz/accessrules/delaybetweenattempts/delaybetweenattempts.module.ts @@ -24,8 +24,7 @@ import { AddonModQuizAccessDelayBetweenAttemptsHandler } from './services/handle { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModQuizAccessRuleDelegate.registerHandler(AddonModQuizAccessDelayBetweenAttemptsHandler.instance); }, }, diff --git a/src/addons/mod/quiz/accessrules/ipaddress/ipaddress.module.ts b/src/addons/mod/quiz/accessrules/ipaddress/ipaddress.module.ts index 5f33d6adb..2b0d0e1d5 100644 --- a/src/addons/mod/quiz/accessrules/ipaddress/ipaddress.module.ts +++ b/src/addons/mod/quiz/accessrules/ipaddress/ipaddress.module.ts @@ -24,8 +24,7 @@ import { AddonModQuizAccessIpAddressHandler } from './services/handlers/ipaddres { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModQuizAccessRuleDelegate.registerHandler(AddonModQuizAccessIpAddressHandler.instance); }, }, diff --git a/src/addons/mod/quiz/accessrules/numattempts/numattempts.module.ts b/src/addons/mod/quiz/accessrules/numattempts/numattempts.module.ts index d6774518c..05312de10 100644 --- a/src/addons/mod/quiz/accessrules/numattempts/numattempts.module.ts +++ b/src/addons/mod/quiz/accessrules/numattempts/numattempts.module.ts @@ -24,8 +24,7 @@ import { AddonModQuizAccessNumAttemptsHandler } from './services/handlers/numatt { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModQuizAccessRuleDelegate.registerHandler(AddonModQuizAccessNumAttemptsHandler.instance); }, }, diff --git a/src/addons/mod/quiz/accessrules/offlineattempts/offlineattempts.module.ts b/src/addons/mod/quiz/accessrules/offlineattempts/offlineattempts.module.ts index 9f25e7429..ad07f27f7 100644 --- a/src/addons/mod/quiz/accessrules/offlineattempts/offlineattempts.module.ts +++ b/src/addons/mod/quiz/accessrules/offlineattempts/offlineattempts.module.ts @@ -30,8 +30,7 @@ import { AddonModQuizAccessOfflineAttemptsHandler } from './services/handlers/of { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModQuizAccessRuleDelegate.registerHandler(AddonModQuizAccessOfflineAttemptsHandler.instance); }, }, diff --git a/src/addons/mod/quiz/accessrules/openclosedate/openclosedate.module.ts b/src/addons/mod/quiz/accessrules/openclosedate/openclosedate.module.ts index 536df6a30..190baa87f 100644 --- a/src/addons/mod/quiz/accessrules/openclosedate/openclosedate.module.ts +++ b/src/addons/mod/quiz/accessrules/openclosedate/openclosedate.module.ts @@ -24,8 +24,7 @@ import { AddonModQuizAccessOpenCloseDateHandler } from './services/handlers/open { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModQuizAccessRuleDelegate.registerHandler(AddonModQuizAccessOpenCloseDateHandler.instance); }, }, diff --git a/src/addons/mod/quiz/accessrules/password/password.module.ts b/src/addons/mod/quiz/accessrules/password/password.module.ts index aa86a43a4..58570654b 100644 --- a/src/addons/mod/quiz/accessrules/password/password.module.ts +++ b/src/addons/mod/quiz/accessrules/password/password.module.ts @@ -37,8 +37,7 @@ import { SITE_SCHEMA } from './services/database/password'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModQuizAccessRuleDelegate.registerHandler(AddonModQuizAccessPasswordHandler.instance); }, }, diff --git a/src/addons/mod/quiz/accessrules/safebrowser/safebrowser.module.ts b/src/addons/mod/quiz/accessrules/safebrowser/safebrowser.module.ts index d7762e27d..a4f222365 100644 --- a/src/addons/mod/quiz/accessrules/safebrowser/safebrowser.module.ts +++ b/src/addons/mod/quiz/accessrules/safebrowser/safebrowser.module.ts @@ -24,8 +24,7 @@ import { AddonModQuizAccessSafeBrowserHandler } from './services/handlers/safebr { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModQuizAccessRuleDelegate.registerHandler(AddonModQuizAccessSafeBrowserHandler.instance); }, }, diff --git a/src/addons/mod/quiz/accessrules/securewindow/securewindow.module.ts b/src/addons/mod/quiz/accessrules/securewindow/securewindow.module.ts index 7a8f1da71..b83e8a185 100644 --- a/src/addons/mod/quiz/accessrules/securewindow/securewindow.module.ts +++ b/src/addons/mod/quiz/accessrules/securewindow/securewindow.module.ts @@ -24,8 +24,7 @@ import { AddonModQuizAccessSecureWindowHandler } from './services/handlers/secur { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModQuizAccessRuleDelegate.registerHandler(AddonModQuizAccessSecureWindowHandler.instance); }, }, diff --git a/src/addons/mod/quiz/accessrules/timelimit/timelimit.module.ts b/src/addons/mod/quiz/accessrules/timelimit/timelimit.module.ts index e8d3ac8bf..4fae54f5e 100644 --- a/src/addons/mod/quiz/accessrules/timelimit/timelimit.module.ts +++ b/src/addons/mod/quiz/accessrules/timelimit/timelimit.module.ts @@ -30,8 +30,7 @@ import { AddonModQuizAccessTimeLimitHandler } from './services/handlers/timelimi { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonModQuizAccessRuleDelegate.registerHandler(AddonModQuizAccessTimeLimitHandler.instance); }, }, diff --git a/src/addons/mod/quiz/quiz.module.ts b/src/addons/mod/quiz/quiz.module.ts index 11ecdf0ec..05bad8666 100644 --- a/src/addons/mod/quiz/quiz.module.ts +++ b/src/addons/mod/quiz/quiz.module.ts @@ -69,8 +69,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseModuleDelegate.registerHandler(AddonModQuizModuleHandler.instance); CoreCourseModulePrefetchDelegate.registerHandler(AddonModQuizPrefetchHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModQuizGradeLinkHandler.instance); diff --git a/src/addons/mod/resource/resource.module.ts b/src/addons/mod/resource/resource.module.ts index 3cecc5ec1..5049aa8cd 100644 --- a/src/addons/mod/resource/resource.module.ts +++ b/src/addons/mod/resource/resource.module.ts @@ -47,8 +47,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseModuleDelegate.registerHandler(AddonModResourceModuleHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModResourceIndexLinkHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModResourceListLinkHandler.instance); diff --git a/src/addons/mod/scorm/scorm.module.ts b/src/addons/mod/scorm/scorm.module.ts index f4dc142e6..308f07164 100644 --- a/src/addons/mod/scorm/scorm.module.ts +++ b/src/addons/mod/scorm/scorm.module.ts @@ -63,8 +63,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseModuleDelegate.registerHandler(AddonModScormModuleHandler.instance); CoreCourseModulePrefetchDelegate.registerHandler(AddonModScormPrefetchHandler.instance); CoreCronDelegate.register(AddonModScormSyncCronHandler.instance); diff --git a/src/addons/mod/survey/survey.module.ts b/src/addons/mod/survey/survey.module.ts index 0b00f21ae..6c9716d2b 100644 --- a/src/addons/mod/survey/survey.module.ts +++ b/src/addons/mod/survey/survey.module.ts @@ -61,8 +61,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseModuleDelegate.registerHandler(AddonModSurveyModuleHandler.instance); CoreCourseModulePrefetchDelegate.registerHandler(AddonModSurveyPrefetchHandler.instance); CoreCronDelegate.register(AddonModSurveySyncCronHandler.instance); diff --git a/src/addons/mod/url/url.module.ts b/src/addons/mod/url/url.module.ts index 7a30d7856..e943d15ab 100644 --- a/src/addons/mod/url/url.module.ts +++ b/src/addons/mod/url/url.module.ts @@ -47,8 +47,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseModuleDelegate.registerHandler(AddonModUrlModuleHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModUrlIndexLinkHandler.instance); CoreContentLinksDelegate.registerHandler(AddonModUrlListLinkHandler.instance); diff --git a/src/addons/mod/wiki/wiki.module.ts b/src/addons/mod/wiki/wiki.module.ts index 409c64783..dd63d4c0a 100644 --- a/src/addons/mod/wiki/wiki.module.ts +++ b/src/addons/mod/wiki/wiki.module.ts @@ -63,8 +63,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseModuleDelegate.registerHandler(AddonModWikiModuleHandler.instance); CoreCourseModulePrefetchDelegate.registerHandler(AddonModWikiPrefetchHandler.instance); CoreCronDelegate.register(AddonModWikiSyncCronHandler.instance); diff --git a/src/addons/mod/workshop/assessment/accumulative/accumulative.module.ts b/src/addons/mod/workshop/assessment/accumulative/accumulative.module.ts index 7eaf6ccc4..be3c10dc1 100644 --- a/src/addons/mod/workshop/assessment/accumulative/accumulative.module.ts +++ b/src/addons/mod/workshop/assessment/accumulative/accumulative.module.ts @@ -29,8 +29,7 @@ import { CoreSharedModule } from '@/core/shared.module'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonWorkshopAssessmentStrategyDelegate.registerHandler( AddonModWorkshopAssessmentStrategyAccumulativeHandler.instance, ); diff --git a/src/addons/mod/workshop/assessment/comments/comments.module.ts b/src/addons/mod/workshop/assessment/comments/comments.module.ts index 2ceaf9a5a..cb56fc9cc 100644 --- a/src/addons/mod/workshop/assessment/comments/comments.module.ts +++ b/src/addons/mod/workshop/assessment/comments/comments.module.ts @@ -29,8 +29,7 @@ import { AddonModWorkshopAssessmentStrategyCommentsHandler } from './services/ha { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonWorkshopAssessmentStrategyDelegate.registerHandler( AddonModWorkshopAssessmentStrategyCommentsHandler.instance, ); diff --git a/src/addons/mod/workshop/assessment/numerrors/numerrors.module.ts b/src/addons/mod/workshop/assessment/numerrors/numerrors.module.ts index dab6f1f38..7d2591c2a 100644 --- a/src/addons/mod/workshop/assessment/numerrors/numerrors.module.ts +++ b/src/addons/mod/workshop/assessment/numerrors/numerrors.module.ts @@ -29,8 +29,7 @@ import { AddonModWorkshopAssessmentStrategyNumErrorsHandler } from './services/h { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonWorkshopAssessmentStrategyDelegate.registerHandler( AddonModWorkshopAssessmentStrategyNumErrorsHandler.instance, ); diff --git a/src/addons/mod/workshop/assessment/rubric/rubric.module.ts b/src/addons/mod/workshop/assessment/rubric/rubric.module.ts index 04885352e..26ef01711 100644 --- a/src/addons/mod/workshop/assessment/rubric/rubric.module.ts +++ b/src/addons/mod/workshop/assessment/rubric/rubric.module.ts @@ -29,8 +29,7 @@ import { AddonModWorkshopAssessmentStrategyRubricHandler } from './services/hand { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { AddonWorkshopAssessmentStrategyDelegate.registerHandler( AddonModWorkshopAssessmentStrategyRubricHandler.instance, ); diff --git a/src/addons/mod/workshop/workshop.module.ts b/src/addons/mod/workshop/workshop.module.ts index 1823ec561..28a93fc50 100644 --- a/src/addons/mod/workshop/workshop.module.ts +++ b/src/addons/mod/workshop/workshop.module.ts @@ -65,8 +65,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseModuleDelegate.registerHandler(AddonModWorkshopModuleHandler.instance); CoreCourseModulePrefetchDelegate.registerHandler(AddonModWorkshopPrefetchHandler.instance); CoreCronDelegate.register(AddonModWorkshopSyncCronHandler.instance); diff --git a/src/addons/notes/notes.module.ts b/src/addons/notes/notes.module.ts index e7c9bcef5..5d82c91d1 100644 --- a/src/addons/notes/notes.module.ts +++ b/src/addons/notes/notes.module.ts @@ -58,8 +58,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => async () => { + useValue: () => { CoreUserDelegate.registerHandler(AddonNotesUserHandler.instance); CoreCourseOptionsDelegate.registerHandler(AddonNotesCourseOptionHandler.instance); CoreCronDelegate.register(AddonNotesSyncCronHandler.instance); diff --git a/src/addons/notifications/notifications.module.ts b/src/addons/notifications/notifications.module.ts index 86595e7c3..0f2142d22 100644 --- a/src/addons/notifications/notifications.module.ts +++ b/src/addons/notifications/notifications.module.ts @@ -58,8 +58,7 @@ const preferencesRoutes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreMainMenuDelegate.registerHandler(AddonNotificationsMainMenuHandler.instance); CoreCronDelegate.register(AddonNotificationsCronHandler.instance); CorePushNotificationsDelegate.registerClickHandler(AddonNotificationsPushClickHandler.instance); diff --git a/src/addons/privatefiles/privatefiles.module.ts b/src/addons/privatefiles/privatefiles.module.ts index 48806c006..ca91c9d3f 100644 --- a/src/addons/privatefiles/privatefiles.module.ts +++ b/src/addons/privatefiles/privatefiles.module.ts @@ -44,8 +44,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreMainMenuDelegate.registerHandler(AddonPrivateFilesMainMenuHandler.instance); }, }, diff --git a/src/addons/qbehaviour/adaptive/adaptive.module.ts b/src/addons/qbehaviour/adaptive/adaptive.module.ts index f0d6b50b8..01d6f8a6f 100644 --- a/src/addons/qbehaviour/adaptive/adaptive.module.ts +++ b/src/addons/qbehaviour/adaptive/adaptive.module.ts @@ -23,8 +23,7 @@ import { AddonQbehaviourAdaptiveHandler } from './services/handlers/adaptive'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionBehaviourDelegate.registerHandler(AddonQbehaviourAdaptiveHandler.instance); }, }, diff --git a/src/addons/qbehaviour/adaptivenopenalty/adaptivenopenalty.module.ts b/src/addons/qbehaviour/adaptivenopenalty/adaptivenopenalty.module.ts index 521c2139f..6b29f6da9 100644 --- a/src/addons/qbehaviour/adaptivenopenalty/adaptivenopenalty.module.ts +++ b/src/addons/qbehaviour/adaptivenopenalty/adaptivenopenalty.module.ts @@ -24,8 +24,7 @@ import { AddonQbehaviourAdaptiveNoPenaltyHandler } from './services/handlers/ada { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionBehaviourDelegate.registerHandler(AddonQbehaviourAdaptiveNoPenaltyHandler.instance); }, }, diff --git a/src/addons/qbehaviour/deferredcbm/deferredcbm.module.ts b/src/addons/qbehaviour/deferredcbm/deferredcbm.module.ts index 94e8e2c1c..9606c4c63 100644 --- a/src/addons/qbehaviour/deferredcbm/deferredcbm.module.ts +++ b/src/addons/qbehaviour/deferredcbm/deferredcbm.module.ts @@ -30,8 +30,7 @@ import { AddonQbehaviourDeferredCBMHandler } from './services/handlers/deferredc { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionBehaviourDelegate.registerHandler(AddonQbehaviourDeferredCBMHandler.instance); }, }, diff --git a/src/addons/qbehaviour/deferredfeedback/deferredfeedback.module.ts b/src/addons/qbehaviour/deferredfeedback/deferredfeedback.module.ts index 8ec75de4a..6c516d394 100644 --- a/src/addons/qbehaviour/deferredfeedback/deferredfeedback.module.ts +++ b/src/addons/qbehaviour/deferredfeedback/deferredfeedback.module.ts @@ -23,8 +23,7 @@ import { AddonQbehaviourDeferredFeedbackHandler } from './services/handlers/defe { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionBehaviourDelegate.registerHandler(AddonQbehaviourDeferredFeedbackHandler.instance); }, }, diff --git a/src/addons/qbehaviour/immediatecbm/immediatecbm.module.ts b/src/addons/qbehaviour/immediatecbm/immediatecbm.module.ts index c5bc7d5a9..1717db79b 100644 --- a/src/addons/qbehaviour/immediatecbm/immediatecbm.module.ts +++ b/src/addons/qbehaviour/immediatecbm/immediatecbm.module.ts @@ -24,8 +24,7 @@ import { AddonQbehaviourImmediateCBMHandler } from './services/handlers/immediat { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionBehaviourDelegate.registerHandler(AddonQbehaviourImmediateCBMHandler.instance); }, }, diff --git a/src/addons/qbehaviour/immediatefeedback/immediatefeedback.module.ts b/src/addons/qbehaviour/immediatefeedback/immediatefeedback.module.ts index 99e137d95..33191c7cc 100644 --- a/src/addons/qbehaviour/immediatefeedback/immediatefeedback.module.ts +++ b/src/addons/qbehaviour/immediatefeedback/immediatefeedback.module.ts @@ -24,8 +24,7 @@ import { AddonQbehaviourImmediateFeedbackHandler } from './services/handlers/imm { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionBehaviourDelegate.registerHandler(AddonQbehaviourImmediateFeedbackHandler.instance); }, }, diff --git a/src/addons/qbehaviour/informationitem/informationitem.module.ts b/src/addons/qbehaviour/informationitem/informationitem.module.ts index c72b94676..3c465a4df 100644 --- a/src/addons/qbehaviour/informationitem/informationitem.module.ts +++ b/src/addons/qbehaviour/informationitem/informationitem.module.ts @@ -30,8 +30,7 @@ import { AddonQbehaviourInformationItemHandler } from './services/handlers/infor { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionBehaviourDelegate.registerHandler(AddonQbehaviourInformationItemHandler.instance); }, }, diff --git a/src/addons/qbehaviour/interactive/interactive.module.ts b/src/addons/qbehaviour/interactive/interactive.module.ts index 421f6ab4e..5f258023f 100644 --- a/src/addons/qbehaviour/interactive/interactive.module.ts +++ b/src/addons/qbehaviour/interactive/interactive.module.ts @@ -24,8 +24,7 @@ import { AddonQbehaviourInteractiveHandler } from './services/handlers/interacti { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionBehaviourDelegate.registerHandler(AddonQbehaviourInteractiveHandler.instance); }, }, diff --git a/src/addons/qbehaviour/interactivecountback/interactivecountback.module.ts b/src/addons/qbehaviour/interactivecountback/interactivecountback.module.ts index 161b1c5a1..461bfb633 100644 --- a/src/addons/qbehaviour/interactivecountback/interactivecountback.module.ts +++ b/src/addons/qbehaviour/interactivecountback/interactivecountback.module.ts @@ -24,8 +24,7 @@ import { AddonQbehaviourInteractiveCountbackHandler } from './services/handlers/ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionBehaviourDelegate.registerHandler(AddonQbehaviourInteractiveCountbackHandler.instance); }, }, diff --git a/src/addons/qbehaviour/manualgraded/manualgraded.module.ts b/src/addons/qbehaviour/manualgraded/manualgraded.module.ts index 45582465f..d8216f028 100644 --- a/src/addons/qbehaviour/manualgraded/manualgraded.module.ts +++ b/src/addons/qbehaviour/manualgraded/manualgraded.module.ts @@ -24,8 +24,7 @@ import { AddonQbehaviourManualGradedHandler } from './services/handlers/manualgr { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionBehaviourDelegate.registerHandler(AddonQbehaviourManualGradedHandler.instance); }, }, diff --git a/src/addons/qtype/calculated/calculated.module.ts b/src/addons/qtype/calculated/calculated.module.ts index d140819ab..73b7a5a3f 100644 --- a/src/addons/qtype/calculated/calculated.module.ts +++ b/src/addons/qtype/calculated/calculated.module.ts @@ -30,8 +30,7 @@ import { AddonQtypeCalculatedHandler } from './services/handlers/calculated'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionDelegate.registerHandler(AddonQtypeCalculatedHandler.instance); }, }, diff --git a/src/addons/qtype/calculatedmulti/calculatedmulti.module.ts b/src/addons/qtype/calculatedmulti/calculatedmulti.module.ts index cbe7d1829..4dd42bd1e 100644 --- a/src/addons/qtype/calculatedmulti/calculatedmulti.module.ts +++ b/src/addons/qtype/calculatedmulti/calculatedmulti.module.ts @@ -24,8 +24,7 @@ import { AddonQtypeCalculatedMultiHandler } from './services/handlers/calculated { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionDelegate.registerHandler(AddonQtypeCalculatedMultiHandler.instance); }, }, diff --git a/src/addons/qtype/calculatedsimple/calculatedsimple.module.ts b/src/addons/qtype/calculatedsimple/calculatedsimple.module.ts index 9a7b52b18..46f250724 100644 --- a/src/addons/qtype/calculatedsimple/calculatedsimple.module.ts +++ b/src/addons/qtype/calculatedsimple/calculatedsimple.module.ts @@ -24,8 +24,7 @@ import { AddonQtypeCalculatedSimpleHandler } from './services/handlers/calculate { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionDelegate.registerHandler(AddonQtypeCalculatedSimpleHandler.instance); }, }, diff --git a/src/addons/qtype/ddimageortext/ddimageortext.module.ts b/src/addons/qtype/ddimageortext/ddimageortext.module.ts index 68ad009b1..392a181c3 100644 --- a/src/addons/qtype/ddimageortext/ddimageortext.module.ts +++ b/src/addons/qtype/ddimageortext/ddimageortext.module.ts @@ -30,8 +30,7 @@ import { AddonQtypeDdImageOrTextHandler } from './services/handlers/ddimageortex { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionDelegate.registerHandler(AddonQtypeDdImageOrTextHandler.instance); }, }, diff --git a/src/addons/qtype/ddmarker/ddmarker.module.ts b/src/addons/qtype/ddmarker/ddmarker.module.ts index 6ec64137e..0dee46686 100644 --- a/src/addons/qtype/ddmarker/ddmarker.module.ts +++ b/src/addons/qtype/ddmarker/ddmarker.module.ts @@ -30,8 +30,7 @@ import { AddonQtypeDdMarkerHandler } from './services/handlers/ddmarker'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionDelegate.registerHandler(AddonQtypeDdMarkerHandler.instance); }, }, diff --git a/src/addons/qtype/ddwtos/ddwtos.module.ts b/src/addons/qtype/ddwtos/ddwtos.module.ts index 33563da45..ed923dea9 100644 --- a/src/addons/qtype/ddwtos/ddwtos.module.ts +++ b/src/addons/qtype/ddwtos/ddwtos.module.ts @@ -30,8 +30,7 @@ import { AddonQtypeDdwtosHandler } from './services/handlers/ddwtos'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionDelegate.registerHandler(AddonQtypeDdwtosHandler.instance); }, }, diff --git a/src/addons/qtype/description/description.module.ts b/src/addons/qtype/description/description.module.ts index 198e4f89e..d580e9d59 100644 --- a/src/addons/qtype/description/description.module.ts +++ b/src/addons/qtype/description/description.module.ts @@ -30,8 +30,7 @@ import { AddonQtypeDescriptionHandler } from './services/handlers/description'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionDelegate.registerHandler(AddonQtypeDescriptionHandler.instance); }, }, diff --git a/src/addons/qtype/essay/essay.module.ts b/src/addons/qtype/essay/essay.module.ts index 3d18fb67b..390479bbf 100644 --- a/src/addons/qtype/essay/essay.module.ts +++ b/src/addons/qtype/essay/essay.module.ts @@ -32,8 +32,7 @@ import { AddonQtypeEssayComponent } from './component/essay'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionDelegate.registerHandler(AddonQtypeEssayHandler.instance); }, }, diff --git a/src/addons/qtype/gapselect/gapselect.module.ts b/src/addons/qtype/gapselect/gapselect.module.ts index 15f730e4f..badb30c4f 100644 --- a/src/addons/qtype/gapselect/gapselect.module.ts +++ b/src/addons/qtype/gapselect/gapselect.module.ts @@ -30,8 +30,7 @@ import { AddonQtypeGapSelectHandler } from './services/handlers/gapselect'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionDelegate.registerHandler(AddonQtypeGapSelectHandler.instance); }, }, diff --git a/src/addons/qtype/match/match.module.ts b/src/addons/qtype/match/match.module.ts index b52672cc2..0df4636e5 100644 --- a/src/addons/qtype/match/match.module.ts +++ b/src/addons/qtype/match/match.module.ts @@ -30,8 +30,7 @@ import { AddonQtypeMatchHandler } from './services/handlers/match'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionDelegate.registerHandler(AddonQtypeMatchHandler.instance); }, }, diff --git a/src/addons/qtype/multianswer/multianswer.module.ts b/src/addons/qtype/multianswer/multianswer.module.ts index e5840b65b..9548089b3 100644 --- a/src/addons/qtype/multianswer/multianswer.module.ts +++ b/src/addons/qtype/multianswer/multianswer.module.ts @@ -30,8 +30,7 @@ import { AddonQtypeMultiAnswerHandler } from './services/handlers/multianswer'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionDelegate.registerHandler(AddonQtypeMultiAnswerHandler.instance); }, }, diff --git a/src/addons/qtype/multichoice/multichoice.module.ts b/src/addons/qtype/multichoice/multichoice.module.ts index 43ee32d66..12488668f 100644 --- a/src/addons/qtype/multichoice/multichoice.module.ts +++ b/src/addons/qtype/multichoice/multichoice.module.ts @@ -30,8 +30,7 @@ import { AddonQtypeMultichoiceHandler } from './services/handlers/multichoice'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionDelegate.registerHandler(AddonQtypeMultichoiceHandler.instance); }, }, diff --git a/src/addons/qtype/numerical/numerical.module.ts b/src/addons/qtype/numerical/numerical.module.ts index b2956adb4..f13ba4fbe 100644 --- a/src/addons/qtype/numerical/numerical.module.ts +++ b/src/addons/qtype/numerical/numerical.module.ts @@ -24,8 +24,7 @@ import { AddonQtypeNumericalHandler } from './services/handlers/numerical'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionDelegate.registerHandler(AddonQtypeNumericalHandler.instance); }, }, diff --git a/src/addons/qtype/randomsamatch/randomsamatch.module.ts b/src/addons/qtype/randomsamatch/randomsamatch.module.ts index 59063e97a..877e772a3 100644 --- a/src/addons/qtype/randomsamatch/randomsamatch.module.ts +++ b/src/addons/qtype/randomsamatch/randomsamatch.module.ts @@ -24,8 +24,7 @@ import { AddonQtypeRandomSaMatchHandler } from './services/handlers/randomsamatc { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionDelegate.registerHandler(AddonQtypeRandomSaMatchHandler.instance); }, }, diff --git a/src/addons/qtype/shortanswer/shortanswer.module.ts b/src/addons/qtype/shortanswer/shortanswer.module.ts index 363c237c5..dcadc635e 100644 --- a/src/addons/qtype/shortanswer/shortanswer.module.ts +++ b/src/addons/qtype/shortanswer/shortanswer.module.ts @@ -30,8 +30,7 @@ import { AddonQtypeShortAnswerHandler } from './services/handlers/shortanswer'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionDelegate.registerHandler(AddonQtypeShortAnswerHandler.instance); }, }, diff --git a/src/addons/qtype/truefalse/truefalse.module.ts b/src/addons/qtype/truefalse/truefalse.module.ts index 129857221..83f60d24d 100644 --- a/src/addons/qtype/truefalse/truefalse.module.ts +++ b/src/addons/qtype/truefalse/truefalse.module.ts @@ -24,8 +24,7 @@ import { AddonQtypeTrueFalseHandler } from './services/handlers/truefalse'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreQuestionDelegate.registerHandler(AddonQtypeTrueFalseHandler.instance); }, }, diff --git a/src/addons/remotethemes/remotethemes.module.ts b/src/addons/remotethemes/remotethemes.module.ts index 74666bff4..e7b7d8d1c 100644 --- a/src/addons/remotethemes/remotethemes.module.ts +++ b/src/addons/remotethemes/remotethemes.module.ts @@ -21,8 +21,7 @@ import { AddonRemoteThemesHandler } from './services/remotethemes-handler'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => async () => { + useValue: () => { CoreStyles.registerStyleHandler(AddonRemoteThemesHandler.instance); }, }, diff --git a/src/addons/storagemanager/storagemanager.module.ts b/src/addons/storagemanager/storagemanager.module.ts index 57c30cab2..2a32b1c19 100644 --- a/src/addons/storagemanager/storagemanager.module.ts +++ b/src/addons/storagemanager/storagemanager.module.ts @@ -36,8 +36,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => async () => { + useValue: () => { CoreCourseOptionsDelegate.registerHandler(AddonStorageManagerCourseMenuHandler.instance); }, }, diff --git a/src/addons/userprofilefield/checkbox/checkbox.module.ts b/src/addons/userprofilefield/checkbox/checkbox.module.ts index 9f163b4c2..92e44c431 100644 --- a/src/addons/userprofilefield/checkbox/checkbox.module.ts +++ b/src/addons/userprofilefield/checkbox/checkbox.module.ts @@ -30,9 +30,9 @@ import { CoreSharedModule } from '@/core/shared.module'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => - CoreUserProfileFieldDelegate.registerHandler(AddonUserProfileFieldCheckboxHandler.instance), + useValue: () => { + CoreUserProfileFieldDelegate.registerHandler(AddonUserProfileFieldCheckboxHandler.instance); + }, }, ], exports: [ diff --git a/src/addons/userprofilefield/datetime/datetime.module.ts b/src/addons/userprofilefield/datetime/datetime.module.ts index a70a4da0b..4c3fe5783 100644 --- a/src/addons/userprofilefield/datetime/datetime.module.ts +++ b/src/addons/userprofilefield/datetime/datetime.module.ts @@ -30,9 +30,9 @@ import { CoreSharedModule } from '@/core/shared.module'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => - CoreUserProfileFieldDelegate.registerHandler(AddonUserProfileFieldDatetimeHandler.instance), + useValue: () => { + CoreUserProfileFieldDelegate.registerHandler(AddonUserProfileFieldDatetimeHandler.instance); + }, }, ], exports: [ diff --git a/src/addons/userprofilefield/menu/menu.module.ts b/src/addons/userprofilefield/menu/menu.module.ts index 62aae65da..e2fa301c6 100644 --- a/src/addons/userprofilefield/menu/menu.module.ts +++ b/src/addons/userprofilefield/menu/menu.module.ts @@ -30,9 +30,9 @@ import { CoreSharedModule } from '@/core/shared.module'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => - CoreUserProfileFieldDelegate.registerHandler(AddonUserProfileFieldMenuHandler.instance), + useValue: () => { + CoreUserProfileFieldDelegate.registerHandler(AddonUserProfileFieldMenuHandler.instance); + }, }, ], exports: [ diff --git a/src/addons/userprofilefield/text/text.module.ts b/src/addons/userprofilefield/text/text.module.ts index 83131dfe0..812f24cee 100644 --- a/src/addons/userprofilefield/text/text.module.ts +++ b/src/addons/userprofilefield/text/text.module.ts @@ -30,9 +30,9 @@ import { CoreSharedModule } from '@/core/shared.module'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => - CoreUserProfileFieldDelegate.registerHandler(AddonUserProfileFieldTextHandler.instance), + useValue: () => { + CoreUserProfileFieldDelegate.registerHandler(AddonUserProfileFieldTextHandler.instance); + }, }, ], exports: [ diff --git a/src/addons/userprofilefield/textarea/textarea.module.ts b/src/addons/userprofilefield/textarea/textarea.module.ts index 579b284ff..f2a29d40d 100644 --- a/src/addons/userprofilefield/textarea/textarea.module.ts +++ b/src/addons/userprofilefield/textarea/textarea.module.ts @@ -32,9 +32,9 @@ import { CoreEditorComponentsModule } from '@features/editor/components/componen { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => - CoreUserProfileFieldDelegate.registerHandler(AddonUserProfileFieldTextareaHandler.instance), + useValue: () => { + CoreUserProfileFieldDelegate.registerHandler(AddonUserProfileFieldTextareaHandler.instance); + }, }, ], exports: [ diff --git a/src/app/app.component.test.ts b/src/app/app.component.test.ts index e815b64bd..ca22b6277 100644 --- a/src/app/app.component.test.ts +++ b/src/app/app.component.test.ts @@ -12,17 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Observable, Subject } from 'rxjs'; - import { AppComponent } from '@/app/app.component'; -import { CoreApp } from '@services/app'; import { CoreEvents } from '@singletons/events'; import { CoreLang, CoreLangProvider } from '@services/lang'; -import { Network, Platform, NgZone } from '@singletons'; import { mockSingleton, renderComponent } from '@/testing/utils'; import { CoreNavigator, CoreNavigatorService } from '@services/navigator'; -import { CoreSitePlugins } from '@features/siteplugins/services/siteplugins'; describe('AppComponent', () => { @@ -30,12 +25,6 @@ describe('AppComponent', () => { let navigator: CoreNavigatorService; beforeEach(() => { - mockSingleton(CoreApp, { setStatusBarColor: jest.fn() }); - mockSingleton(Network, { onChange: () => new Observable() }); - mockSingleton(Platform, { ready: () => Promise.resolve(), resume: new Subject() }); - mockSingleton(NgZone, { run: jest.fn() }); - mockSingleton(CoreSitePlugins, { hasSitePluginsLoaded: false }); - navigator = mockSingleton(CoreNavigator, ['navigate']); langProvider = mockSingleton(CoreLang, ['clearCustomStrings']); }); diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 730c31f6e..555132d45 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -51,7 +51,7 @@ export function createTranslateLoader(http: HttpClient): TranslateHttpLoader { TranslateModule.forRoot({ loader: { provide: TranslateLoader, - useFactory: (createTranslateLoader), + useFactory: createTranslateLoader, deps: [HttpClient], }, }), @@ -66,8 +66,7 @@ export function createTranslateLoader(http: HttpClient): TranslateHttpLoader { { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCronDelegate.register(CoreSiteInfoCronHandler.instance); }, }, diff --git a/src/core/components/iframe/iframe.ts b/src/core/components/iframe/iframe.ts index 3afcd69a2..48ee9a60c 100644 --- a/src/core/components/iframe/iframe.ts +++ b/src/core/components/iframe/iframe.ts @@ -32,6 +32,8 @@ import { DomSanitizer } from '@singletons'; }) export class CoreIframeComponent implements OnChanges { + static loadingTimeout = 15000; + @ViewChild('iframe') iframe?: ElementRef; @Input() src?: string; @Input() iframeWidth?: string; @@ -43,7 +45,6 @@ export class CoreIframeComponent implements OnChanges { safeUrl?: SafeResourceUrl; displayHelp = false; - protected readonly IFRAME_TIMEOUT = 15000; protected logger: CoreLogger; protected initialized = false; @@ -89,7 +90,7 @@ export class CoreIframeComponent implements OnChanges { if (this.loading) { setTimeout(() => { this.loading = false; - }, this.IFRAME_TIMEOUT); + }, CoreIframeComponent.loadingTimeout); } } diff --git a/src/core/components/tests/iframe.test.ts b/src/core/components/tests/iframe.test.ts index 2b80c90c3..75a0c754d 100644 --- a/src/core/components/tests/iframe.test.ts +++ b/src/core/components/tests/iframe.test.ts @@ -12,8 +12,28 @@ // See the License for the specific language governing permissions and // limitations under the License. +import { CoreIframeComponent } from '@components/iframe/iframe'; + +import { renderTemplate } from '@/testing/utils'; + describe('CoreIframeComponent', () => { - it.todo('should render'); + it('should render', async () => { + // Arrange. + CoreIframeComponent.loadingTimeout = 0; + + // Act. + const { nativeElement } = await renderTemplate( + CoreIframeComponent, + '', + ); + + // Assert. + expect(nativeElement.innerHTML.trim()).not.toHaveLength(0); + + const iframe = nativeElement.querySelector('iframe'); + expect(iframe).not.toBeNull(); + expect(iframe.src).toEqual('https://moodle.org/'); + }); }); diff --git a/src/core/components/tests/user-avatar.test.ts b/src/core/components/tests/user-avatar.test.ts index a8d933837..7b4c5f12a 100644 --- a/src/core/components/tests/user-avatar.test.ts +++ b/src/core/components/tests/user-avatar.test.ts @@ -12,8 +12,22 @@ // See the License for the specific language governing permissions and // limitations under the License. +import { CoreUserAvatarComponent } from '@components/user-avatar/user-avatar'; + +import { renderComponent } from '@/testing/utils'; + describe('CoreUserAvatarComponent', () => { - it.todo('should render'); + it('should render', async () => { + // Act. + const { nativeElement } = await renderComponent(CoreUserAvatarComponent); + + // Assert. + expect(nativeElement.innerHTML.trim()).not.toHaveLength(0); + + const image = nativeElement.querySelector('img'); + expect(image).not.toBeNull(); + expect(image.src).toEqual(document.location.href + 'assets/img/user-avatar.png'); + }); }); diff --git a/src/core/directives/tests/format-text.test.ts b/src/core/directives/tests/format-text.test.ts index 3bfc5afa8..aea7a5ded 100644 --- a/src/core/directives/tests/format-text.test.ts +++ b/src/core/directives/tests/format-text.test.ts @@ -13,34 +13,29 @@ // limitations under the License. import { IonContent } from '@ionic/angular'; -import { NgZone } from '@angular/core'; import Faker from 'faker'; import { CoreConfig } from '@services/config'; -import { CoreDomUtils, CoreDomUtilsProvider } from '@services/utils/dom'; +import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper'; import { CoreFilepool } from '@services/filepool'; +import { CoreFilter } from '@features/filter/services/filter'; +import { CoreFilterHelper } from '@features/filter/services/filter-helper'; import { CoreFormatTextDirective } from '@directives/format-text'; import { CoreSite } from '@classes/site'; import { CoreSites } from '@services/sites'; -import { CoreUrlUtils, CoreUrlUtilsProvider } from '@services/utils/url'; -import { CoreUtils, CoreUtilsProvider } from '@services/utils/utils'; -import { Platform } from '@singletons'; +import { CoreUtils } from '@services/utils/utils'; -import { mock, mockSingleton, RenderConfig, renderWrapperComponent } from '@/testing/utils'; -import { CoreFilter } from '@features/filter/services/filter'; -import { CoreApp } from '@services/app'; +import { mock, mockSingleton, RenderConfig, renderTemplate, renderWrapperComponent } from '@/testing/utils'; describe('CoreFormatTextDirective', () => { let config: Partial; beforeEach(() => { - mockSingleton(Platform, { ready: () => Promise.resolve() }); + mockSingleton(CoreSites, { getSite: () => Promise.reject() }); mockSingleton(CoreConfig, { get: (_, defaultValue) => defaultValue }); - - CoreDomUtils.setInstance(new CoreDomUtilsProvider()); - CoreUrlUtils.setInstance(new CoreUrlUtilsProvider()); - CoreUtils.setInstance(new CoreUtilsProvider(mock())); + mockSingleton(CoreFilter, { formatText: text => Promise.resolve(text) }); + mockSingleton(CoreFilterHelper, { getFiltersAndFormatText: text => Promise.resolve({ text, filters: [] }) }); config = { providers: [ @@ -53,9 +48,6 @@ describe('CoreFormatTextDirective', () => { // Arrange const sentence = Faker.lorem.sentence(); - mockSingleton(CoreSites, { getSite: () => Promise.reject() }); - mockSingleton(CoreFilter, { formatText: (text) => Promise.resolve(text) }); - // Act const fixture = await renderWrapperComponent( CoreFormatTextDirective, @@ -70,6 +62,63 @@ describe('CoreFormatTextDirective', () => { expect(text.innerHTML).toEqual(sentence); }); + it('should format text', async () => { + // Arrange + mockSingleton(CoreFilter, { formatText: () => 'Formatted text' }); + + // Act + const { nativeElement } = await renderTemplate( + CoreFormatTextDirective, + '', + ); + + // Assert + const text = nativeElement.querySelector('core-format-text'); + expect(text).not.toBeNull(); + expect(text.textContent).toEqual('Formatted text'); + + expect(CoreFilter.formatText).toHaveBeenCalledTimes(1); + expect(CoreFilter.formatText).toHaveBeenCalledWith( + 'Lorem ipsum dolor', + expect.anything(), + expect.anything(), + undefined, + ); + }); + + it('should get filters from server and format text', async () => { + // Arrange + mockSingleton(CoreFilterHelper, { + getFiltersAndFormatText: () => Promise.resolve({ + text: 'Formatted text', + filters: [], + }), + }); + + // Act + const { nativeElement } = await renderTemplate(CoreFormatTextDirective, ` + + `); + + // Assert + const text = nativeElement.querySelector('core-format-text'); + expect(text).not.toBeNull(); + expect(text.textContent).toEqual('Formatted text'); + + expect(CoreFilterHelper.getFiltersAndFormatText).toHaveBeenCalledTimes(1); + expect(CoreFilterHelper.getFiltersAndFormatText).toHaveBeenCalledWith( + 'Lorem ipsum dolor', + 'course', + 42, + expect.anything(), + undefined, + ); + }); + it('should use external-content directive on images', async () => { // Arrange const site = mock({ @@ -86,11 +135,9 @@ describe('CoreFormatTextDirective', () => { getSite: () => Promise.resolve(site), getCurrentSite: () => Promise.resolve(site), }); - mockSingleton(CoreFilter, { formatText: (text) => Promise.resolve(text) }); - mockSingleton(CoreApp, { isMobile: () => false }); // Act - const fixture = await renderWrapperComponent( + const { nativeElement } = await renderWrapperComponent( CoreFormatTextDirective, 'core-format-text', { text: '', siteId: site.getId() }, @@ -98,7 +145,7 @@ describe('CoreFormatTextDirective', () => { ); // Assert - const image = fixture.nativeElement.querySelector('img'); + const image = nativeElement.querySelector('img'); expect(image).not.toBeNull(); expect(image.src).toEqual('file://local-path/'); @@ -106,10 +153,28 @@ describe('CoreFormatTextDirective', () => { expect(CoreFilepool.getSrcByUrl).toHaveBeenCalledTimes(1); }); - it.todo('should format text'); + it('should use link directive on anchors', async () => { + // Arrange + mockSingleton(CoreContentLinksHelper, { handleLink: () => Promise.resolve(true) }); - it.todo('should get filters from server and format text'); + // Act + const { nativeElement } = await renderWrapperComponent( + CoreFormatTextDirective, + 'core-format-text', + { text: 'Link' }, + ); + const anchor = nativeElement.querySelector('a'); - it.todo('should use link directive on anchors'); + anchor.click(); + + // Assert + expect(CoreContentLinksHelper.handleLink).toHaveBeenCalledTimes(1); + expect(CoreContentLinksHelper.handleLink).toHaveBeenCalledWith( + 'https://anchor-url/', + undefined, + expect.anything(), + expect.anything(), + ); + }); }); diff --git a/src/core/directives/tests/link.test.ts b/src/core/directives/tests/link.test.ts index 00bdbab0f..891df6111 100644 --- a/src/core/directives/tests/link.test.ts +++ b/src/core/directives/tests/link.test.ts @@ -13,8 +13,9 @@ // limitations under the License. import { CoreLinkDirective } from '@directives/link'; +import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper'; -import { renderTemplate } from '@/testing/utils'; +import { mockSingleton, renderTemplate } from '@/testing/utils'; describe('CoreLinkDirective', () => { @@ -33,6 +34,28 @@ describe('CoreLinkDirective', () => { expect(anchor.href).toEqual('https://moodle.org/'); }); - it.todo('should capture clicks'); + it('should capture clicks', async () => { + // Arrange + mockSingleton(CoreContentLinksHelper, { handleLink: () => Promise.resolve(true) }); + + // Act + const { nativeElement } = await renderTemplate( + CoreLinkDirective, + 'Link', + ); + + const anchor = nativeElement.querySelector('a'); + + anchor.click(); + + // Assert + expect(CoreContentLinksHelper.handleLink).toHaveBeenCalledTimes(1); + expect(CoreContentLinksHelper.handleLink).toHaveBeenCalledWith( + 'https://moodle.org/', + undefined, + expect.anything(), + expect.anything(), + ); + }); }); diff --git a/src/core/features/course/course.module.ts b/src/core/features/course/course.module.ts index 3e56ecb0c..906b0df92 100644 --- a/src/core/features/course/course.module.ts +++ b/src/core/features/course/course.module.ts @@ -90,8 +90,7 @@ const courseIndexRoutes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCronDelegate.register(CoreCourseSyncCronHandler.instance); CoreCronDelegate.register(CoreCourseLogCronHandler.instance); CoreTagAreaDelegate.registerHandler(CoreCourseTagAreaHandler.instance); diff --git a/src/core/features/course/format/singleactivity/singleactivity.module.ts b/src/core/features/course/format/singleactivity/singleactivity.module.ts index 8db7ae9f3..c42f04b27 100644 --- a/src/core/features/course/format/singleactivity/singleactivity.module.ts +++ b/src/core/features/course/format/singleactivity/singleactivity.module.ts @@ -30,8 +30,7 @@ import { CoreCourseFormatSingleActivityHandler } from './services/handlers/singl { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseFormatDelegate.registerHandler(CoreCourseFormatSingleActivityHandler.instance); }, }, diff --git a/src/core/features/course/format/social/social.module.ts b/src/core/features/course/format/social/social.module.ts index 16f1379c6..1278c67df 100644 --- a/src/core/features/course/format/social/social.module.ts +++ b/src/core/features/course/format/social/social.module.ts @@ -22,8 +22,7 @@ import { CoreCourseFormatSocialHandler } from './services/handlers/social-format { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseFormatDelegate.registerHandler(CoreCourseFormatSocialHandler.instance); }, }, diff --git a/src/core/features/course/format/topics/topics.module.ts b/src/core/features/course/format/topics/topics.module.ts index 3a7594aa7..8cca95c71 100644 --- a/src/core/features/course/format/topics/topics.module.ts +++ b/src/core/features/course/format/topics/topics.module.ts @@ -22,8 +22,7 @@ import { CoreCourseFormatTopicsHandler } from './services/handlers/topics-format { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseFormatDelegate.registerHandler(CoreCourseFormatTopicsHandler.instance); }, }, diff --git a/src/core/features/course/format/weeks/weeks.module.ts b/src/core/features/course/format/weeks/weeks.module.ts index 491c122e4..7393de0d1 100644 --- a/src/core/features/course/format/weeks/weeks.module.ts +++ b/src/core/features/course/format/weeks/weeks.module.ts @@ -22,8 +22,7 @@ import { CoreCourseFormatWeeksHandler } from './services/handlers/weeks-format'; { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreCourseFormatDelegate.registerHandler(CoreCourseFormatWeeksHandler.instance); }, }, diff --git a/src/core/features/courses/courses.module.ts b/src/core/features/courses/courses.module.ts index 6ca5284b4..b07d4bc2b 100644 --- a/src/core/features/courses/courses.module.ts +++ b/src/core/features/courses/courses.module.ts @@ -66,8 +66,7 @@ const mainMenuHomeSiblingRoutes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreMainMenuHomeDelegate.registerHandler(CoreDashboardHomeHandler.instance); CoreMainMenuHomeDelegate.registerHandler(CoreCoursesMyCoursesHomeHandler.instance); CoreContentLinksDelegate.registerHandler(CoreCoursesCourseLinkHandler.instance); diff --git a/src/core/features/fileuploader/fileuploader.module.ts b/src/core/features/fileuploader/fileuploader.module.ts index 8ca214fe7..c0774617d 100644 --- a/src/core/features/fileuploader/fileuploader.module.ts +++ b/src/core/features/fileuploader/fileuploader.module.ts @@ -34,8 +34,7 @@ export const CORE_FILEUPLOADER_SERVICES: Type[] = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreFileUploaderDelegate.registerHandler(CoreFileUploaderAlbumHandler.instance); CoreFileUploaderDelegate.registerHandler(CoreFileUploaderAudioHandler.instance); CoreFileUploaderDelegate.registerHandler(CoreFileUploaderCameraHandler.instance); diff --git a/src/core/features/grades/grades.module.ts b/src/core/features/grades/grades.module.ts index 2a9c3dbd7..b359d575c 100644 --- a/src/core/features/grades/grades.module.ts +++ b/src/core/features/grades/grades.module.ts @@ -62,7 +62,6 @@ const courseIndexRoutes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], useValue: () => { CoreMainMenuDelegate.registerHandler(CoreGradesMainMenuHandler.instance); CoreUserDelegate.registerHandler(CoreGradesUserHandler.instance); diff --git a/src/core/features/h5p/h5p.module.ts b/src/core/features/h5p/h5p.module.ts index e8be04d82..89b5a494a 100644 --- a/src/core/features/h5p/h5p.module.ts +++ b/src/core/features/h5p/h5p.module.ts @@ -38,8 +38,7 @@ export const CORE_H5P_SERVICES: Type[] = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CorePluginFileDelegate.registerHandler(CoreH5PPluginFileHandler.instance); }, }, diff --git a/src/core/features/login/login.module.ts b/src/core/features/login/login.module.ts index 235541150..caa91ea91 100644 --- a/src/core/features/login/login.module.ts +++ b/src/core/features/login/login.module.ts @@ -40,8 +40,7 @@ const appRoutes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => async () => { + useValue: () => { CoreCronDelegate.register(CoreLoginCronHandler.instance); }, }, diff --git a/src/core/features/mainmenu/mainmenu.module.ts b/src/core/features/mainmenu/mainmenu.module.ts index 0c871de7d..ae4136604 100644 --- a/src/core/features/mainmenu/mainmenu.module.ts +++ b/src/core/features/mainmenu/mainmenu.module.ts @@ -49,8 +49,7 @@ const appRoutes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreMainMenuDelegate.registerHandler(CoreMainMenuHomeHandler.instance); }, }, diff --git a/src/core/features/pushnotifications/pushnotifications.module.ts b/src/core/features/pushnotifications/pushnotifications.module.ts index fac638aa2..b765e6fb8 100644 --- a/src/core/features/pushnotifications/pushnotifications.module.ts +++ b/src/core/features/pushnotifications/pushnotifications.module.ts @@ -41,8 +41,7 @@ export const CORE_PUSHNOTIFICATIONS_SERVICES: Type[] = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => async () => { + useValue: async () => { // Register the handlers. CoreCronDelegate.register(CorePushNotificationsRegisterCronHandler.instance); CoreCronDelegate.register(CorePushNotificationsUnregisterCronHandler.instance); diff --git a/src/core/features/settings/services/settings-helper.ts b/src/core/features/settings/services/settings-helper.ts index 94fddfc40..2d68d2330 100644 --- a/src/core/features/settings/services/settings-helper.ts +++ b/src/core/features/settings/services/settings-helper.ts @@ -65,7 +65,7 @@ export class CoreSettingsHelperProvider { protected colorSchemes: CoreColorScheme[] = []; protected currentColorScheme = CoreColorScheme.LIGHT; - constructor() { + async initialize(): Promise { this.prefersDark = window.matchMedia('(prefers-color-scheme: dark)'); if (!CoreConstants.CONFIG.forceColorScheme) { @@ -94,6 +94,11 @@ export class CoreSettingsHelperProvider { // Listen for changes to the prefers-color-scheme media query. this.prefersDark.addEventListener && this.prefersDark.addEventListener('change', this.toggleDarkModeListener.bind(this)); + + // Init zoom level. + await this.upgradeZoomLevel(); + + this.initDomSettings(); } /** diff --git a/src/core/features/settings/settings.module.ts b/src/core/features/settings/settings.module.ts index 28db5b75b..e94d2072b 100644 --- a/src/core/features/settings/settings.module.ts +++ b/src/core/features/settings/settings.module.ts @@ -17,7 +17,7 @@ import { Routes } from '@angular/router'; import { AppRoutingModule } from '@/app/app-routing.module'; import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module'; -import { CoreSettingsHelperProvider } from './services/settings-helper'; +import { CoreSettingsHelper, CoreSettingsHelperProvider } from './services/settings-helper'; import { CoreSettingsDelegateService } from './services/settings-delegate'; export const CORE_SETTINGS_SERVICES: Type[] = [ @@ -49,15 +49,7 @@ const mainMenuMoreRoutes: Routes = [ CoreMainMenuTabRoutingModule.forChild(mainMenuMoreRoutes), ], providers: [ - { - provide: APP_INITIALIZER, - multi: true, - deps: [CoreSettingsHelperProvider], - useFactory: (helper: CoreSettingsHelperProvider) => async () => { - await helper.upgradeZoomLevel(); - helper.initDomSettings(); - }, - }, + { provide: APP_INITIALIZER, multi: true, useValue: () => CoreSettingsHelper.initialize() }, ], }) export class CoreSettingsModule {} diff --git a/src/core/features/sharedfiles/sharedfiles.module.ts b/src/core/features/sharedfiles/sharedfiles.module.ts index 5d82b264a..409747798 100644 --- a/src/core/features/sharedfiles/sharedfiles.module.ts +++ b/src/core/features/sharedfiles/sharedfiles.module.ts @@ -51,7 +51,7 @@ const routes: Routes = [ { provide: APP_INITIALIZER, multi: true, - useFactory: () => async () => { + useValue: async () => { CoreFileUploaderDelegate.registerHandler(CoreSharedFilesUploadHandler.instance); CoreSettingsDelegate.registerHandler(CoreSharedFilesSettingsHandler.instance); diff --git a/src/core/features/sitehome/sitehome.module.ts b/src/core/features/sitehome/sitehome.module.ts index d77faecd2..40283ba13 100644 --- a/src/core/features/sitehome/sitehome.module.ts +++ b/src/core/features/sitehome/sitehome.module.ts @@ -40,8 +40,7 @@ const mainMenuHomeRoutes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreContentLinksDelegate.registerHandler(CoreSiteHomeIndexLinkHandler.instance); CoreMainMenuHomeDelegate.registerHandler(CoreSiteHomeHomeHandler.instance); }, diff --git a/src/core/features/user/user.module.ts b/src/core/features/user/user.module.ts index 52c1e87ef..75901a66e 100644 --- a/src/core/features/user/user.module.ts +++ b/src/core/features/user/user.module.ts @@ -77,8 +77,7 @@ const courseIndexRoutes: Routes = [ { provide: APP_INITIALIZER, multi: true, - deps: [], - useFactory: () => () => { + useValue: () => { CoreUserDelegate.registerHandler(CoreUserProfileMailHandler.instance); CoreContentLinksDelegate.registerHandler(CoreUserProfileLinkHandler.instance); CoreCronDelegate.register(CoreUserSyncCronHandler.instance); diff --git a/src/core/initializers/initialize-services.ts b/src/core/initializers/initialize-services.ts new file mode 100644 index 000000000..c07eeafff --- /dev/null +++ b/src/core/initializers/initialize-services.ts @@ -0,0 +1,25 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { CoreFilepool } from '@services/filepool'; +import { CoreLang } from '@services/lang'; +import { CoreLocalNotifications } from '@services/local-notifications'; + +export default async function(): Promise { + await Promise.all([ + CoreFilepool.initialize(), + CoreLang.initialize(), + CoreLocalNotifications.initialize(), + ]); +} diff --git a/src/core/initializers/inject-ios-scripts.ts b/src/core/initializers/inject-ios-scripts.ts new file mode 100644 index 000000000..a1a728bb2 --- /dev/null +++ b/src/core/initializers/inject-ios-scripts.ts @@ -0,0 +1,26 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { CoreApp } from '@services/app'; +import { CoreIframeUtils } from '@services/utils/iframe'; +import { Platform } from '@singletons'; + +export default async function(): Promise { + if (!CoreApp.isIOS() || !('WKUserScript' in window)) { + return; + } + + await Platform.ready(); + await CoreIframeUtils.injectiOSScripts(window); +} diff --git a/src/core/initializers/watch-network.ts b/src/core/initializers/watch-network.ts new file mode 100644 index 000000000..ee867a42e --- /dev/null +++ b/src/core/initializers/watch-network.ts @@ -0,0 +1,24 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { CoreCronDelegate } from '@services/cron'; +import { Network, NgZone } from '@singletons'; + +export default function(): void { + // When the app is re-connected, start network handlers that were stopped. + Network.onConnect().subscribe(() => { + // Execute the callback in the Angular zone, so change detection doesn't stop working. + NgZone.run(() => CoreCronDelegate.startNetworkHandlers()); + }); +} diff --git a/src/core/services/app.ts b/src/core/services/app.ts index 96454cc1b..87ec78cd8 100644 --- a/src/core/services/app.ts +++ b/src/core/services/app.ts @@ -50,7 +50,7 @@ type SchemaVersionsManager = { @Injectable({ providedIn: 'root' }) export class CoreAppProvider { - protected db: SQLiteDB; + protected db?: SQLiteDB; protected logger: CoreLogger; protected ssoAuthenticationDeferred?: PromiseDefer; protected isKeyboardShown = false; @@ -65,7 +65,6 @@ export class CoreAppProvider { constructor() { this.schemaVersionsManager = new Promise(resolve => this.resolveSchemaVersionsManager = resolve); - this.db = CoreDB.getDB(DBNAME); this.logger = CoreLogger.getInstance('CoreAppProvider'); } @@ -82,13 +81,13 @@ export class CoreAppProvider { * Initialize database. */ async initializeDatabase(): Promise { - await this.db.createTableFromSchema(SCHEMA_VERSIONS_TABLE_SCHEMA); + await this.getDB().createTableFromSchema(SCHEMA_VERSIONS_TABLE_SCHEMA); this.resolveSchemaVersionsManager({ get: async name => { try { // Fetch installed version of the schema. - const entry = await this.db.getRecord(SCHEMA_VERSIONS_TABLE_NAME, { name }); + const entry = await this.getDB().getRecord(SCHEMA_VERSIONS_TABLE_NAME, { name }); return entry.version; } catch (error) { @@ -97,7 +96,7 @@ export class CoreAppProvider { } }, set: async (name, version) => { - await this.db.insertRecord(SCHEMA_VERSIONS_TABLE_NAME, { name, version }); + await this.getDB().insertRecord(SCHEMA_VERSIONS_TABLE_NAME, { name, version }); }, }); } @@ -149,10 +148,10 @@ export class CoreAppProvider { this.logger.debug(`Migrating schema '${schema.name}' of app DB from version ${oldVersion} to ${schema.version}`); if (schema.tables) { - await this.db.createTablesFromSchema(schema.tables); + await this.getDB().createTablesFromSchema(schema.tables); } if (schema.migrate && oldVersion > 0) { - await schema.migrate(this.db, oldVersion); + await schema.migrate(this.getDB(), oldVersion); } // Set installed version. @@ -165,6 +164,10 @@ export class CoreAppProvider { * @return App's DB. */ getDB(): SQLiteDB { + if (!this.db) { + this.db = CoreDB.getDB(DBNAME); + } + return this.db; } diff --git a/src/core/services/cron.ts b/src/core/services/cron.ts index dd39cd04d..76a043947 100644 --- a/src/core/services/cron.ts +++ b/src/core/services/cron.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Injectable, NgZone } from '@angular/core'; +import { Injectable } from '@angular/core'; import { CoreApp } from '@services/app'; import { CoreConfig } from '@services/config'; @@ -21,7 +21,7 @@ import { CoreConstants } from '@/core/constants'; import { SQLiteDB } from '@classes/sqlitedb'; import { CoreError } from '@classes/errors/error'; -import { makeSingleton, Network } from '@singletons'; +import { makeSingleton } from '@singletons'; import { CoreLogger } from '@singletons/logger'; import { APP_SCHEMA, CRON_TABLE_NAME, CronDBEntry } from '@services/database/cron'; @@ -44,17 +44,9 @@ export class CoreCronDelegateService { protected appDB: Promise; protected resolveAppDB!: (appDB: SQLiteDB) => void; - constructor(zone: NgZone) { + constructor() { this.appDB = new Promise(resolve => this.resolveAppDB = resolve); this.logger = CoreLogger.getInstance('CoreCronDelegate'); - - // When the app is re-connected, start network handlers that were stopped. - Network.onConnect().subscribe(() => { - // Execute the callback in the Angular zone, so change detection doesn't stop working. - zone.run(() => { - this.startNetworkHandlers(); - }); - }); } /** diff --git a/src/core/services/filepool.ts b/src/core/services/filepool.ts index 3cc4c2854..275785a4a 100644 --- a/src/core/services/filepool.ts +++ b/src/core/services/filepool.ts @@ -97,8 +97,24 @@ export class CoreFilepoolProvider { constructor() { this.appDB = new Promise(resolve => this.resolveAppDB = resolve); this.logger = CoreLogger.getInstance('CoreFilepoolProvider'); + } - this.init(); + /** + * Initialize queue. + */ + async initialize(): Promise { + // Waiting for the app to be ready to start processing the queue. + await ApplicationInit.donePromise; + + this.checkQueueProcessing(); + + // Start queue when device goes online. + Network.onConnect().subscribe(() => { + // Execute the callback in the Angular zone, so change detection doesn't stop working. + NgZone.run(() => { + this.checkQueueProcessing(); + }); + }); } /** @@ -114,24 +130,6 @@ export class CoreFilepoolProvider { this.resolveAppDB(CoreApp.getDB()); } - /** - * Init some properties. - */ - protected async init(): Promise { - // Waiting for the app to be ready to start processing the queue. - await ApplicationInit.donePromise; - - this.checkQueueProcessing(); - - // Start queue when device goes online. - Network.onConnect().subscribe(() => { - // Execute the callback in the Angular zone, so change detection doesn't stop working. - NgZone.run(() => { - this.checkQueueProcessing(); - }); - }); - } - /** * Link a file with a component. * diff --git a/src/core/services/lang.ts b/src/core/services/lang.ts index 7d9f54ebe..c14cd0054 100644 --- a/src/core/services/lang.ts +++ b/src/core/services/lang.ts @@ -37,13 +37,11 @@ export class CoreLangProvider { protected customStringsRaw?: string; protected sitePluginsStrings: CoreLanguageObject = {}; // Strings defined by site plugins. - constructor() { + async initialize(): Promise { // Set fallback language and language to use until the app determines the right language to use. Translate.setDefaultLang(this.fallbackLanguage); Translate.use(this.defaultLanguage); - this.initLanguage(); - Translate.onLangChange.subscribe((event: LangChangeEvent) => { document.documentElement.setAttribute('lang', event.lang); @@ -51,12 +49,14 @@ export class CoreLangProvider { dir = dir.indexOf('rtl') != -1 ? 'rtl' : 'ltr'; document.documentElement.setAttribute('dir', dir); }); + + await this.initializeCurrentLanguage(); } /** * Init language. */ - protected async initLanguage(): Promise { + protected async initializeCurrentLanguage(): Promise { await Platform.ready(); let language: string; @@ -68,7 +68,7 @@ export class CoreLangProvider { language = await this.getCurrentLanguage(); } - return this.changeCurrentLanguage(language); + await this.changeCurrentLanguage(language); } /** diff --git a/src/core/services/local-notifications.ts b/src/core/services/local-notifications.ts index df0869718..c6547f8fe 100644 --- a/src/core/services/local-notifications.ts +++ b/src/core/services/local-notifications.ts @@ -62,27 +62,12 @@ export class CoreLocalNotificationsProvider { this.appDB = new Promise(resolve => this.resolveAppDB = resolve); this.logger = CoreLogger.getInstance('CoreLocalNotificationsProvider'); this.queueRunner = new CoreQueueRunner(10); - - this.init(); - } - - /** - * Initialize database. - */ - async initializeDatabase(): Promise { - try { - await CoreApp.createTablesFromSchema(APP_SCHEMA); - } catch (e) { - // Ignore errors. - } - - this.resolveAppDB(CoreApp.getDB()); } /** * Init some properties. */ - protected async init(): Promise { + async initialize(): Promise { await Platform.ready(); if (!this.isAvailable()) { @@ -131,6 +116,19 @@ export class CoreLocalNotificationsProvider { }); } + /** + * Initialize database. + */ + async initializeDatabase(): Promise { + try { + await CoreApp.createTablesFromSchema(APP_SCHEMA); + } catch (e) { + // Ignore errors. + } + + this.resolveAppDB(CoreApp.getDB()); + } + /** * Cancel a local notification. * diff --git a/src/core/services/tests/navigator.test.ts b/src/core/services/tests/navigator.test.ts index d2c3fe25d..a0000b07e 100644 --- a/src/core/services/tests/navigator.test.ts +++ b/src/core/services/tests/navigator.test.ts @@ -14,12 +14,9 @@ import { NavController as NavControllerService } from '@ionic/angular'; -import { mock, mockSingleton } from '@/testing/utils'; +import { mockSingleton } from '@/testing/utils'; import { CoreNavigatorService } from '@services/navigator'; -import { CoreUtils, CoreUtilsProvider } from '@services/utils/utils'; -import { CoreUrlUtils, CoreUrlUtilsProvider } from '@services/utils/url'; -import { CoreTextUtils, CoreTextUtilsProvider } from '@services/utils/text'; import { NavController, Router } from '@singletons'; import { ActivatedRoute, RouterState } from '@angular/router'; import { CoreSites } from '@services/sites'; @@ -36,15 +33,12 @@ describe('CoreNavigator', () => { let navControllerMock: NavControllerService; beforeEach(() => { - router = { url: '/' }; currentMainMenuHandlers = ['home']; navigator = new CoreNavigatorService(); navControllerMock = mockSingleton(NavController, ['navigateRoot', 'navigateForward']); - mockSingleton(Router, router); - mockSingleton(CoreUtils, new CoreUtilsProvider(mock())); - mockSingleton(CoreUrlUtils, new CoreUrlUtilsProvider()); - mockSingleton(CoreTextUtils, new CoreTextUtilsProvider()); + router = mockSingleton(Router, { url: '/' }); + mockSingleton(CoreSites, { getCurrentSiteId: () => 42, isLoggedIn: () => true }); mockSingleton(CoreMainMenu, { isMainMenuTab: path => Promise.resolve(currentMainMenuHandlers.includes(path)) }); }); diff --git a/src/core/services/utils/iframe.ts b/src/core/services/utils/iframe.ts index b9bb6c531..99f6e15bf 100644 --- a/src/core/services/utils/iframe.ts +++ b/src/core/services/utils/iframe.ts @@ -25,7 +25,7 @@ import { CoreTextUtils } from '@services/utils/text'; import { CoreUrlUtils } from '@services/utils/url'; import { CoreUtils, PromiseDefer } from '@services/utils/utils'; -import { makeSingleton, Network, Platform, NgZone, Translate, Diagnostic } from '@singletons'; +import { makeSingleton, Network, NgZone, Translate, Diagnostic } from '@singletons'; import { CoreLogger } from '@singletons/logger'; import { CoreUrl } from '@singletons/url'; import { CoreWindow } from '@singletons/window'; @@ -52,11 +52,6 @@ export class CoreIframeUtilsProvider { constructor() { this.logger = CoreLogger.getInstance('CoreUtilsProvider'); - - if (CoreApp.isIOS() && 'WKUserScript' in window) { - // eslint-disable-next-line promise/catch-or-return - Platform.ready().then(() => this.injectiOSScripts(window)); - } } /** @@ -558,7 +553,7 @@ export class CoreIframeUtilsProvider { * * @param userScriptWindow Window. */ - private injectiOSScripts(userScriptWindow: WKUserScriptWindow) { + injectiOSScripts(userScriptWindow: WKUserScriptWindow): void { const wwwPath = CoreFile.getWWWAbsolutePath(); const linksPath = CoreTextUtils.concatenatePaths(wwwPath, 'assets/js/iframe-treat-links.js'); diff --git a/src/core/services/utils/utils.ts b/src/core/services/utils/utils.ts index 6c5ca7826..2acf447f2 100644 --- a/src/core/services/utils/utils.ts +++ b/src/core/services/utils/utils.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Injectable, NgZone } from '@angular/core'; +import { Injectable } from '@angular/core'; import { InAppBrowserObject, InAppBrowserOptions } from '@ionic-native/in-app-browser'; import { FileEntry } from '@ionic-native/file/ngx'; import { Subscription } from 'rxjs'; @@ -26,7 +26,7 @@ import { CoreDomUtils } from '@services/utils/dom'; import { CoreMimetypeUtils } from '@services/utils/mimetype'; import { CoreTextUtils } from '@services/utils/text'; import { CoreWSError } from '@classes/errors/wserror'; -import { makeSingleton, Clipboard, InAppBrowser, FileOpener, WebIntent, QRScanner, Translate } from '@singletons'; +import { makeSingleton, Clipboard, InAppBrowser, FileOpener, WebIntent, QRScanner, Translate, NgZone } from '@singletons'; import { CoreLogger } from '@singletons/logger'; import { CoreFileSizeSum } from '@services/plugin-file-delegate'; import { CoreViewerQRScannerComponent } from '@features/viewer/components/qr-scanner/qr-scanner'; @@ -49,7 +49,7 @@ export class CoreUtilsProvider { protected uniqueIds: {[name: string]: number} = {}; protected qrScanData?: {deferred: PromiseDefer; observable: Subscription}; - constructor(protected zone: NgZone) { + constructor() { this.logger = CoreLogger.getInstance('CoreUtilsProvider'); } @@ -1005,7 +1005,7 @@ export class CoreUtilsProvider { // Trigger global events when a url is loaded or the window is closed. This is to make it work like in Ionic 1. const loadStartSubscription = this.iabInstance.on('loadstart').subscribe((event) => { // Execute the callback in the Angular zone, so change detection doesn't stop working. - this.zone.run(() => { + NgZone.run(() => { // Store the last loaded URLs (max 10). loadStartUrls.push(event.url); if (loadStartUrls.length > 10) { @@ -1020,7 +1020,7 @@ export class CoreUtilsProvider { // Load stop is needed with InAppBrowser v3. Custom URL schemes no longer trigger load start, simulate it. loadStopSubscription = this.iabInstance.on('loadstop').subscribe((event) => { // Execute the callback in the Angular zone, so change detection doesn't stop working. - this.zone.run(() => { + NgZone.run(() => { if (loadStartUrls.indexOf(event.url) == -1) { // The URL was stopped but not started, probably a custom URL scheme. CoreEvents.trigger(CoreEvents.IAB_LOAD_START, event); @@ -1031,7 +1031,7 @@ export class CoreUtilsProvider { const exitSubscription = this.iabInstance.on('exit').subscribe((event) => { // Execute the callback in the Angular zone, so change detection doesn't stop working. - this.zone.run(() => { + NgZone.run(() => { loadStartSubscription.unsubscribe(); loadStopSubscription && loadStopSubscription.unsubscribe(); exitSubscription.unsubscribe(); diff --git a/src/core/singletons/index.ts b/src/core/singletons/index.ts index d22a26290..deee2a2be 100644 --- a/src/core/singletons/index.ts +++ b/src/core/singletons/index.ts @@ -73,8 +73,9 @@ let createSingletonMethodProxy = (instance: any, method: Function, property: str * * @see makeSingleton */ -export type CoreSingletonProxy = Service & { +export type CoreSingletonProxy = Service & { instance: Service; + injectionToken: Type | AbstractType | Type | string; setInstance(instance: Service): void; }; @@ -113,13 +114,14 @@ export function makeSingleton( // eslint-disabl injectionToken: Type | AbstractType | Type | string, ): CoreSingletonProxy { const singleton = { + injectionToken, setInstance(instance: Service) { Object.defineProperty(singleton, 'instance', { value: instance, configurable: true, }); }, - } as { instance: Service; setInstance(instance: Service) }; + } as Pick, 'injectionToken' | 'instance' | 'setInstance'>; Object.defineProperty(singleton, 'instance', { get: () => { diff --git a/src/testing/setup.ts b/src/testing/setup.ts index 6bffcfaca..b988506bb 100644 --- a/src/testing/setup.ts +++ b/src/testing/setup.ts @@ -14,7 +14,9 @@ import 'jest-preset-angular'; -import { setCreateSingletonMethodProxy } from '@singletons'; +import { setCreateSingletonMethodProxy, setSingletonsInjector } from '@singletons'; + +import { resetTestingEnvironment, getServiceInstance } from './utils'; // eslint-disable-next-line no-console console.debug = () => { @@ -22,7 +24,7 @@ console.debug = () => { }; // eslint-disable-next-line no-console, jest/no-jasmine-globals, @typescript-eslint/no-explicit-any -console.error = (...args: any[]) => fail(args.map(a => a.toString()).join('')); +console.error = (...args: any[]) => fail(args.map(a => String(a)).join('')); // eslint-disable-next-line jest/no-jasmine-globals process.on('unhandledRejection', error => fail(error)); @@ -35,3 +37,6 @@ setCreateSingletonMethodProxy( instance[`mock_${String(property)}`] ?? jest.fn((...args) => method.call(instance, ...args)), ); + +setSingletonsInjector({ get: injectionToken => getServiceInstance(injectionToken) }); +beforeEach(() => resetTestingEnvironment()); diff --git a/src/testing/stubs/directives/core-external-content.ts b/src/testing/stubs/directives/core-external-content.ts new file mode 100644 index 000000000..c929bd2b4 --- /dev/null +++ b/src/testing/stubs/directives/core-external-content.ts @@ -0,0 +1,24 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Directive, Input } from '@angular/core'; + +@Directive({ + selector: '[core-external-content]', +}) +export class CoreExternalContentDirectiveStub { // eslint-disable-line @angular-eslint/directive-class-suffix + + @Input() siteId?: string; + +} diff --git a/src/testing/stubs/pipes/translate.ts b/src/testing/stubs/pipes/translate.ts new file mode 100644 index 000000000..093693b91 --- /dev/null +++ b/src/testing/stubs/pipes/translate.ts @@ -0,0 +1,26 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'translate', +}) +export class TranslatePipeStub implements PipeTransform { + + transform(text: string): string { + return text; + } + +} diff --git a/src/testing/utils.ts b/src/testing/utils.ts index 0bb4e7fff..a6ec2613b 100644 --- a/src/testing/utils.ts +++ b/src/testing/utils.ts @@ -12,10 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, CUSTOM_ELEMENTS_SCHEMA, Type, ViewChild } from '@angular/core'; +import { AbstractType, Component, CUSTOM_ELEMENTS_SCHEMA, Type, ViewChild } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { Observable, Subject } from 'rxjs'; -import { CoreSingletonProxy } from '@singletons'; +import { CORE_SITE_SCHEMAS } from '@services/sites'; +import { CoreSingletonProxy, Network, Platform } from '@singletons'; +import { CoreTextUtilsProvider } from '@services/utils/text'; + +import { TranslatePipeStub } from './stubs/pipes/translate'; +import { CoreExternalContentDirectiveStub } from './stubs/directives/core-external-content'; abstract class WrapperComponent { @@ -23,6 +30,95 @@ abstract class WrapperComponent { }; +type ServiceInjectionToken = AbstractType | Type | string; + +let testBedInitialized = false; +const textUtils = new CoreTextUtilsProvider(); +const DEFAULT_SERVICE_SINGLETON_MOCKS: [CoreSingletonProxy, Record][] = [ + [Platform, mock({ is: () => false, ready: () => Promise.resolve(), resume: new Subject() })], + [Network, { onChange: () => new Observable() }], +]; + +async function renderAngularComponent(component: Type, config: RenderConfig): Promise> { + config.declarations.push(component); + + TestBed.configureTestingModule({ + declarations: [ + ...getDefaultDeclarations(), + ...config.declarations, + ], + providers: [ + ...getDefaultProviders(), + ...config.providers, + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + imports: [BrowserModule], + }); + + testBedInitialized = true; + + await TestBed.compileComponents(); + + const fixture = TestBed.createComponent(component); + + fixture.autoDetectChanges(true); + + await fixture.whenRenderingDone(); + await fixture.whenStable(); + + return fixture; +} + +function createWrapperComponent(template: string, componentClass: Type): Type> { + @Component({ template }) + class HostComponent extends WrapperComponent { + + @ViewChild(componentClass) child!: U; + + } + + return HostComponent; +} + +function getDefaultDeclarations(): unknown[] { + return [ + TranslatePipeStub, + CoreExternalContentDirectiveStub, + ]; +} + +function getDefaultProviders(): unknown[] { + const serviceProviders = DEFAULT_SERVICE_SINGLETON_MOCKS.map( + ([singleton, mockInstance]) => ({ + provide: singleton.injectionToken, + useValue: mockInstance, + }), + ); + + return [ + ...serviceProviders, + { provide: CORE_SITE_SCHEMAS, multiple: true, useValue: [] }, + ]; +} + +function resolveServiceInstanceFromTestBed(injectionToken: Exclude): Record | null { + if (!testBedInitialized) { + return null; + } + + return TestBed.inject(injectionToken) as Record | null; +} + +function createNewServiceInstance(injectionToken: Exclude): Record | null { + try { + const constructor = injectionToken as { new (): Record }; + + return new constructor(); + } catch (e) { + return null; + } +} + export interface RenderConfig { declarations: unknown[]; providers: unknown[]; @@ -66,19 +162,40 @@ export function mockSingleton( ): T; export function mockSingleton( singleton: CoreSingletonProxy, - methodsOrInstance: string[] | Record = [], - instance: Record = {}, + methodsOrProperties: string[] | Record = [], + properties: Record = {}, ): T { - instance = Array.isArray(methodsOrInstance) ? instance : methodsOrInstance; + properties = Array.isArray(methodsOrProperties) ? properties : methodsOrProperties; - const methods = Array.isArray(methodsOrInstance) ? methodsOrInstance : []; + const methods = Array.isArray(methodsOrProperties) ? methodsOrProperties : []; + const instance = getServiceInstance(singleton.injectionToken); const mockInstance = mock(methods, instance); + Object.assign(mockInstance, properties); + singleton.setInstance(mockInstance); return mockInstance; } +export function resetTestingEnvironment(): void { + testBedInitialized = false; + + for (const [singleton, mockInstance] of DEFAULT_SERVICE_SINGLETON_MOCKS) { + mockSingleton(singleton, mockInstance); + } +} + +export function getServiceInstance(injectionToken: ServiceInjectionToken): Record { + if (typeof injectionToken === 'string') { + return {}; + } + + return resolveServiceInstanceFromTestBed(injectionToken) + ?? createNewServiceInstance(injectionToken) + ?? {}; +} + export async function renderComponent(component: Type, config: Partial = {}): Promise> { return renderAngularComponent(component, { declarations: [], @@ -108,45 +225,13 @@ export async function renderTemplate( export async function renderWrapperComponent( component: Type, tag: string, - inputs: Record = {}, + inputs: Record = {}, config: Partial = {}, ): Promise> { const inputAttributes = Object .entries(inputs) - .map(([name, value]) => `${name}="${value.toString().replace(/"/g, '"')}"`) + .map(([name, value]) => `[${name}]="${textUtils.escapeHTML(JSON.stringify(value)).replace(/\//g, '\\/')}"`) .join(' '); return renderTemplate(component, `<${tag} ${inputAttributes}>`, config); } - -async function renderAngularComponent(component: Type, config: RenderConfig): Promise> { - config.declarations.push(component); - - TestBed.configureTestingModule({ - declarations: config.declarations, - schemas: [CUSTOM_ELEMENTS_SCHEMA], - providers: config.providers, - }); - - await TestBed.compileComponents(); - - const fixture = TestBed.createComponent(component); - - fixture.autoDetectChanges(true); - - await fixture.whenRenderingDone(); - await fixture.whenStable(); - - return fixture; -} - -function createWrapperComponent(template: string, componentClass: Type): Type> { - @Component({ template }) - class HostComponent extends WrapperComponent { - - @ViewChild(componentClass) child!: U; - - } - - return HostComponent; -}