commit
d2fa4e6382
|
@ -1,4 +1,4 @@
|
||||||
const { pathsToModuleNameMapper } = require('ts-jest/utils');
|
const { pathsToModuleNameMapper } = require('ts-jest');
|
||||||
const { compilerOptions } = require('./tsconfig');
|
const { compilerOptions } = require('./tsconfig');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
@ -9,17 +9,9 @@ module.exports = {
|
||||||
'src/**/*.{ts,html}',
|
'src/**/*.{ts,html}',
|
||||||
'!src/testing/**/*',
|
'!src/testing/**/*',
|
||||||
],
|
],
|
||||||
transform: {
|
transformIgnorePatterns: ['node_modules/(?!@stencil|@angular|@ionic|@moodlehq|@ngx-translate|swiper)'],
|
||||||
'^.+\\.(ts|html)$': 'ts-jest',
|
|
||||||
},
|
|
||||||
transformIgnorePatterns: ['node_modules/(?!@awesome-cordova-plugins|@ionic/core|@stencil/core|ionicons|@moodlehq/ionic-native-push)'],
|
|
||||||
moduleNameMapper: {
|
moduleNameMapper: {
|
||||||
...pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/src/' }),
|
...pathsToModuleNameMapper(compilerOptions.paths, { prefix: '<rootDir>/src/' }),
|
||||||
'^!raw-loader!.*': 'jest-raw-loader',
|
'^!raw-loader!.*': 'jest-raw-loader',
|
||||||
},
|
},
|
||||||
globals: {
|
|
||||||
'ts-jest': {
|
|
||||||
tsconfig: './tsconfig.test.json',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -175,11 +175,14 @@
|
||||||
"gulp-rename": "^2.0.0",
|
"gulp-rename": "^2.0.0",
|
||||||
"gulp-slash": "^1.1.3",
|
"gulp-slash": "^1.1.3",
|
||||||
"jest": "^29.7.0",
|
"jest": "^29.7.0",
|
||||||
|
"jest-preset-angular": "^13.1.4",
|
||||||
|
"jest-raw-loader": "^1.0.1",
|
||||||
"jsonc-parser": "^2.3.1",
|
"jsonc-parser": "^2.3.1",
|
||||||
"keytar": "^7.2.0",
|
"keytar": "^7.2.0",
|
||||||
"minimatch": "^5.1.0",
|
"minimatch": "^5.1.0",
|
||||||
"native-run": "^2.0.0",
|
"native-run": "^2.0.0",
|
||||||
"patch-package": "^6.5.0",
|
"patch-package": "^6.5.0",
|
||||||
|
"ts-jest": "^29.1.1",
|
||||||
"ts-node": "^8.3.0",
|
"ts-node": "^8.3.0",
|
||||||
"typescript": "~5.1.3"
|
"typescript": "~5.1.3"
|
||||||
},
|
},
|
||||||
|
|
|
@ -12,8 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Route } from '@angular/compiler/src/core';
|
import { Route, UrlSegment, UrlSegmentGroup } from '@angular/router';
|
||||||
import { UrlSegment, UrlSegmentGroup } from '@angular/router';
|
|
||||||
|
|
||||||
import { mock } from '@/testing/utils';
|
import { mock } from '@/testing/utils';
|
||||||
|
|
||||||
|
|
|
@ -125,7 +125,7 @@ export class CoreDatabaseTable<
|
||||||
}
|
}
|
||||||
|
|
||||||
const sorting = options?.sorting
|
const sorting = options?.sorting
|
||||||
&& this.normalizedSorting(options.sorting).map(([column, direction]) => `${column} ${direction}`).join(', ');
|
&& this.normalizedSorting(options.sorting).map(([column, direction]) => `${column.toString()} ${direction}`).join(', ');
|
||||||
|
|
||||||
return this.database.getRecords(this.tableName, conditions, sorting, '*', options?.offset, options?.limit);
|
return this.database.getRecords(this.tableName, conditions, sorting, '*', options?.offset, options?.limit);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ export abstract class CorePromise<T = unknown> implements Promise<T> {
|
||||||
this.nativePromise = nativePromise;
|
this.nativePromise = nativePromise;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Symbol.toStringTag]: string;
|
[Symbol.toStringTag]!: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
|
|
|
@ -238,11 +238,11 @@ export class CoreCourseProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
const course = await CoreCourses.getCourseByField('id', courseId, site.id);
|
const course = await CoreCourses.getCourseByField('id', courseId, site.id);
|
||||||
const formatOptions = CoreUtils.objectToKeyValueMap<{ indentation?: string }>(
|
const formatOptions = CoreUtils.objectToKeyValueMap(
|
||||||
course.courseformatoptions ?? [],
|
course.courseformatoptions ?? [],
|
||||||
'name',
|
'name',
|
||||||
'value',
|
'value',
|
||||||
);
|
) as { indentation?: string };
|
||||||
|
|
||||||
return formatOptions.indentation === '1';
|
return formatOptions.indentation === '1';
|
||||||
}
|
}
|
||||||
|
|
|
@ -275,7 +275,7 @@ export class CoreCourseFormatDelegateService extends CoreDelegate<CoreCourseForm
|
||||||
[course, sections],
|
[course, sections],
|
||||||
);
|
);
|
||||||
|
|
||||||
if (sectionData && 'forceSelected' in sectionData) {
|
if (sectionData && typeof sectionData === 'object' && 'forceSelected' in sectionData) {
|
||||||
return sectionData;
|
return sectionData;
|
||||||
} else if (sectionData) {
|
} else if (sectionData) {
|
||||||
// Function just returned the section, don't force selecting it.
|
// Function just returned the section, don't force selecting it.
|
||||||
|
|
|
@ -636,7 +636,10 @@ export class CoreCoursesProvider {
|
||||||
ignoreErrors(this.getUserNavigationOptionsObservable(courseIds, options), {}),
|
ignoreErrors(this.getUserNavigationOptionsObservable(courseIds, options), {}),
|
||||||
ignoreErrors(this.getUserAdministrationOptionsObservable(courseIds, options), {}),
|
ignoreErrors(this.getUserAdministrationOptionsObservable(courseIds, options), {}),
|
||||||
).pipe(
|
).pipe(
|
||||||
map(([navOptions, admOptions]) => ({ navOptions, admOptions })),
|
map(([navOptions, admOptions]) => ({
|
||||||
|
navOptions: navOptions as CoreCourseUserAdminOrNavOptionCourseIndexed,
|
||||||
|
admOptions: admOptions as CoreCourseUserAdminOrNavOptionCourseIndexed,
|
||||||
|
})),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -933,7 +933,8 @@ export class CoreFileProvider {
|
||||||
// If destFolder is not set, use same location as ZIP file. We need to use absolute paths (including basePath).
|
// If destFolder is not set, use same location as ZIP file. We need to use absolute paths (including basePath).
|
||||||
destFolder = this.addBasePathIfNeeded(destFolder || CoreMimetypeUtils.removeExtension(path));
|
destFolder = this.addBasePathIfNeeded(destFolder || CoreMimetypeUtils.removeExtension(path));
|
||||||
|
|
||||||
const result = await Zip.unzip(fileEntry.toURL(), destFolder, onProgress);
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
|
const result = await Zip.unzip(fileEntry.toURL(), destFolder, onProgress as unknown as Function);
|
||||||
|
|
||||||
if (result == -1) {
|
if (result == -1) {
|
||||||
throw new CoreError('Unzip failed.');
|
throw new CoreError('Unzip failed.');
|
||||||
|
|
|
@ -136,7 +136,7 @@ export class CoreNavigatorService {
|
||||||
animated: options.animated,
|
animated: options.animated,
|
||||||
animation: options.animation,
|
animation: options.animation,
|
||||||
animationDirection: options.animationDirection,
|
animationDirection: options.animationDirection,
|
||||||
queryParams: CoreObject.isEmpty(options.params ?? {}) ? null : CoreObject.withoutEmpty(options.params),
|
queryParams: CoreObject.isEmpty(options.params ?? {}) ? null : CoreObject.withoutEmpty(options.params ?? {}),
|
||||||
relativeTo: path.startsWith('/') ? null : this.getCurrentRoute(),
|
relativeTo: path.startsWith('/') ? null : this.getCurrentRoute(),
|
||||||
replaceUrl: options.replace,
|
replaceUrl: options.replace,
|
||||||
});
|
});
|
||||||
|
|
|
@ -1405,7 +1405,7 @@ export class CoreUtilsProvider {
|
||||||
* @param enumeration Enumeration object.
|
* @param enumeration Enumeration object.
|
||||||
* @returns Keys of the enumeration.
|
* @returns Keys of the enumeration.
|
||||||
*/
|
*/
|
||||||
enumKeys<O, K extends keyof O = keyof O>(enumeration: O): K[] {
|
enumKeys<O extends object, K extends keyof O = keyof O>(enumeration: O): K[] {
|
||||||
return Object.keys(enumeration).filter(k => Number.isNaN(+k)) as K[];
|
return Object.keys(enumeration).filter(k => Number.isNaN(+k)) as K[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,7 @@ export function setCreateSingletonMethodProxy(method: typeof createSingletonMeth
|
||||||
* defined using a class or the string used in the `provide` key if it was defined using an object.
|
* defined using a class or the string used in the `provide` key if it was defined using an object.
|
||||||
* @returns Singleton proxy.
|
* @returns Singleton proxy.
|
||||||
*/
|
*/
|
||||||
export function makeSingleton<Service extends object = object>( // eslint-disable-line @typescript-eslint/ban-types
|
export function makeSingleton<Service extends object = object>(
|
||||||
injectionToken: Type<Service> | AbstractType<Service> | Type<unknown> | string,
|
injectionToken: Type<Service> | AbstractType<Service> | Type<unknown> | string,
|
||||||
): CoreSingletonProxy<Service> {
|
): CoreSingletonProxy<Service> {
|
||||||
const singleton = {
|
const singleton = {
|
||||||
|
|
|
@ -66,7 +66,7 @@ function expectBool (str) {
|
||||||
throw SyntaxError('Invalid bool value, expected 0 or 1')
|
throw SyntaxError('Invalid bool value, expected 0 or 1')
|
||||||
}
|
}
|
||||||
|
|
||||||
return [ boolMatch === '1', match.length ]
|
return [ boolMatch === '1', match?.length ]
|
||||||
}
|
}
|
||||||
|
|
||||||
function expectInt (str) {
|
function expectInt (str) {
|
||||||
|
@ -77,7 +77,7 @@ function expectInt (str) {
|
||||||
throw SyntaxError('Expected an integer value')
|
throw SyntaxError('Expected an integer value')
|
||||||
}
|
}
|
||||||
|
|
||||||
return [ parseInt(intMatch, 10), match.length ]
|
return [ parseInt(intMatch, 10), match?.length ]
|
||||||
}
|
}
|
||||||
|
|
||||||
function expectFloat (str) {
|
function expectFloat (str) {
|
||||||
|
@ -105,7 +105,7 @@ function expectFloat (str) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
return [ floatValue, match.length ]
|
return [ floatValue, match?.length ]
|
||||||
}
|
}
|
||||||
|
|
||||||
function readBytes (str, len, escapedString = false) {
|
function readBytes (str, len, escapedString = false) {
|
||||||
|
@ -260,8 +260,10 @@ function expectObject (str, cache) {
|
||||||
str = str.substring(value[1])
|
str = str.substring(value[1])
|
||||||
totalOffset += value[1]
|
totalOffset += value[1]
|
||||||
|
|
||||||
|
if (prop[0]) {
|
||||||
obj[prop[0]] = value[0]
|
obj[prop[0]] = value[0]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// strict parsing, expect } after object literal
|
// strict parsing, expect } after object literal
|
||||||
if (str.charAt(0) !== '}') {
|
if (str.charAt(0) !== '}') {
|
||||||
|
@ -299,7 +301,7 @@ function expectArray (str, cache) {
|
||||||
throw SyntaxError('Expected array length annotation')
|
throw SyntaxError('Expected array length annotation')
|
||||||
}
|
}
|
||||||
|
|
||||||
str = str.substring(arrayLiteralBeginMatch.length)
|
str = str.substring(arrayLiteralBeginMatch?.length)
|
||||||
|
|
||||||
const array = expectArrayItems(str, parseInt(arrayLengthMatch, 10), cache)
|
const array = expectArrayItems(str, parseInt(arrayLengthMatch, 10), cache)
|
||||||
|
|
||||||
|
@ -308,7 +310,7 @@ function expectArray (str, cache) {
|
||||||
throw SyntaxError('Expected }')
|
throw SyntaxError('Expected }')
|
||||||
}
|
}
|
||||||
|
|
||||||
return [ array[0], arrayLiteralBeginMatch.length + (array[1] as number) + 1 ] // jump over }
|
return [ array[0], arrayLiteralBeginMatch?.length ?? 0 + (array[1] as number) + 1 ] // jump over }
|
||||||
}
|
}
|
||||||
|
|
||||||
function expectArrayItems (str, expectedItems = 0, cache) {
|
function expectArrayItems (str, expectedItems = 0, cache) {
|
||||||
|
|
|
@ -91,9 +91,9 @@ export class CoreObject {
|
||||||
* @param keysOrRegex If array is supplied, keys to include. Otherwise, regular expression used to filter keys.
|
* @param keysOrRegex If array is supplied, keys to include. Otherwise, regular expression used to filter keys.
|
||||||
* @returns New object with only the specified keys.
|
* @returns New object with only the specified keys.
|
||||||
*/
|
*/
|
||||||
static only<T, K extends keyof T>(obj: T, keys: K[]): Pick<T, K>;
|
static only<T extends object, K extends keyof T>(obj: T, keys: K[]): Pick<T, K>;
|
||||||
static only<T>(obj: T, regex: RegExp): Partial<T>;
|
static only<T extends object>(obj: T, regex: RegExp): Partial<T>;
|
||||||
static only<T, K extends keyof T>(obj: T, keysOrRegex: K[] | RegExp): Pick<T, K> | Partial<T> {
|
static only<T extends object, K extends keyof T>(obj: T, keysOrRegex: K[] | RegExp): Pick<T, K> | Partial<T> {
|
||||||
const newObject: Partial<T> = {};
|
const newObject: Partial<T> = {};
|
||||||
|
|
||||||
if (Array.isArray(keysOrRegex)) {
|
if (Array.isArray(keysOrRegex)) {
|
||||||
|
@ -136,7 +136,7 @@ export class CoreObject {
|
||||||
* @param obj Objet.
|
* @param obj Objet.
|
||||||
* @returns New object without empty values.
|
* @returns New object without empty values.
|
||||||
*/
|
*/
|
||||||
static withoutEmpty<T>(obj: T): CoreObjectWithoutEmpty<T> {
|
static withoutEmpty<T extends object>(obj: T): CoreObjectWithoutEmpty<T> {
|
||||||
const cleanObj = {};
|
const cleanObj = {};
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(obj)) {
|
for (const [key, value] of Object.entries(obj)) {
|
||||||
|
@ -156,7 +156,7 @@ export class CoreObject {
|
||||||
* @param obj Objet.
|
* @param obj Objet.
|
||||||
* @returns New object without undefined values.
|
* @returns New object without undefined values.
|
||||||
*/
|
*/
|
||||||
static withoutUndefined<T>(obj: T): CoreObjectWithoutUndefined<T> {
|
static withoutUndefined<T extends object>(obj: T): CoreObjectWithoutUndefined<T> {
|
||||||
const cleanObj = {};
|
const cleanObj = {};
|
||||||
|
|
||||||
for (const [key, value] of Object.entries(obj)) {
|
for (const [key, value] of Object.entries(obj)) {
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
// (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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -22,16 +22,15 @@ import { CORE_SITE_SCHEMAS } from '@services/sites';
|
||||||
import { ApplicationInit, CoreSingletonProxy, Translate } from '@singletons';
|
import { ApplicationInit, CoreSingletonProxy, Translate } from '@singletons';
|
||||||
import { CoreTextUtilsProvider } from '@services/utils/text';
|
import { CoreTextUtilsProvider } from '@services/utils/text';
|
||||||
|
|
||||||
import { TranslatePipeStub } from './stubs/pipes/translate';
|
|
||||||
import { CoreExternalContentDirectiveStub } from './stubs/directives/core-external-content';
|
import { CoreExternalContentDirectiveStub } from './stubs/directives/core-external-content';
|
||||||
import { CoreNetwork } from '@services/network';
|
import { CoreNetwork } from '@services/network';
|
||||||
import { CorePlatform } from '@services/platform';
|
import { CorePlatform } from '@services/platform';
|
||||||
import { CoreDB } from '@services/db';
|
import { CoreDB } from '@services/db';
|
||||||
import { CoreNavigator, CoreNavigatorService } from '@services/navigator';
|
import { CoreNavigator, CoreNavigatorService } from '@services/navigator';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { TranslateService, TranslateStore } from '@ngx-translate/core';
|
import { TranslateModule, TranslateService, TranslateStore } from '@ngx-translate/core';
|
||||||
import { CoreIonLoadingElement } from '@classes/ion-loading';
|
import { CoreIonLoadingElement } from '@classes/ion-loading';
|
||||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
|
||||||
import { DefaultUrlSerializer, UrlSerializer } from '@angular/router';
|
import { DefaultUrlSerializer, UrlSerializer } from '@angular/router';
|
||||||
import { CoreUtils, CoreUtilsProvider } from '@services/utils/utils';
|
import { CoreUtils, CoreUtilsProvider } from '@services/utils/utils';
|
||||||
import { Equal } from '@/core/utils/types';
|
import { Equal } from '@/core/utils/types';
|
||||||
|
@ -102,7 +101,8 @@ async function renderAngularComponent<T>(component: Type<T>, config: RenderConfi
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
BrowserAnimationsModule,
|
NoopAnimationsModule,
|
||||||
|
TranslateModule.forChild(),
|
||||||
...config.imports,
|
...config.imports,
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
@ -146,7 +146,6 @@ function createWrapperComponent<U>(template: string, componentClass: Type<U>): T
|
||||||
*/
|
*/
|
||||||
function getDefaultDeclarations(): unknown[] {
|
function getDefaultDeclarations(): unknown[] {
|
||||||
return [
|
return [
|
||||||
TranslatePipeStub,
|
|
||||||
CoreExternalContentDirectiveStub,
|
CoreExternalContentDirectiveStub,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue